> I will put it in the distribution. I will call it vserver-copy.
Groovy....
> There is one issue. It did not work for me :-(
This is not so cool.
> You are using ssh to check if the target dhost/vserver is running
>
> but you are using rsync over rsh to perform the copy. On most machine
> rsh is not enabled/installed. So the copy failed without much explanation.
Did you try the -v flag? I only have ssh installed - no rsh. I am guessing
that perhaps rsync uses rsh by default, and checks for ssh only after the
first method fails. I now force rsync to use ssh when doing a network
copy, which you can change with the -R option.
The script will now either copy locally or to a remote host, with the
option of rewriting the vserver.conf and /etc/hosts files with a new
hostname and IP address.
> vserver takes some time when in fact, potentially most of it is already
> available. Using vfiles, you can get the list of all file different from
> a reference vserver (potentially different) and copy just that. Then on
> the target, you can re-unify.
> The vcp script would accept a -r argument, which is the reference vserver.
> The script would check that both the source and the target host have
> such a vserver and would use vfile at one end and vunify at the other
I like the idea, however vunify is very dependent upon the package
manager, yes? Or at least rpm. Is there a way to make that distribution
independent?
I don't know exactly how vunify works, but if you want to do the hard work
I'll integrate it with the rest of the options.
> Thanks!
You're welcome.
Hey Paul,
I don't know if it is intentional or not, but some of the directories and
files under your vserver web pages are not readable (vcp/vcp is one of
them, listen-with-no-bind is another...)
Cheers, Mark.
--
Mark Lawrence ([EMAIL PROTECTED]) Mobile: +41 79 309 0633
#!/bin/sh
#
# Copyright (C) 2002, Mark Lawrence <[EMAIL PROTECTED]>.
# Licence: GPL
#
# Copy/Sync a virtual host from one machine to another
version="0.2.0"
umask 022
me=${0##*/}
### Helper functions ###
# Save stdin and stdout for later use
exec 3>&1
exec 4>&2
noninteractive () {
exec > /dev/null
}
interactive () {
exec 1>&3
exec 2>&4
}
info () {
! $quiet && echo "I: $1" >&3
}
warn () {
echo "W: $1" >&4
}
error () {
echo "E: $2" >&4
exit $1
}
### Usage/Info functions ###
usage () {
cat <<EOF 1>&2
Usage: $me [-hVvqidrRs] vserver [host:]newname
EOF
}
full_usage () {
usage
cat <<EOF
$me uses rsync to make a copy of a vserver. If the destination
name contains a host specification the vserver will be synchronised to
the remote destination over ssh/rsh.
This can be used on a running vserver to make a warm backup. With the -s
flag a vserver can even be operationally moved to different hardware within
seconds.
The -i and -d flags can be used to minimally reconfigure the destination
vserver (overwrites /etc/vservers/newname.conf and /vservers/newname/etc/hosts)
Options:
-h, --help this help
-V, --version copyright and version information
-v, --verbose show all output
-q, --quiet direct all output to /dev/null (no password
prompt for logins on remote hosts!)
-d, --domain [string] new dns domain (must be used with -i)
-i, --ip [addr] new IP address (must be used with -d)
-r, --vsroot location of "/vserver/" directory
-R, --rsh use rsh (instead of default ssh) for
network transport
-s, --stopstart stop the local vserver before copying and start
it on the destination host afterwards
EOF
}
full_version () {
cat <<EOF
$me version $version
Copyright (c) 2002 Mark Lawrence <[EMAIL PROTECTED]>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
EOF
}
### Default values and Command line options ###
stopstart=(false)
verbose=(false)
quiet=(false)
ssh="ssh"
rsflag="-e"
rsh=(false)
colon=":"
domain=""
ip=""
vsroot="/vservers"
if [ $# -eq 0 ]; then # Script invoked with no command-line args?
usage
exit 1
fi
temp=$(getopt -o hVvqd:i:rRs --long
help,version,verbose,quiet,domain:,ip:,vsroot,rsh,stopstart, -n $me -- "$@")
if [ $? != 0 ]; then
echo " (See -h for help)"
exit 1
fi
# Note the quotes around `$temp': they are essential!
eval set -- "$temp"
while true; do
case "$1" in
-h|--help) full_usage
exit 1
;;
-V|--version) full_version
exit 1
;;
-v|--verbose) verbose=(true)
shift
;;
-q|--quiet) quiet=(true)
shift
;;
-d|--domain) domain="$2"
shift 2
;;
-i|--ip) ip="$2"
shift 2
;;
-r|--vsroot) vsroot="$2"
shift 2
;;
-R|--rsh) rsh=(true)
shift
;;
-s|--stopstart) stopstart=(true)
shift
;;
--) shift
break
;;
*) echo "Internal error!"
exit 1
;;
esac
done
if (($# != 2)); then
usage
exit 1
fi
### ###
# By default we are reasonably quiet (ouput only via info, warn & error)
if $verbose; then
interactive
else
noninteractive
fi
vserver=$1
vconf=/etc/vservers/$vserver.conf
vroot=$vsroot/$vserver
if $rsh; then
ssh="rsh"
fi
if (echo $2 | grep -q '^[a-z][a-z0-9]\+$'); then
dhost=""
newname=$2
ssh=""
rsflag=""
colon=""
if $rsh; then
warn "rsh is set but not used for a local copy"
fi
elif (echo $2 | grep -q '^[a-z][a-z0-9]\+:$'); then
dhost=${2/:/}
newname=$vserver
elif (echo $2 | grep -q '^[a-z][a-z0-9]\+:[a-z][a-z0-9]\+$'); then
dhost=${2/:*/}
newname=${2/*:/}
else
error 1 "Second argument must be of the form \"[host:]name\" or \"host:\""
fi
target=$vsroot/$newname
targetconf=/etc/vservers/$newname.conf
### Perform some sanity checks ###
if [ ! -d $vroot ]; then
error 1 "Directory \"$vroot\" does not exist"
fi
if [ ! -e $vconf ]; then
error 1 "Vserver file \"$vconf\" does not exist"
fi
if [ "$dhost" == "" ] && [ "$vserver" == "$newname" ]; then
error 1 "Source and destination names cannot be the same on the localhost"
fi
if [ "$dhost" != "" ] && ! (host $dhost | grep -q 'has address'); then
error 1 "$dhost does not resolve into an IP address"
fi
#if [ "$vserver" != "$newname" -a \( "$ip" == "" -o "$domain" == "" \) ]; then
if [ \( "$ip" != "" -a "$domain" == "" \) -o \
\( "$ip" == "" -a "$domain" != "" \) ]
then
error 1 "Both IP address and domain must be specified together"
fi
if [ "$ip" != "" ] && \
! (echo $ip | grep -q '^[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}$' ); then
error 1 "\"$ip\" is not a valid IP address"
fi
# This works both locally and remote
if ($ssh $dhost /usr/sbin/vserver $newname running | grep -q 'is running'); then
warn "destination vserver \"$newname\" is running"
error 1 "Cannot copy over a running vserver"
fi
### Do the copy ###
if $stopstart; then
info "Stopping virtual server \"$vserver\" on localhost"
/usr/sbin/vserver $vserver stop
fi
info "Syncing directories"
# trailing slashes very important in the rsync!
if ! rsync -avxz $rsflag $ssh $vroot/ $dhost$colon$target/; then
error $? "vserver copy failed"
fi
if [ "$ip" != "" -a "$domain" != "" ]; then
# Insert the new IPROOT/S_HOSTNAME values into the config file
info "Modifying $targetconf"
tmpf=$(tempfile)
if (sed -e "s/^S_HOSTNAME=.*/S_HOSTNAME=\"$newname\"/" \
-e "s/^IPROOT=.*/IPROOT=\"$ip\"/" $vconf > $tmpf)
then
if ! rsync -v $rsflag $ssh $tmpf $dhost$colon$targetconf; then
error $? "vserver config file copy/change failed"
fi
else
warn "Unable to reconfigure virtual server config file"
fi
# create a new /etc/hostname
info "Creating hostname file"
echo $newname > $tmpf
if ! rsync -v $rsflag $ssh $tmpf $dhost$colon$target/etc/hostname; then
error $? "vserver /etc/hostname copy failed"
fi
info "Creating /etc/hosts"
cat << EOF > $tmpf
# /etc/hosts (automatically generated by $me)
127.0.0.1 localhost
$ip $newname.$domain $newname
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts
EOF
# copy /etc/hosts
if ! rsync -v $rsflag $ssh $tmpf $dhost$colon$target/etc/hosts; then
error $? "vserver /etc/hosts copy failed"
fi
rm -f $tmpf
else
# copy newname.conf unchanged
info "Copying $targetconf"
if ! rsync -v $rsflag $ssh $vconf $dhost$colon$targetconf; then
error $? "vserver config file copy/change failed"
fi
fi
if $stopstart; then
info "Starting virtual server \"$vserver\" on $dhost"
$ssh $dhost /usr/sbin/vserver $vserver start
if ($ssh $dhost /usr/sbin/vserver $vserver running | \
grep -q 'not running'); then
error 1 "Virtual server \"$vserver\" failed to start on $dhost"
fi
fi
exit 0