Commit 5d325fcf by Ubuntu Committed by Daniel Lezcano

lxc-clone: support btrfs and clean up safely

btrfs support from Scott Moser. Signed-off-by: 's avatarSerge Hallyn <serge.hallyn@canonical.com> Signed-off-by: 's avatarDaniel Lezcano <dlezcano@fr.ibm.com>
parent 8b7071ec
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
# License along with this library; if not, write to the Free Software # License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
set -e
usage() { usage() {
echo "usage: lxc-clone -o <orig> -n <new> [-s] [-h] [-L fssize] [-v vgname] [-p lxc_lv_prefix] [-t fstype]" 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" ...@@ -61,48 +63,49 @@ eval set -- "$getopt"
while true; do while true; do
case "$1" in case "$1" in
-h|--help) -h|--help)
help help
exit 1 exit 1
;; ;;
-s|--snapshot) -s|--snapshot)
shift shift
snapshot=yes snapshot=yes
snapshot_opt="-s" snapshot_opt="-s"
;; ;;
-o|--orig) -o|--orig)
shift shift
lxc_orig=$1 lxc_orig=$1
shift shift
;; ;;
-L|--fssize) -L|--fssize)
shift shift
lxc_size=$1 lxc_size=$1
shift shift
;; ;;
-v|--vgname) -v|--vgname)
shift shift
lxc_vg=$1 lxc_vg=$1
shift shift
;; ;;
-n|--new) -n|--new)
shift shift
lxc_new=$1 lxc_new=$1
shift shift
;; ;;
-p|--lvprefix) -p|--lvprefix)
shift shift
lxc_lv_prefix=$1 lxc_lv_prefix=$1
shift shift
;; ;;
--) --)
shift shift
break;; break
*) ;;
echo $1 *)
usage echo $1
exit 1 usage
;; exit 1
;;
esac esac
done done
...@@ -148,10 +151,27 @@ if [ -d "$lxc_path/$lxc_new" ]; then ...@@ -148,10 +151,27 @@ if [ -d "$lxc_path/$lxc_new" ]; then
exit 1 exit 1
fi 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 hostname=$lxc_new
echo "Tweaking configuration" echo "Tweaking configuration"
...@@ -168,92 +188,79 @@ fi ...@@ -168,92 +188,79 @@ fi
echo "Copying rootfs..." echo "Copying rootfs..."
rootfs=$lxc_path/$lxc_new/rootfs rootfs=$lxc_path/$lxc_new/rootfs
# First figure out if the old is a device. For now we only support
# lvm devices. container_running=True
mounted=0 lxc-info -s -n $lxc_orig|grep RUNNING >/dev/null 2>&1 || container_running=False
#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
sed -i '/lxc.rootfs/d' $lxc_path/$lxc_new/config sed -i '/lxc.rootfs/d' $lxc_path/$lxc_new/config
oldroot=`grep lxc.rootfs $lxc_path/$lxc_orig/config | awk -F= '{ print $2 '}` oldroot=`grep lxc.rootfs $lxc_path/$lxc_orig/config | awk -F= '{ print $2 '}`
if [ -b $oldroot ]; then if [ -b $oldroot ]; then
# this is a device. If we don't want to snapshot, then mkfs, mount type vgscan || { echo "Please install lvm"; false; }
# and rsync. Trivial but not yet implemented lvdisplay $oldroot > /dev/null 2>&1 || { echo "non-lvm blockdev cloning not supported"; false; }
#if [ $snapshot == "no" ]; then lvm=TRUE
# echo "non-snapshot and non-lvm clone of block device not yet implemented" # ok, create a snapshot of the lvm device
# exit 1 if [ $container_running = "True" ]; then
#fi lxc-freeze -n $lxc_orig
lvdisplay $oldroot > /dev/null 2>&1 frozen=1
if [ $? -ne 0 ]; then fi
lvm=False lvcreate -s -L $lxc_size -n ${lxc_lv_prefix}${lxc_new}_snapshot $oldroot
echo "non-lvm block device cloning not yet implemented" if [ $container_running = "True" ]; then
exit 1 lxc-unfreeze -n $lxc_orig
else frozen=0
lvm=TRUE fi
fi if [ $snapshot = "no" ]; then
# ok, create a snapshot of the lvm device #mount snapshot
if [ $container_running == "True" ]; then mkdir -p ${rootfs}_snapshot
lxc-freeze -n $lxc_orig mount /dev/$lxc_vg/${lxc_lv_prefix}${lxc_new}_snapshot ${rootfs}_snapshot || { echo "failed to mount new rootfs_snapshot"; false; }
fi #create a new lv
lvcreate -s -L $lxc_size -n ${lxc_lv_prefix}${lxc_new}_snapshot $oldroot lvcreate -L $lxc_size $lxc_vg -n ${lxc_lv_prefix}$lxc_new
RETVAL=$? echo "lxc.rootfs = /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new" >> $lxc_path/$lxc_new/config
if [ $container_running == "True" ]; then # and mount it so we can tweak it
lxc-unfreeze -n $lxc_orig mkdir -p $lxc_path/$lxc_new/rootfs
fi mkfs -t $fstype /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new
if [ $RETVAL -ne 0 ]; then mount /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new $rootfs || { echo "failed to mount new rootfs"; false; }
echo "snapshot creation failed" mounted=1
exit 1 rsync -ax ${rootfs}_snapshot/ ${rootfs}/ || { echo "copy of data to new lv failed"; false; }
fi umount ${rootfs}_snapshot
if [ $snapshot == "no" ]; then rmdir ${rootfs}_snapshot
#mount snapshot lvremove -f $lxc_vg/${lxc_lv_prefix}${lxc_new}_snapshot
mkdir -p ${rootfs}_snapshot else
mount /dev/$lxc_vg/${lxc_lv_prefix}${lxc_new}_snapshot ${rootfs}_snapshot || { echo "failed to mount new rootfs_snapshot"; exit 1; } lvrename $lxc_vg/${lxc_lv_prefix}${lxc_new}_snapshot $lxc_vg/${lxc_lv_prefix}$lxc_new
#create a new lv echo "lxc.rootfs = /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new" >> $lxc_path/$lxc_new/config
lvcreate -L $lxc_size $lxc_vg -n ${lxc_lv_prefix}$lxc_new # and mount it so we can tweak it
echo "lxc.rootfs = /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new" >> $lxc_path/$lxc_new/config mkdir -p $lxc_path/$lxc_new/rootfs
# and mount it so we can tweak it mount /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new $rootfs || { echo "failed to mount new rootfs"; false; }
mkdir -p $lxc_path/$lxc_new/rootfs mounted=1
mkfs -t $fstype /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new fi
mount /dev/$lxc_vg/${lxc_lv_prefix}$lxc_new $rootfs || { echo "failed to mount new rootfs"; exit 1; }
mounted=1 elif out=$(btrfs subvolume list "$lxc_path/$lxc_orig/rootfs" 2>&1); then
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; } out=$(btrfs subvolume snapshot "$lxc_path/$lxc_orig/rootfs" "$rootfs" 2>&1) || { echo "failed btrfs snapshot"; false; }
rm -rf ${rootfs}_snapshot echo "lxc.rootfs = $rootfs" >> "$lxc_path/$lxc_new/config"
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
else else
if [ $container_running == True ];then if [ $snapshot = "yes" ]; then
lxc-freeze -n $lxc_orig echo "Can't snapshot a directory"
fi cleanup
rsync -ax $lxc_path/$lxc_orig/rootfs $lxc_path/$lxc_new/rootfs fi
RETVAL=$? if [ $container_running = "True" ]; then
if [ $container_running == True ];then lxc-freeze -n $lxc_orig
lxc-unfreeze -n $lxc_orig frozen=1
fi fi
if [ RETVAL -ne 0 ]; then mkdir -p $lxc_path/$lxc_new/rootfs/
echo "copying rootfs failed" rsync -ax $lxc_path/$lxc_orig/rootfs/ $lxc_path/$lxc_new/rootfs/
exit 1 echo "lxc.rootfs = $rootfs" >> $lxc_path/$lxc_new/config
fi if [ $container_running = "True" ]; then
echo "lxc.rootfs = $rootfs" >> $lxc_path/$lxc_new/config lxc-unfreeze -n $lxc_orig
frozen=0
fi
fi fi
echo "Updating rootfs..." echo "Updating rootfs..."
# so you can 'ssh $hostname.' or 'ssh $hostname.local' # so you can 'ssh $hostname.' or 'ssh $hostname.local'
if [ -f $rootfs/etc/dhcp/dhclient.conf ]; then 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 fi
# set the hostname # set the hostname
...@@ -267,7 +274,7 @@ EOF ...@@ -267,7 +274,7 @@ EOF
# if this was a block device, then umount it now # if this was a block device, then umount it now
if [ $mounted -eq 1 ]; then if [ $mounted -eq 1 ]; then
umount $rootfs umount $rootfs
fi fi
echo "'$lxc_new' created" echo "'$lxc_new' created"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment