* 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 <rha...@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 ------------------------------------------------------------------------------ EMC VNX: the world's simplest storage, starting under $10K The only unified storage solution that offers unified management Up to 160% more powerful than alternatives and 25% more efficient. Guaranteed. http://p.sf.net/sfu/emc-vnx-dev2dev _______________________________________________ Lxc-users mailing list Lxc-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-users