util-vserver-0.30.208
[util-vserver.git] / scripts / legacy / vserver-copy
diff --git a/scripts/legacy/vserver-copy b/scripts/legacy/vserver-copy
new file mode 100755 (executable)
index 0000000..d7b968f
--- /dev/null
@@ -0,0 +1,380 @@
+#!/bin/bash
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vserver-copy by Mark Lawrence <nomad@null.net>
+#  
+# 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, or (at your option)
+# any later version.
+#  
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#  
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Copy/Sync a virtual host from one machine to another
+#
+# History:
+#
+# 2003-04-04: Version 0.4 - Mark lawrence
+# - Set "ONBOOT=no" in the destination .conf file when --startstop
+#   is not used, in case the destination roothost reboots. We don't
+#   want two copies of a vserver running at the same time.
+#
+# 2003-03-04: Version 0.3 - Mark lawrence
+# - Changed all checks for [ "" != "$var" ] into [ -n|-z "$var" ]. "" doesn't
+#   seem to work for bash on the Sparc architecture.
+# - Changed $ssh variable into $shcmd.
+#
+# 2003-02-23: Version 0.2 - Mark Lawrence
+# - Set ONBOOT to "no" in the original .conf file when the "-s" flag is 
+#   used so that if/when you reboot the source roothost you don't have the
+#   same vserver and IP address running on two machines.
+
+: ${UTIL_VSERVER_VARS:=/usr/lib/util-vserver/util-vserver-vars}
+test -e "$UTIL_VSERVER_VARS" || {
+    echo $"Can not find util-vserver installation (the file '$UTIL_VSERVER_VARS' would be expected); aborting..." >&2
+    exit 1
+}
+. "$UTIL_VSERVER_VARS"
+
+VERSION="0.4"
+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: $me: $1" >&3
+}
+
+warn () {
+       ! $quiet && echo "W: $me: $1" >&4
+}
+
+error () {
+       ! $quiet && echo "E: $me: $2" >&4
+       exit $1
+}
+
+
+### Usage/Info functions ###
+
+usage () {
+    cat <<EOF 1>&2
+Usage: $me [-hVvqidrRs] vserver newname
+       $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 (rewrites /etc/vservers/newname.conf and $__DEFAULT_VSERVERDIR/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   <nomad@null.net>
+
+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)
+shcmd="ssh"
+rsflag="-e"
+rsh=(false)
+colon=":"
+domain=""
+ip=""
+vsroot=$__DEFAULT_VSERVERDIR
+
+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 [ $? -ne 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 [ $# -ne 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
+
+now=$(date)
+info "called on $(hostname) at $now"
+
+
+vserver=$1
+vconf=/etc/vservers/$vserver.conf
+vroot=$vsroot/$vserver
+
+if $rsh; then
+       shcmd="rsh"
+fi
+
+if (echo $2 | grep '^[a-z][a-z0-9]\+$'); then
+       dhost=""
+       newname=$2
+       shcmd=""
+       rsflag=""
+       colon=""
+       if $rsh; then
+               warn "rsh is set but not used for a local copy"
+       fi
+elif (echo $2 | grep '^[a-z].*[a-z0-9]:$'); then
+       dhost=${2/:/}
+       newname=$vserver
+elif (echo $2 | grep '^[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 [ -z "$dhost" ] && [ "$vserver" == "$newname" ]; then
+       error 1 "Source and destination names cannot be the same on the localhost"
+fi
+
+if [ -n "$dhost" ] && ! (host $dhost | grep 'has address'); then
+       warn "$dhost does not resolve into an IP address"
+fi
+
+if [ \( -n "$ip" -a -z "$domain" \) -o \
+     \( -z "$ip" -a -n "$domain" \) ]
+then
+       error 1 "Both IP address and domain must be specified together"
+fi
+
+if [ -n "$ip" ] && \
+! (echo $ip | grep '^[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 ($shcmd $dhost $__SBINDIR/vserver $newname running | grep 'is running'); then
+       warn "destination vserver \"$newname\" is running" 
+       error 1 "Cannot copy over a running vserver"
+fi
+
+
+### Do the copy ###
+
+info "Attempting to copy $vserver to $dhost$colon$newname"
+
+if $stopstart; then
+       info "Stopping virtual server \"$vserver\" on localhost"
+       $__SBINDIR/vserver $vserver stop
+fi
+
+info "Syncing directories"
+# trailing slashes very important in the rsync!
+if ! rsync -avxz $rsflag $shcmd $vroot/ $dhost$colon$target/; then
+       error 1 "rsync failed"
+fi
+
+if [ -n "$ip" -a -n "$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 $shcmd $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 $shcmd $tmpf $dhost$colon$target/etc/hostname; then
+               error 1 "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 $shcmd $tmpf $dhost$colon$target/etc/hosts; then
+               error 1 "vserver /etc/hosts copy failed"
+       fi
+       rm -f $tmpf
+
+else
+       if ! $stopstart; then
+               # Make sure that this vserver doesn't start on the 
+               # destination host if it reboots
+               tmpf=$(tempfile)
+               sed -e 's/^ONBOOT=.*/ONBOOT=no/' $vconf > $tmpf
+               vconf=$tmpf
+       fi
+
+       # copy newname.conf unchanged
+       info "Copying $targetconf"
+       if ! rsync -v $rsflag $shcmd $vconf $dhost$colon$targetconf; then
+               error 1 "vserver config file copy/change failed"
+       fi
+
+       rm -f $tmpf
+fi
+
+
+if $stopstart; then
+       info "Starting virtual server \"$vserver\" on $dhost"
+       $shcmd $dhost $__SBINDIR/vserver $vserver start
+       if ($shcmd $dhost $__SBINDIR/vserver $vserver running | \
+       grep 'not running'); then
+               error 1 "Virtual server \"$vserver\" failed to start on $dhost"
+       fi
+
+       # Make sure that we don't start the original on next boot
+       tmpf=$(tempfile)
+       sed -e 's/^ONBOOT=.*/ONBOOT=no/' $vconf > $tmpf
+       mv $tmpf $vconf
+fi
+
+exit 0