aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUbuntu <ubuntu@server-4676.novalocal>2012-02-09 18:38:21 +0000
committerDaniel Lezcano <daniel.lezcano@free.fr>2012-02-26 10:44:41 +0100
commit5d325fcf7e5adcf003ae34bcc492e64a6c8315a0 (patch)
treebbd7e2a2c3638a77dc221bc500f356fcc67664da
parentadd btrfs support to lxc-create (diff)
downloadlxc-5d325fcf7e5adcf003ae34bcc492e64a6c8315a0.tar.gz
lxc-5d325fcf7e5adcf003ae34bcc492e64a6c8315a0.tar.bz2
lxc-5d325fcf7e5adcf003ae34bcc492e64a6c8315a0.zip
lxc-clone: support btrfs and clean up safely
btrfs support from Scott Moser. Signed-off-by: Serge Hallyn <serge.hallyn@canonical.com> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
-rw-r--r--src/lxc/lxc-clone.in247
1 files changed, 127 insertions, 120 deletions
diff --git a/src/lxc/lxc-clone.in b/src/lxc/lxc-clone.in
index b6363a3..386be30 100644
--- a/src/lxc/lxc-clone.in
+++ b/src/lxc/lxc-clone.in
@@ -21,6 +21,8 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+set -e
+
usage() {
echo "usage: lxc-clone -o <orig> -n <new> [-s] [-h] [-L fssize] [-v vgname] [-p lxc_lv_prefix] [-t fstype]"
}
@@ -61,48 +63,49 @@ eval set -- "$getopt"
while true; do
case "$1" in
- -h|--help)
- help
- exit 1
- ;;
- -s|--snapshot)
- shift
- snapshot=yes
- snapshot_opt="-s"
- ;;
- -o|--orig)
- shift
- lxc_orig=$1
- shift
- ;;
- -L|--fssize)
- shift
- lxc_size=$1
- shift
- ;;
- -v|--vgname)
- shift
- lxc_vg=$1
- shift
- ;;
- -n|--new)
- shift
- lxc_new=$1
- shift
- ;;
- -p|--lvprefix)
- shift
- lxc_lv_prefix=$1
- shift
- ;;
- --)
- shift
- break;;
- *)
- echo $1
- usage
- exit 1
- ;;
+ -h|--help)
+ help
+ exit 1
+ ;;
+ -s|--snapshot)
+ shift
+ snapshot=yes
+ snapshot_opt="-s"
+ ;;
+ -o|--orig)
+ shift
+ lxc_orig=$1
+ shift
+ ;;
+ -L|--fssize)
+ shift
+ lxc_size=$1
+ shift
+ ;;
+ -v|--vgname)
+ shift
+ lxc_vg=$1
+ shift
+ ;;
+ -n|--new)
+ shift
+ lxc_new=$1
+ shift
+ ;;
+ -p|--lvprefix)
+ shift
+ lxc_lv_prefix=$1
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ *)
+ echo $1
+ usage
+ exit 1
+ ;;
esac
done
@@ -148,10 +151,27 @@ if [ -d "$lxc_path/$lxc_new" ]; then
exit 1
fi
-trap "${bindir}/lxc-destroy -n $lxc_new; echo aborted; exit 1" SIGHUP SIGINT SIGTERM
+mounted=0
+frozen=0
+oldroot=`grep lxc.rootfs $lxc_path/$lxc_orig/config | awk -F= '{ print $2 '}`
-mkdir -p $lxc_path/$lxc_new
+cleanup() {
+ if [ -b $oldroot ]; then
+ if [ $mounted -eq 1 ]; then
+ umount $rootfs || true
+ fi
+ lvremove -f $rootdev || true
+ fi
+ ${bindir}/lxc-destroy -n $lxc_new || true
+ if [ $frozen -eq 1 ]; then
+ lxc-unfreeze -n $lxc_orig
+ fi
+ echo aborted
+ exit 1
+}
+trap cleanup SIGHUP SIGINT SIGTERM
+mkdir -p $lxc_path/$lxc_new
hostname=$lxc_new
echo "Tweaking configuration"
@@ -168,92 +188,79 @@ fi
echo "Copying rootfs..."
rootfs=$lxc_path/$lxc_new/rootfs
-# First figure out if the old is a device. For now we only support
-# lvm devices.
-mounted=0
-#is container running
-lxc-info -s -n $lxc_orig|grep RUNNING >/dev/null 2>&1
-if [ $? -ne 0 ]; then
- container_running=True
-else
- container_running=False
-fi
+
+container_running=True
+lxc-info -s -n $lxc_orig|grep RUNNING >/dev/null 2>&1 || container_running=False
+
sed -i '/lxc.rootfs/d' $lxc_path/$lxc_new/config
oldroot=`grep lxc.rootfs $lxc_path/$lxc_orig/config | awk -F= '{ print $2 '}`
if [ -b $oldroot ]; then
- # this is a device. If we don't want to snapshot, then mkfs, mount
- # and rsync. Trivial but not yet implemented
- #if [ $snapshot == "no" ]; then
- # echo "non-snapshot and non-lvm clone of block device not yet implemented"
- # exit 1
- #fi
- lvdisplay $oldroot > /dev/null 2>&1
- if [ $? -ne 0 ]; then
- lvm=False
- echo "non-lvm block device cloning not yet implemented"
- exit 1
- else
- lvm=TRUE
- fi
- # ok, create a snapshot of the lvm device
- if [ $container_running == "True" ]; then
- lxc-freeze -n $lxc_orig
- fi
- lvcreate -s -L $lxc_size -n ${lxc_lv_prefix}${lxc_new}_snapshot $oldroot
- RETVAL=$?
- if [ $container_running == "True" ]; then
- lxc-unfreeze -n $lxc_orig
- fi
- if [ $RETVAL -ne 0 ]; then
- echo "snapshot creation failed"
- exit 1
- fi
- if [ $snapshot == "no" ]; then
- #mount snapshot
- mkdir -p ${rootfs}_snapshot
- mount /dev/$lxc_vg/${lxc_lv_prefix}${lxc_new}_snapshot ${rootfs}_snapshot || { echo "failed to mount new rootfs_snapshot"; exit 1; }
- #create a new lv
- lvcreate -L $lxc_size $lxc_vg -n ${lxc_lv_prefix}$lxc_new
- echo "lxc.rootfs = /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new" >> $lxc_path/$lxc_new/config
- # and mount it so we can tweak it
- mkdir -p $lxc_path/$lxc_new/rootfs
- mkfs -t $fstype /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new
- mount /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new $rootfs || { echo "failed to mount new rootfs"; exit 1; }
- mounted=1
- rsync -ax ${rootfs}_snapshot/ ${rootfs}/ || { echo "copy of data to new lv failed"; exit 1; }
- umount ${rootfs}_snapshot || { echo "failed to unmount new rootfs_snapshot"; exit 1; }
- rm -rf ${rootfs}_snapshot
- lvremove -f $lxc_vg/${lxc_lv_prefix}$lxc_new || echo "failed to remove the snapshot"
- else
- lvrename $lxc_vg/${lxc_lv_prefix}}${lxc_new}_snapshot $lxc_vg/${lxc_lv_prefix}$lxc_new
- echo "lxc.rootfs = /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new" >> $lxc_path/$lxc_new/config
- # and mount it so we can tweak it
- mkdir -p $lxc_path/$lxc_new/rootfs
- mount /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new $rootfs || { echo "failed to mount new rootfs"; exit 1; }
- mounted=1
- fi
+ type vgscan || { echo "Please install lvm"; false; }
+ lvdisplay $oldroot > /dev/null 2>&1 || { echo "non-lvm blockdev cloning not supported"; false; }
+ lvm=TRUE
+ # ok, create a snapshot of the lvm device
+ if [ $container_running = "True" ]; then
+ lxc-freeze -n $lxc_orig
+ frozen=1
+ fi
+ lvcreate -s -L $lxc_size -n ${lxc_lv_prefix}${lxc_new}_snapshot $oldroot
+ if [ $container_running = "True" ]; then
+ lxc-unfreeze -n $lxc_orig
+ frozen=0
+ fi
+ if [ $snapshot = "no" ]; then
+ #mount snapshot
+ mkdir -p ${rootfs}_snapshot
+ mount /dev/$lxc_vg/${lxc_lv_prefix}${lxc_new}_snapshot ${rootfs}_snapshot || { echo "failed to mount new rootfs_snapshot"; false; }
+ #create a new lv
+ lvcreate -L $lxc_size $lxc_vg -n ${lxc_lv_prefix}$lxc_new
+ echo "lxc.rootfs = /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new" >> $lxc_path/$lxc_new/config
+ # and mount it so we can tweak it
+ mkdir -p $lxc_path/$lxc_new/rootfs
+ mkfs -t $fstype /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new
+ mount /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new $rootfs || { echo "failed to mount new rootfs"; false; }
+ mounted=1
+ rsync -ax ${rootfs}_snapshot/ ${rootfs}/ || { echo "copy of data to new lv failed"; false; }
+ umount ${rootfs}_snapshot
+ rmdir ${rootfs}_snapshot
+ lvremove -f $lxc_vg/${lxc_lv_prefix}${lxc_new}_snapshot
+ else
+ lvrename $lxc_vg/${lxc_lv_prefix}${lxc_new}_snapshot $lxc_vg/${lxc_lv_prefix}$lxc_new
+ echo "lxc.rootfs = /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new" >> $lxc_path/$lxc_new/config
+ # and mount it so we can tweak it
+ mkdir -p $lxc_path/$lxc_new/rootfs
+ mount /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new $rootfs || { echo "failed to mount new rootfs"; false; }
+ mounted=1
+ fi
+
+elif out=$(btrfs subvolume list "$lxc_path/$lxc_orig/rootfs" 2>&1); then
+
+ out=$(btrfs subvolume snapshot "$lxc_path/$lxc_orig/rootfs" "$rootfs" 2>&1) || { echo "failed btrfs snapshot"; false; }
+ echo "lxc.rootfs = $rootfs" >> "$lxc_path/$lxc_new/config"
else
- if [ $container_running == True ];then
- lxc-freeze -n $lxc_orig
- fi
- rsync -ax $lxc_path/$lxc_orig/rootfs $lxc_path/$lxc_new/rootfs
- RETVAL=$?
- if [ $container_running == True ];then
- lxc-unfreeze -n $lxc_orig
- fi
- if [ RETVAL -ne 0 ]; then
- echo "copying rootfs failed"
- exit 1
- fi
- echo "lxc.rootfs = $rootfs" >> $lxc_path/$lxc_new/config
+ if [ $snapshot = "yes" ]; then
+ echo "Can't snapshot a directory"
+ cleanup
+ fi
+ if [ $container_running = "True" ]; then
+ lxc-freeze -n $lxc_orig
+ frozen=1
+ fi
+ mkdir -p $lxc_path/$lxc_new/rootfs/
+ rsync -ax $lxc_path/$lxc_orig/rootfs/ $lxc_path/$lxc_new/rootfs/
+ echo "lxc.rootfs = $rootfs" >> $lxc_path/$lxc_new/config
+ if [ $container_running = "True" ]; then
+ lxc-unfreeze -n $lxc_orig
+ frozen=0
+ fi
fi
echo "Updating rootfs..."
# so you can 'ssh $hostname.' or 'ssh $hostname.local'
if [ -f $rootfs/etc/dhcp/dhclient.conf ]; then
- sed -i "s/send host-name.*$/send host-name \"$hostname\";/" $rootfs/etc/dhcp/dhclient.conf
+ sed -i "s/send host-name.*$/send host-name \"$hostname\";/" $rootfs/etc/dhcp/dhclient.conf
fi
# set the hostname
@@ -267,7 +274,7 @@ EOF
# if this was a block device, then umount it now
if [ $mounted -eq 1 ]; then
- umount $rootfs
+ umount $rootfs
fi
echo "'$lxc_new' created"