From: Serge E. Hallyn Date: Thu, 23 Jun 2011 22:42:24 +0000 (+0200) Subject: Add lxc-clone script X-Git-Tag: lxc-0.7.5~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=be8b5972427bf6d5f83c94b5e50a30cdeba2543a;p=thirdparty%2Flxc.git Add lxc-clone script Create an lxc-clone script to clone containers. It should probably be factored into helpers and then enhanced, in particular to convert between LVM and non-LVM containers, create non-snapshot LVM clones, support loopback devices, and, when stable enough, to use overlayfs, btrfs, etc. But this is a start. Signed-off-by: Serge Hallyn Signed-off-by: Daniel Lezcano --- diff --git a/configure.ac b/configure.ac index 6cce1b408..0d4f4c0fd 100644 --- a/configure.ac +++ b/configure.ac @@ -157,6 +157,7 @@ AC_CONFIG_FILES([ src/lxc/lxc-setuid src/lxc/lxc-version src/lxc/lxc-create + src/lxc/lxc-clone src/lxc/lxc-destroy ]) diff --git a/lxc.spec.in b/lxc.spec.in index 452493de4..f22cd06ae 100644 --- a/lxc.spec.in +++ b/lxc.spec.in @@ -78,6 +78,7 @@ rm -rf %{buildroot} %{_bindir}/* %attr(4111,root,root) %{_bindir}/lxc-attach %attr(4111,root,root) %{_bindir}/lxc-create +%attr(4111,root,root) %{_bindir}/lxc-clone %attr(4111,root,root) %{_bindir}/lxc-start %attr(4111,root,root) %{_bindir}/lxc-netstat %attr(4111,root,root) %{_bindir}/lxc-unshare diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am index 9def453f2..1dfca0088 100644 --- a/src/lxc/Makefile.am +++ b/src/lxc/Makefile.am @@ -70,6 +70,7 @@ bin_SCRIPTS = \ lxc-setuid \ lxc-version \ lxc-create \ + lxc-clone \ lxc-destroy bin_PROGRAMS = \ diff --git a/src/lxc/lxc-clone.in b/src/lxc/lxc-clone.in new file mode 100644 index 000000000..91944a0e5 --- /dev/null +++ b/src/lxc/lxc-clone.in @@ -0,0 +1,208 @@ +#!/bin/bash + +# +# lxc: linux Container library + +# Authors: +# Serge Hallyn +# Daniel Lezcano + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# This library 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 +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +usage() { + echo "usage: lxc-clone -o -n [-s] [-h] [-L fssize] [-v vgname]" +} + +help() { + usage + echo + echo "creates a lxc system object." + echo + echo "Options:" + echo "orig : name of the original container" + echo "new : name of the new container" + 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" +} + +shortoptions='ho:n:sL:v:' +longoptions='help,orig:,name:,snapshot,fssize,vgname' +lxc_path=/var/lib/lxc +bindir=/usr/bin +snapshot=no +lxc_size=2G +lxc_vg=lxc + +getopt=$(getopt -o $shortoptions --longoptions $longoptions -- "$@") +if [ $? != 0 ]; then + usage + exit 1; +fi + +eval set -- "$getopt" + +while true; do + case "$1" in + -h|--help) + help + exit 1 + ;; + -s|--snapshot) + shift + snapshot=yes + ;; + -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 + ;; + --) + shift + break;; + *) + echo $1 + usage + exit 1 + ;; + esac +done + +if [ -z "$lxc_path" ]; then + echo "no configuration path defined !" + exit 1 +fi + +if [ ! -r $lxc_path ]; then + echo "configuration path '$lxc_path' not found" + exit 1 +fi + +if [ -z "$lxc_orig" ]; then + echo "no original container name specified" + usage + exit 1 +fi + +if [ -z "$lxc_new" ]; then + echo "no new container name specified" + usage + exit 1 +fi + +if [ "$(id -u)" != "0" ]; then + echo "This command has to be run as root" + exit 1 +fi + +if [ ! -r $lxc_path ]; then + echo "no configuration path defined !" + exit 1 +fi + +if [ ! -d "$lxc_path/$lxc_orig" ]; then + echo "'$lxc_orig' does not exist" + exit 1 +fi + +if [ -d "$lxc_path/$lxc_new" ]; then + echo "'$lxc_new' already exists" + exit 1 +fi + +trap "${bindir}/lxc-destroy -n $lxc_new; echo aborted; exit 1" SIGHUP SIGINT SIGTERM + +mkdir -p $lxc_path/$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 + +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 + +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 +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 + echo "non-snapshot and non-lvm clone of block device not yet implemented" + exit 1 + 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 +else + cp -a $lxc_path/$lxc_orig/rootfs $lxc_path/$lxc_new/rootfs || return 1 + 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 + sed -i "s/send host-name.*$/send host-name $hostname/" $rootfs/etc/dhcp/dhclient.conf +fi + +# set the hostname +cat < $rootfs/etc/hostname +$hostname +EOF +# set minimal hosts +cat < $rootfs/etc/hosts +127.0.0.1 localhost $hostname +EOF + +# if this was a block device, then umount it now +if [ $mounted -eq 1 ]; then + umount $rootfs +fi + +echo "'$lxc_new' created"