<div dir="ltr">I saw this on the blog. Very useful and time saver. Exactly what alot of pople were looking for.<br><br>
<div class="gmail_quote">On Wed, Mar 30, 2011 at 7:29 PM, Serge E. Hallyn <span dir="ltr"><<a href="mailto:serge.hallyn@ubuntu.com">serge.hallyn@ubuntu.com</a>></span> wrote:<br>
<blockquote style="BORDER-LEFT: #ccc 1px solid; MARGIN: 0px 0px 0px 0.8ex; PADDING-LEFT: 1ex" class="gmail_quote">I've replaced most of my previous use of kvm and cloud instances for bug<br>investigations with lxc instances.  To emulate my older workflows, I've<br>
created lxc-clone.  My diff against the current natty lxc package is<br>attached.  I've written up how I use this at <a href="http://s3hh.wordpress.com/" target="_blank">s3hh.wordpress.com</a>.  Briefly,<br>I have a single pristine container, with LVM rootfs, for each of lucid,<br>
maverick, and natty.  When I want a container, I<br><br>       lxc-clone -o natty -n n1 -s<br>       lxc-start -n n1<br><br>which takes about 5 seconds altogether.  Ruin n1 however I like, and<br><br>       lxc-destroy -l -n n1<br>
<br>when done.<br><br>It needs fleshing out, but it's at the point where it does exactly what<br>I need.  The next thing I'm likely to add will be btrfs snapshotting,<br>not sure when.<br><br>Daniel, is this something you'd consider adding?  I assume that if so,<br>
then there are changes you'd like to make to the interface :)<br><br>thanks,<br>-serge<br><br>=== modified file 'configure'<br>--- configure   2011-03-10 07:25:34 +0000<br>+++ configure   2011-03-30 15:36:58 +0000<br>
@@ -5057,7 +5057,7 @@<br>  CFLAGS="$CFLAGS -Wall"<br> fi<br><br>-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"<br>
+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"<br>
<br> ac_config_commands="$ac_config_commands default"<br><br>@@ -5842,6 +5842,7 @@<br>    "src/lxc/lxc-setuid") CONFIG_FILES="$CONFIG_FILES src/lxc/lxc-setuid" ;;<br>    "src/lxc/lxc-version") CONFIG_FILES="$CONFIG_FILES src/lxc/lxc-version" ;;<br>
    "src/lxc/lxc-create") CONFIG_FILES="$CONFIG_FILES src/lxc/lxc-create" ;;<br>+    "src/lxc/lxc-clone") CONFIG_FILES="$CONFIG_FILES src/lxc/lxc-clone" ;;<br>    "src/lxc/lxc-destroy") CONFIG_FILES="$CONFIG_FILES src/lxc/lxc-destroy" ;;<br>
    "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;<br><br><br>=== modified file '<a href="http://configure.ac/" target="_blank">configure.ac</a>'<br>--- <a href="http://configure.ac/" target="_blank">configure.ac</a>        2011-03-10 07:25:34 +0000<br>
+++ <a href="http://configure.ac/" target="_blank">configure.ac</a>        2011-03-30 15:36:58 +0000<br>@@ -156,6 +156,7 @@<br>       src/lxc/lxc-setuid<br>       src/lxc/lxc-version<br>       src/lxc/lxc-create<br>+       src/lxc/lxc-clone<br>
       src/lxc/lxc-destroy<br><br> ])<br><br>=== modified file 'lxc.spec'<br>--- lxc.spec    2011-03-10 07:25:34 +0000<br>+++ lxc.spec    2011-03-30 15:36:58 +0000<br>@@ -78,6 +78,7 @@<br> %{_bindir}/*<br> %attr(4111,root,root) %{_bindir}/lxc-attach<br>
 %attr(4111,root,root) %{_bindir}/lxc-create<br>+%attr(4111,root,root) %{_bindir}/lxc-clone<br> %attr(4111,root,root) %{_bindir}/lxc-start<br> %attr(4111,root,root) %{_bindir}/lxc-netstat<br> %attr(4111,root,root) %{_bindir}/lxc-unshare<br>
<br>=== modified file 'src/lxc/Makefile.am'<br>--- src/lxc/Makefile.am 2011-03-10 07:25:34 +0000<br>+++ src/lxc/Makefile.am 2011-03-30 15:36:58 +0000<br>@@ -72,6 +72,7 @@<br>       lxc-setuid \<br>       lxc-version \<br>
       lxc-create \<br>+       lxc-clone \<br>       lxc-destroy<br><br> bin_PROGRAMS = \<br><br>=== modified file 'src/lxc/Makefile.in'<br>--- src/lxc/Makefile.in 2011-03-10 07:25:34 +0000<br>+++ src/lxc/Makefile.in 2011-03-30 15:36:58 +0000<br>
@@ -49,7 +49,8 @@<br>       $(srcdir)/<a href="http://lxc-create.in/" target="_blank">lxc-create.in</a> $(srcdir)/<a href="http://lxc-destroy.in/" target="_blank">lxc-destroy.in</a> \<br>       $(srcdir)/<a href="http://lxc-ls.in/" target="_blank">lxc-ls.in</a> $(srcdir)/<a href="http://lxc-netstat.in/" target="_blank">lxc-netstat.in</a> \<br>
       $(srcdir)/<a href="http://lxc-ps.in/" target="_blank">lxc-ps.in</a> $(srcdir)/<a href="http://lxc-setcap.in/" target="_blank">lxc-setcap.in</a> \<br>-       $(srcdir)/<a href="http://lxc-setuid.in/" target="_blank">lxc-setuid.in</a> $(srcdir)/<a href="http://lxc-version.in/" target="_blank">lxc-version.in</a><br>
+       $(srcdir)/<a href="http://lxc-setuid.in/" target="_blank">lxc-setuid.in</a> $(srcdir)/<a href="http://lxc-version.in/" target="_blank">lxc-version.in</a> \<br>+       $(srcdir)/<a href="http://lxc-clone.in/" target="_blank">lxc-clone.in</a><br>
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4<br> am__aclocal_m4_deps = $(top_srcdir)/config/acinclude.m4 \<br>       $(top_srcdir)/config/linux.m4 $(top_srcdir)/<a href="http://configure.ac/" target="_blank">configure.ac</a><br>
@@ -58,7 +59,8 @@<br> mkinstalldirs = $(install_sh) -d<br> CONFIG_HEADER = $(top_builddir)/src/config.h<br> CONFIG_CLEAN_FILES = lxc-ps lxc-ls lxc-netstat lxc-checkconfig \<br>-       lxc-setcap lxc-setuid lxc-version lxc-create lxc-destroy<br>
+       lxc-setcap lxc-setuid lxc-version lxc-create lxc-destroy \<br>+       lxc-clone<br> CONFIG_CLEAN_VPATH_FILES =<br> am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibdir)" \<br>       "$(DESTDIR)$(sodir)" "$(DESTDIR)$(bindir)" \<br>
@@ -376,6 +378,7 @@<br>       lxc-setcap \<br>       lxc-setuid \<br>       lxc-version \<br>+       lxc-clone \<br>       lxc-create \<br>       lxc-destroy<br><br>@@ -445,6 +448,8 @@<br>       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@<br>
 lxc-version: $(top_builddir)/config.status $(srcdir)/<a href="http://lxc-version.in/" target="_blank">lxc-version.in</a><br>       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@<br>+lxc-clone: $(top_builddir)/config.status $(srcdir)/<a href="http://lxc-clone.in/" target="_blank">lxc-clone.in</a><br>
+       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@<br> lxc-create: $(top_builddir)/config.status $(srcdir)/<a href="http://lxc-create.in/" target="_blank">lxc-create.in</a><br>       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@<br>
 lxc-destroy: $(top_builddir)/config.status $(srcdir)/<a href="http://lxc-destroy.in/" target="_blank">lxc-destroy.in</a><br><br>=== added file 'src/lxc/<a href="http://lxc-clone.in/" target="_blank">lxc-clone.in</a>'<br>
--- src/lxc/<a href="http://lxc-clone.in/" target="_blank">lxc-clone.in</a>        1970-01-01 00:00:00 +0000<br>+++ src/lxc/<a href="http://lxc-clone.in/" target="_blank">lxc-clone.in</a>        2011-03-30 15:36:58 +0000<br>
@@ -0,0 +1,206 @@<br>+#!/bin/bash<br>+<br>+#<br>+# lxc: linux Container library<br>+<br>+# Authors:<br>+# Serge Hallyn <<a href="mailto:serge.hallyn@ubuntu.com">serge.hallyn@ubuntu.com</a>><br>+# Daniel Lezcano <<a href="mailto:daniel.lezcano@free.fr">daniel.lezcano@free.fr</a>><br>
+<br>+# This library is free software; you can redistribute it and/or<br>+# modify it under the terms of the GNU Lesser General Public<br>+# License as published by the Free Software Foundation; either<br>+# version 2.1 of the License, or (at your option) any later version.<br>
+<br>+# This library is distributed in the hope that it will be useful,<br>+# but WITHOUT ANY WARRANTY; without even the implied warranty of<br>+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU<br>+# Lesser General Public License for more details.<br>
+<br>+# You should have received a copy of the GNU Lesser General Public<br>+# License along with this library; if not, write to the Free Software<br>+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA<br>
+<br>+usage() {<br>+    echo "usage: lxc-clone -o <orig> -n <new> [-s] [-h] [-L fssize] [-v vgname]"<br>+}<br>+<br>+help() {<br>+    usage<br>+    echo<br>+    echo "creates a lxc system object."<br>
+    echo<br>+    echo "Options:"<br>+    echo "orig        : name of the original container"<br>+    echo "new         : name of the new container"<br>+    echo "-s          : make the new rootfs a snapshot of the original"<br>
+    echo "fssize      : size if creating a new fs.  By default, 2G"<br>+    echo "vgname      : lvm volume group name, lxc by default"<br>+}<br>+<br>+shortoptions='ho:n:sL:v:'<br>+longoptions='help,orig:,name:,snapshot,fssize,vgname'<br>
+lxc_path=/var/lib/lxc<br>+bindir=/usr/bin<br>+snapshot=no<br>+lxc_size=2G<br>+lxc_vg=lxc<br>+<br>+getopt=$(getopt -o $shortoptions --longoptions  $longoptions -- "$@")<br>+if [ $? != 0 ]; then<br>+    usage<br>
+    exit 1;<br>+fi<br>+<br>+eval set -- "$getopt"<br>+<br>+while true; do<br>+        case "$1" in<br>+           -h|--help)<br>+               help<br>+               exit 1<br>+               ;;<br>
+           -s|--snapshot)<br>+               shift<br>+               snapshot=yes<br>+               ;;<br>+           -o|--orig)<br>+               shift<br>+               lxc_orig=$1<br>+               shift<br>+               ;;<br>
+           -L|--fssize)<br>+               shift<br>+               lxc_size=$1<br>+               shift<br>+               ;;<br>+           -v|--vgname)<br>+               shift<br>+               lxc_vg=$1<br>+               shift<br>
+               ;;<br>+           -n|--new)<br>+               shift<br>+               lxc_new=$1<br>+               shift<br>+               ;;<br>+            --)<br>+               shift<br>+               break;;<br>
+            *)<br>+               echo $1<br>+               usage<br>+               exit 1<br>+               ;;<br>+        esac<br>+done<br>+<br>+if [ -z "$lxc_path" ]; then<br>+    echo "no configuration path defined !"<br>
+    exit 1<br>+fi<br>+<br>+if [ ! -r $lxc_path ]; then<br>+    echo "configuration path '$lxc_path' not found"<br>+    exit 1<br>+fi<br>+<br>+if [ -z "$lxc_orig" ]; then<br>+    echo "no original container name specified"<br>
+    usage<br>+    exit 1<br>+fi<br>+<br>+if [ -z "$lxc_new" ]; then<br>+    echo "no new container name specified"<br>+    usage<br>+    exit 1<br>+fi<br>+<br>+if [ "$(id -u)" != "0" ]; then<br>
+   echo "This command has to be run as root"<br>+   exit 1<br>+fi<br>+<br>+if [ ! -r $lxc_path ]; then<br>+    echo "no configuration path defined !"<br>+    exit 1<br>+fi<br>+<br>+if [ ! -d "$lxc_path/$lxc_orig" ]; then<br>
+    echo "'$lxc_orig' does not exist"<br>+    exit 1<br>+fi<br>+<br>+if [ -d "$lxc_path/$lxc_new" ]; then<br>+    echo "'$lxc_new' already exists"<br>+    exit 1<br>+fi<br>+<br>
+trap "${bindir}/lxc-destroy -n $lxc_new; echo aborted; exit 1" SIGHUP SIGINT SIGTERM<br>+<br>+mkdir -p $lxc_path/$lxc_new<br>+<br>+echo "Tweaking configuration"<br>+cp $lxc_path/$lxc_orig/config $lxc_path/$lxc_new/config<br>
+sed -i '/lxc.utsname/d' $lxc_path/$lxc_new/config<br>+echo "lxc.utsname = $hostname" >> $lxc_path/$lxc_new/config<br>+<br>+sed -i '/lxc.mount/d' $lxc_path/$lxc_new/config<br>+echo "lxc.mount = $lxc_path/$lxc_new/fstab" >> $lxc_path/$lxc_new/config<br>
+<br>+cp $lxc_path/$lxc_orig/fstab $lxc_path/$lxc_new/fstab<br>+sed -i "s@$lxc_path/$lxc_orig@$lxc_path/$lxc_new@" $lxc_path/$lxc_new/fstab<br>+<br>+echo "Copying rootfs..."<br>+rootfs=$lxc_path/$lxc_new/rootfs<br>
+# First figure out if the old is a device.  For now we only support<br>+# lvm devices.<br>+mounted=0<br>+sed -i '/lxc.rootfs/d' $lxc_path/$lxc_new/config<br>+oldroot=`grep lxc.rootfs $lxc_path/$lxc_orig/config | awk -F= '{ print $2 '}`<br>
+if [ -b $oldroot ]; then<br>+       # this is a device.  If we don't want to snapshot, then mkfs, mount<br>+       # and rsync.  Trivial but not yet implemented<br>+       if [ $snapshot == "no" ]; then<br>
+               echo "non-snapshot and non-lvm clone of block device not yet implemented"<br>+               exit 1<br>+       fi<br>+       lvdisplay $oldroot > /dev/null 2>&1<br>+       if [ $? -ne 0 ]; then<br>
+               echo "non-snapshot and non-lvm clone of block device not yet implemented"<br>+               exit 1<br>+       fi<br>+       # ok, create a snapshot of the lvm device<br>+       lvcreate -s -L $lxc_size -n $lxc_new /dev/$lxc_vg/$lxc_orig || exit 1<br>
+       echo "lxc.rootfs = /dev/$lxc_vg/$lxc_new" >> $lxc_path/$lxc_new/config<br>+       # and mount it so we can tweak it<br>+       mkdir -p $lxc_path/$lxc_new/rootfs<br>+       mount /dev/$lxc_vg/$lxc_new $rootfs || { echo "failed to mount new rootfs"; exit 1; }<br>
+       mounted=1<br>+else<br>+       cp -a $lxc_path/$lxc_orig/rootfs $lxc_path/$lxc_new/rootfs || return 1<br>+       echo "lxc.rootfs = $rootfs" >> $lxc_path/$lxc_new/config<br>+fi<br>+<br>+echo "Updating rootfs..."<br>
+hostname=$lxc_new<br>+<br>+# so you can 'ssh $hostname.' or 'ssh $hostname.local'<br>+sed -i "s/send host-name.*$/send host-name $hostname/" $rootfs/etc/dhcp/dhclient.conf<br>+<br>+# set the hostname<br>
+cat <<EOF > $rootfs/etc/hostname<br>+$hostname<br>+EOF<br>+# set minimal hosts<br>+cat <<EOF > $rootfs/etc/hosts<br>+127.0.0.1 localhost $hostname<br>+EOF<br>+<br>+# if this was a block device, then umount it now<br>
+if [ $mounted -eq 1 ]; then<br>+       umount $rootfs<br>+fi<br>+<br>+echo "'$lxc_new' created"<br><br>=== modified file 'src/lxc/<a href="http://lxc-destroy.in/" target="_blank">lxc-destroy.in</a>'<br>
--- src/lxc/<a href="http://lxc-destroy.in/" target="_blank">lxc-destroy.in</a>      2010-01-10 10:40:21 +0000<br>+++ src/lxc/<a href="http://lxc-destroy.in/" target="_blank">lxc-destroy.in</a>      2011-03-29 23:00:34 +0000<br>
@@ -26,7 +26,8 @@<br> #<br><br> usage() {<br>-    echo "usage: $0 -n <name>"<br>+    echo "usage: $0 -n <name> [-l]"<br>+    echo "       if -l is specified, attempt to lvremove the rootfs device"<br>
 }<br><br> if [ "$(id -u)" != "0" ]; then<br>@@ -34,9 +35,9 @@<br>   exit 1<br> fi<br><br>-shortoptions='n:'<br>-longoptions='name:'<br>-lxc_path=@LXCPATH@<br>+shortoptions='n:l'<br>
+longoptions='name:,lvm'<br>+lxc_path=/var/lib/lxc<br><br> getopt=$(getopt -o $shortoptions --longoptions  $longoptions -- "$@")<br> if [ $? != 0 ]; then<br>@@ -46,6 +47,8 @@<br><br> eval set -- "$getopt"<br>
<br>+lvremove=0<br>+<br> while true; do<br>        case "$1" in<br>           -n|--name)<br>@@ -53,6 +56,10 @@<br>               lxc_name=$1<br>               shift<br>               ;;<br>+           -l|--lvm)<br>
+               shift<br>+               lvremove=1<br>+               ;;<br>            --)<br>               shift<br>               break;;<br>@@ -75,5 +82,13 @@<br>    exit 1<br> fi<br><br>+if [ $lvremove -eq 1 ]; then<br>
+    rootdev=`grep lxc.rootfs $lxc_path/$lxc_name/config | awk -F= '{ print $2 '}`<br>+    # only makes sense if it is a blockdev or a symlink to one<br>+    if [ -b $rootdev -o -h $rootdev ]; then<br>+           lvremove $rootdev<br>
+    fi<br>+fi<br>+<br> # recursively remove the container to remove old container configuration<br> rm -rf --preserve-root $lxc_path/$lxc_name<br><br><br>-----BEGIN PGP SIGNATURE-----<br>Version: GnuPG v1.4.10 (GNU/Linux)<br>
<br>iQEcBAEBAgAGBQJNk1pzAAoJEHmllQITXQdF7G4H/0xMrCVEzaFnmZAdo8jppR6E<br>tvo5fP1MtHlvu/SH+TbNEYv/Pd3TsqFllRomnBgKWPXbRVPmCY3gomoh+ec2wQOd<br>OYX8GMVCusqk2JTOTz/KD9YhBhYUEYrv2JRdXdYAav1yOdEhbtaJWWyO5L3qAV6M<br>lgoHrRqtuM0ueNVY5+0OIrhd5sHbxc/G1BXHERTkcPKWR7GwsyUjWOmjIL8bGQG/<br>
t0GKlyYAJPIbXDATW6Izp/R9q6+5tu8k9A+c2di2afFsS8l7ZhpUU+HhMTvqxYTJ<br>ajoRjfwzfhqbzGh1dnWRyLnRXL9Lfokkkhii0RPbVpIdTLRaYCuJ1Uh2v1im5i4=<br>=/Kxf<br>-----END PGP SIGNATURE-----<br><br>------------------------------------------------------------------------------<br>
Create and publish websites with WebMatrix<br>Use the most popular FREE web apps or write code yourself;<br>WebMatrix provides all the features you need to develop and<br>publish your website. <a href="http://p.sf.net/sfu/ms-webmatrix-sf" target="_blank">http://p.sf.net/sfu/ms-webmatrix-sf</a><br>
<br>_______________________________________________<br>Lxc-users mailing list<br><a href="mailto:Lxc-users@lists.sourceforge.net">Lxc-users@lists.sourceforge.net</a><br><a href="https://lists.sourceforge.net/lists/listinfo/lxc-users" target="_blank">https://lists.sourceforge.net/lists/listinfo/lxc-users</a><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>God Bless<br></div>