[Lxc-users] [PATCH] multiple mods to lxc-clone
Ramez Hanna
rhanna at informatiq.org
Fri Aug 26 11:58:53 UTC 2011
* allow cloning of non-snapshot lvm devices
* if no -s then create a copy of the lvm block device and copy data
from the orig to the new container device
* first take a snapshot, then use this snapshot to copy data,
remove snapshot after done
* if orig container is running freeze it while copying
* in case lvm block device, the container is only frozen during
creation of snapshot ~1 sec
* use rsync -ax insted of cp -a
* in case copying a live contrainer it won't copy runtine mounted
files such as /proc, /sys and some /dev
* new opts
* fstype: type of fs for the newly created lvm device in case of
non-snapshot lvm
* lvprefix: prefix for new lvm device name.
* do not delete the lines lxc.mount by default
* check is fstab exists then copy it
* only modify lines that contain "lxc.mount =", debian template
seems to not have that line but uses lxc.mount. lines which get
screwed
Signed-off-by: InformatiQ <rhanna at informatiq.org>
---
src/lxc/lxc-clone.in | 98 ++++++++++++++++++++++++++++++++++++++------------
1 files changed, 75 insertions(+), 23 deletions(-)
mode change 100644 => 100755 src/lxc/lxc-clone.in
diff --git a/src/lxc/lxc-clone.in b/src/lxc/lxc-clone.in
old mode 100644
new mode 100755
index 91944a0..d42160b
--- a/src/lxc/lxc-clone.in
+++ b/src/lxc/lxc-clone.in
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/bash
#
# lxc: linux Container library
@@ -22,7 +22,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
usage() {
- echo "usage: lxc-clone -o <orig> -n <new> [-s] [-h] [-L fssize]
[-v vgname]"
+ echo "usage: lxc-clone -o <orig> -n <new> [-s] [-h] [-L fssize]
[-v vgname] [-p lxc_lv_prefix] [-t fstype]"
}
help() {
@@ -36,15 +36,19 @@ help() {
echo "-s : make the new rootfs a snapshot of the original"
echo "fssize : size if creating a new fs. By default, 2G"
echo "vgname : lvm volume group name, lxc by default"
+ echo "lvprefix" : lvm volume name prefix, none by default, e.g.
--lvprefix=lxc_ then new lxc lv name will be lxc_newname"
+ echo "fstype" : new container file system type, ext3 by
default (only works for non-snapshot lvm)"
}
-shortoptions='ho:n:sL:v:'
-longoptions='help,orig:,name:,snapshot,fssize,vgname'
+shortoptions='ho:n:sL:v:p:t:'
+longoptions='help,orig:,name:,snapshot,fssize:,vgname:,lvprefix:,fstype:'
lxc_path=/var/lib/lxc
bindir=/usr/bin
snapshot=no
lxc_size=2G
lxc_vg=lxc
+lxc_lv_prefix=""
+fstype=ext3
getopt=$(getopt -o $shortoptions --longoptions $longoptions -- "$@")
if [ $? != 0 ]; then
@@ -63,6 +67,7 @@ while true; do
-s|--snapshot)
shift
snapshot=yes
+ snapshot_opt="-s"
;;
-o|--orig)
shift
@@ -84,6 +89,11 @@ while true; do
lxc_new=$1
shift
;;
+ -p|--lvprefix)
+ shift
+ lxc_lv_prefix=$1
+ shift
+ ;;
--)
shift
break;;
@@ -141,50 +151,92 @@ trap "${bindir}/lxc-destroy -n $lxc_new; echo
aborted; exit 1" SIGHUP SIGINT SIG
mkdir -p $lxc_path/$lxc_new
+hostname=$lxc_new
+
echo "Tweaking configuration"
cp $lxc_path/$lxc_orig/config $lxc_path/$lxc_new/config
sed -i '/lxc.utsname/d' $lxc_path/$lxc_new/config
echo "lxc.utsname = $hostname" >> $lxc_path/$lxc_new/config
-sed -i '/lxc.mount/d' $lxc_path/$lxc_new/config
-echo "lxc.mount = $lxc_path/$lxc_new/fstab" >> $lxc_path/$lxc_new/config
+grep "lxc.mount =" $lxc_path/$lxc_new/config >/dev/null 2>&1 && { sed
-i '/lxc.mount =/d' $lxc_path/$lxc_new/config; echo "lxc.mount =
$lxc_path/$lxc_new/fstab" >> $lxc_path/$lxc_new/config; }
-cp $lxc_path/$lxc_orig/fstab $lxc_path/$lxc_new/fstab
-sed -i "s@$lxc_path/$lxc_orig@$lxc_path/$lxc_new@" $lxc_path/$lxc_new/fstab
+if [ -e $lxc_path/$lxc_orig/fstab ];then
+ cp $lxc_path/$lxc_orig/fstab $lxc_path/$lxc_new/fstab
+ sed -i "s@$lxc_path/$lxc_orig@$lxc_path/$lxc_new@" $lxc_path/$lxc_new/fstab
+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
+fi
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
+ #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
- echo "non-snapshot and non-lvm clone of block device not yet implemented"
- exit 1
- fi
+ 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
- lvcreate -s -L $lxc_size -n $lxc_new /dev/$lxc_vg/$lxc_orig || exit 1
- echo "lxc.rootfs = /dev/$lxc_vg/$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_new $rootfs || { echo "failed to mount new
rootfs"; exit 1; }
- mounted=1
+ if [ $container_running == "True" ]; then
+ lxc-freeze -n $lxc_orig
+ fi
+ lvcreate -s -L $lxc_size -n ${lxc_lv_prefix}${lxc_new}_snapshot
$oldroot || exit 1
+ if [ $container_running == "True" ]; then
+ lxc-unfreeze -n $lxc_orig
+ 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
+
else
- cp -a $lxc_path/$lxc_orig/rootfs $lxc_path/$lxc_new/rootfs || return 1
+ if [ $container_running == True ];then
+ lxc-freeze -n $lxc_orig
+ fi
+ rsync -ax $lxc_path/$lxc_orig/rootfs $lxc_path/$lxc_new/rootfs || return 1
+ if [ $container_running == True ];then
+ lxc-unfreeze -n $lxc_orig
+ fi
echo "lxc.rootfs = $rootfs" >> $lxc_path/$lxc_new/config
fi
echo "Updating rootfs..."
-hostname=$lxc_new
# so you can 'ssh $hostname.' or 'ssh $hostname.local'
if [ -f $rootfs/etc/dhcp/dhclient.conf ]; then
--
1.7.6
More information about the lxc-users
mailing list