[Lxc-users] lxc-clone

matthew byers faintstlsaint at gmail.com
Thu Mar 31 16:42:11 UTC 2011


I saw this on the blog. Very useful and time saver. Exactly what alot of
pople were looking for.

On Wed, Mar 30, 2011 at 7:29 PM, Serge E. Hallyn <serge.hallyn at ubuntu.com>wrote:

> I've replaced most of my previous use of kvm and cloud instances for bug
> investigations with lxc instances.  To emulate my older workflows, I've
> created lxc-clone.  My diff against the current natty lxc package is
> attached.  I've written up how I use this at s3hh.wordpress.com.  Briefly,
> I have a single pristine container, with LVM rootfs, for each of lucid,
> maverick, and natty.  When I want a container, I
>
>        lxc-clone -o natty -n n1 -s
>        lxc-start -n n1
>
> which takes about 5 seconds altogether.  Ruin n1 however I like, and
>
>        lxc-destroy -l -n n1
>
> when done.
>
> It needs fleshing out, but it's at the point where it does exactly what
> I need.  The next thing I'm likely to add will be btrfs snapshotting,
> not sure when.
>
> Daniel, is this something you'd consider adding?  I assume that if so,
> then there are changes you'd like to make to the interface :)
>
> thanks,
> -serge
>
> === modified file 'configure'
> --- configure   2011-03-10 07:25:34 +0000
> +++ configure   2011-03-30 15:36:58 +0000
> @@ -5057,7 +5057,7 @@
>   CFLAGS="$CFLAGS -Wall"
>  fi
>
> -ac_config_files="$ac_config_files Makefile lxc.pc lxc.spec config/Makefile
> doc/Makefile doc/lxc-create.sgml doc/lxc-destroy.sgml doc/lxc-execute.sgml
> doc/lxc-start.sgml doc/lxc-checkpoint.sgml doc/lxc-restart.sgml
> doc/lxc-stop.sgml doc/lxc-console.sgml doc/lxc-freeze.sgml
> doc/lxc-unfreeze.sgml doc/lxc-monitor.sgml doc/lxc-wait.sgml doc/lxc-ls.sgml
> doc/lxc-ps.sgml doc/lxc-cgroup.sgml doc/lxc-kill.sgml doc/lxc.conf.sgml
> doc/lxc.sgml doc/common_options.sgml doc/see_also.sgml doc/rootfs/Makefile
> doc/examples/Makefile doc/examples/lxc-macvlan.conf
> doc/examples/lxc-vlan.conf doc/examples/lxc-no-netns.conf
> doc/examples/lxc-empty-netns.conf doc/examples/lxc-phys.conf
> doc/examples/lxc-veth.conf doc/examples/lxc-complex.conf templates/Makefile
> templates/lxc-lenny templates/lxc-debian templates/lxc-lucid
> templates/lxc-maverick templates/lxc-natty templates/lxc-busybox
> templates/lxc-fedora templates/lxc-sshd src/Makefile src/lxc/Makefile
> src/lxc/lxc-ps src/lxc/lxc-ls src/lxc/lxc-netstat src/lxc/lxc-checkconfig
> src/lxc/lxc-setcap src/lxc/lxc-setuid src/lxc/lxc-version src/lxc/lxc-create
> src/lxc/lxc-destroy"
> +ac_config_files="$ac_config_files Makefile lxc.pc lxc.spec config/Makefile
> doc/Makefile doc/lxc-create.sgml doc/lxc-destroy.sgml doc/lxc-execute.sgml
> doc/lxc-start.sgml doc/lxc-checkpoint.sgml doc/lxc-restart.sgml
> doc/lxc-stop.sgml doc/lxc-console.sgml doc/lxc-freeze.sgml
> doc/lxc-unfreeze.sgml doc/lxc-monitor.sgml doc/lxc-wait.sgml doc/lxc-ls.sgml
> doc/lxc-ps.sgml doc/lxc-cgroup.sgml doc/lxc-kill.sgml doc/lxc.conf.sgml
> doc/lxc.sgml doc/common_options.sgml doc/see_also.sgml doc/rootfs/Makefile
> doc/examples/Makefile doc/examples/lxc-macvlan.conf
> doc/examples/lxc-vlan.conf doc/examples/lxc-no-netns.conf
> doc/examples/lxc-empty-netns.conf doc/examples/lxc-phys.conf
> doc/examples/lxc-veth.conf doc/examples/lxc-complex.conf templates/Makefile
> templates/lxc-lenny templates/lxc-debian templates/lxc-lucid
> templates/lxc-maverick templates/lxc-natty templates/lxc-busybox
> templates/lxc-fedora templates/lxc-sshd src/Makefile src/lxc/Makefile
> src/lxc/lxc-ps src/lxc/lxc-ls src/lxc/lxc-netstat src/lxc/lxc-checkconfig
> src/lxc/lxc-setcap src/lxc/lxc-setuid src/lxc/lxc-version src/lxc/lxc-create
> src/lxc/lxc-clone src/lxc/lxc-destroy"
>
>  ac_config_commands="$ac_config_commands default"
>
> @@ -5842,6 +5842,7 @@
>     "src/lxc/lxc-setuid") CONFIG_FILES="$CONFIG_FILES src/lxc/lxc-setuid"
> ;;
>     "src/lxc/lxc-version") CONFIG_FILES="$CONFIG_FILES src/lxc/lxc-version"
> ;;
>     "src/lxc/lxc-create") CONFIG_FILES="$CONFIG_FILES src/lxc/lxc-create"
> ;;
> +    "src/lxc/lxc-clone") CONFIG_FILES="$CONFIG_FILES src/lxc/lxc-clone" ;;
>     "src/lxc/lxc-destroy") CONFIG_FILES="$CONFIG_FILES src/lxc/lxc-destroy"
> ;;
>     "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
>
>
> === modified file 'configure.ac'
> --- configure.ac        2011-03-10 07:25:34 +0000
> +++ configure.ac        2011-03-30 15:36:58 +0000
> @@ -156,6 +156,7 @@
>        src/lxc/lxc-setuid
>        src/lxc/lxc-version
>        src/lxc/lxc-create
> +       src/lxc/lxc-clone
>        src/lxc/lxc-destroy
>
>  ])
>
> === modified file 'lxc.spec'
> --- lxc.spec    2011-03-10 07:25:34 +0000
> +++ lxc.spec    2011-03-30 15:36:58 +0000
> @@ -78,6 +78,7 @@
>  %{_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
>
> === modified file 'src/lxc/Makefile.am'
> --- src/lxc/Makefile.am 2011-03-10 07:25:34 +0000
> +++ src/lxc/Makefile.am 2011-03-30 15:36:58 +0000
> @@ -72,6 +72,7 @@
>        lxc-setuid \
>        lxc-version \
>        lxc-create \
> +       lxc-clone \
>        lxc-destroy
>
>  bin_PROGRAMS = \
>
> === modified file 'src/lxc/Makefile.in'
> --- src/lxc/Makefile.in 2011-03-10 07:25:34 +0000
> +++ src/lxc/Makefile.in 2011-03-30 15:36:58 +0000
> @@ -49,7 +49,8 @@
>        $(srcdir)/lxc-create.in $(srcdir)/lxc-destroy.in \
>        $(srcdir)/lxc-ls.in $(srcdir)/lxc-netstat.in \
>        $(srcdir)/lxc-ps.in $(srcdir)/lxc-setcap.in \
> -       $(srcdir)/lxc-setuid.in $(srcdir)/lxc-version.in
> +       $(srcdir)/lxc-setuid.in $(srcdir)/lxc-version.in \
> +       $(srcdir)/lxc-clone.in
>  ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
>  am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \
>        $(top_srcdir)/config/linux.m4 $(top_srcdir)/configure.ac
> @@ -58,7 +59,8 @@
>  mkinstalldirs = $(install_sh) -d
>  CONFIG_HEADER = $(top_builddir)/src/config.h
>  CONFIG_CLEAN_FILES = lxc-ps lxc-ls lxc-netstat lxc-checkconfig \
> -       lxc-setcap lxc-setuid lxc-version lxc-create lxc-destroy
> +       lxc-setcap lxc-setuid lxc-version lxc-create lxc-destroy \
> +       lxc-clone
>  CONFIG_CLEAN_VPATH_FILES =
>  am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibdir)" \
>        "$(DESTDIR)$(sodir)" "$(DESTDIR)$(bindir)" \
> @@ -376,6 +378,7 @@
>        lxc-setcap \
>        lxc-setuid \
>        lxc-version \
> +       lxc-clone \
>        lxc-create \
>        lxc-destroy
>
> @@ -445,6 +448,8 @@
>        cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
>  lxc-version: $(top_builddir)/config.status $(srcdir)/lxc-version.in
>        cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
> +lxc-clone: $(top_builddir)/config.status $(srcdir)/lxc-clone.in
> +       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
>  lxc-create: $(top_builddir)/config.status $(srcdir)/lxc-create.in
>        cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
>  lxc-destroy: $(top_builddir)/config.status $(srcdir)/lxc-destroy.in
>
> === added file 'src/lxc/lxc-clone.in'
> --- src/lxc/lxc-clone.in        1970-01-01 00:00:00 +0000
> +++ src/lxc/lxc-clone.in        2011-03-30 15:36:58 +0000
> @@ -0,0 +1,206 @@
> +#!/bin/bash
> +
> +#
> +# lxc: linux Container library
> +
> +# Authors:
> +# Serge Hallyn <serge.hallyn at ubuntu.com>
> +# Daniel Lezcano <daniel.lezcano at free.fr>
> +
> +# 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 <orig> -n <new> [-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'
> +sed -i "s/send host-name.*$/send host-name $hostname/"
> $rootfs/etc/dhcp/dhclient.conf
> +
> +# set the hostname
> +cat <<EOF > $rootfs/etc/hostname
> +$hostname
> +EOF
> +# set minimal hosts
> +cat <<EOF > $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"
>
> === modified file 'src/lxc/lxc-destroy.in'
> --- src/lxc/lxc-destroy.in      2010-01-10 10:40:21 +0000
> +++ src/lxc/lxc-destroy.in      2011-03-29 23:00:34 +0000
> @@ -26,7 +26,8 @@
>  #
>
>  usage() {
> -    echo "usage: $0 -n <name>"
> +    echo "usage: $0 -n <name> [-l]"
> +    echo "       if -l is specified, attempt to lvremove the rootfs
> device"
>  }
>
>  if [ "$(id -u)" != "0" ]; then
> @@ -34,9 +35,9 @@
>    exit 1
>  fi
>
> -shortoptions='n:'
> -longoptions='name:'
> -lxc_path=@LXCPATH@
> +shortoptions='n:l'
> +longoptions='name:,lvm'
> +lxc_path=/var/lib/lxc
>
>  getopt=$(getopt -o $shortoptions --longoptions  $longoptions -- "$@")
>  if [ $? != 0 ]; then
> @@ -46,6 +47,8 @@
>
>  eval set -- "$getopt"
>
> +lvremove=0
> +
>  while true; do
>         case "$1" in
>            -n|--name)
> @@ -53,6 +56,10 @@
>                lxc_name=$1
>                shift
>                ;;
> +           -l|--lvm)
> +               shift
> +               lvremove=1
> +               ;;
>             --)
>                shift
>                break;;
> @@ -75,5 +82,13 @@
>     exit 1
>  fi
>
> +if [ $lvremove -eq 1 ]; then
> +    rootdev=`grep lxc.rootfs $lxc_path/$lxc_name/config | awk -F= '{ print
> $2 '}`
> +    # only makes sense if it is a blockdev or a symlink to one
> +    if [ -b $rootdev -o -h $rootdev ]; then
> +           lvremove $rootdev
> +    fi
> +fi
> +
>  # recursively remove the container to remove old container configuration
>  rm -rf --preserve-root $lxc_path/$lxc_name
>
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (GNU/Linux)
>
> iQEcBAEBAgAGBQJNk1pzAAoJEHmllQITXQdF7G4H/0xMrCVEzaFnmZAdo8jppR6E
> tvo5fP1MtHlvu/SH+TbNEYv/Pd3TsqFllRomnBgKWPXbRVPmCY3gomoh+ec2wQOd
> OYX8GMVCusqk2JTOTz/KD9YhBhYUEYrv2JRdXdYAav1yOdEhbtaJWWyO5L3qAV6M
> lgoHrRqtuM0ueNVY5+0OIrhd5sHbxc/G1BXHERTkcPKWR7GwsyUjWOmjIL8bGQG/
> t0GKlyYAJPIbXDATW6Izp/R9q6+5tu8k9A+c2di2afFsS8l7ZhpUU+HhMTvqxYTJ
> ajoRjfwzfhqbzGh1dnWRyLnRXL9Lfokkkhii0RPbVpIdTLRaYCuJ1Uh2v1im5i4=
> =/Kxf
> -----END PGP SIGNATURE-----
>
>
> ------------------------------------------------------------------------------
> Create and publish websites with WebMatrix
> Use the most popular FREE web apps or write code yourself;
> WebMatrix provides all the features you need to develop and
> publish your website. http://p.sf.net/sfu/ms-webmatrix-sf
>
> _______________________________________________
> Lxc-users mailing list
> Lxc-users at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-users
>
>


-- 
God Bless
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linuxcontainers.org/pipermail/lxc-users/attachments/20110331/0a74ce11/attachment.html>


More information about the lxc-users mailing list