On 04/25/2013 10:18 PM, Serge Hallyn wrote: > This is based on patch from Papp Tamas (thanks). It also does some > reorganizing of lxc-create to commonize some of the backingstore handling. > > I played with it using: > > sudo lvcreate -L 100G -n zfs vg0 > sudo zpool create lxc /dev/vg0/zfs > sudo lxc-create -B zfs --zfsroot lxc -t ubuntu -n dir2 > > or you could > > qemu-img create zfs.img 100G > sudo qemu-nbd -c /dev/nbd0 zfs.img > sudo zpool create lxc /dev/nbd0 > sudo lxc-create -B zfs --zfsroot lxc -t ubuntu -n dir2 > > I'll write the bdev.c handler and hook up lxc-clone next. > > This also fixses a bug in the sed expression to extract the rootfs from > container config, which prepended an extra '/' to the rootdev. (That > caused the zfs list entry not to match at destroy) > > Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com> > Cc: Papp Tamas <tom...@martos.bme.hu>
The only potential annoyance I can see is if we ever try to auto-detect LVM as it's way more verbose than the other checks and will throw a bunch of weird errors to the user who just wanted auto-detect. But LVM currently isn't in the _unset case so that's fine. Acked-by: Stéphane Graber <stgra...@ubuntu.com> > --- > src/lxc/lxc-create.in | 167 > ++++++++++++++++++++++++++++++++---------------- > src/lxc/lxc-destroy.in | 13 +++- > 2 files changed, 124 insertions(+), 56 deletions(-) > > diff --git a/src/lxc/lxc-create.in b/src/lxc/lxc-create.in > index fbb566f..3367a89 100644 > --- a/src/lxc/lxc-create.in > +++ b/src/lxc/lxc-create.in > @@ -22,6 +22,59 @@ > > . @DATADIR@/lxc/lxc.functions > > +verify_btrfs() { > + if which btrfs >/dev/null 2>&1 && \ > + btrfs filesystem df "$lxc_path/" >/dev/null 2>&1; then > + echo "btrfs" > + else > + echo "no" > + fi > +} > + > +verify_zfs() { > + if which zfs >/dev/null 2>&1 && zfs get all "$zfs_root" >/dev/null 2>&1; > then > + echo zfs > + else > + echo no > + fi > +} > + > +verify_lvm() { > + which vgscan > /dev/null 2>&1 > + if [ $? -ne 0 ]; then > + echo "vgscan not found (is lvm2 installed?)" >&2 > + echo no > + return > + fi > + > + grep -q "\<$fstype\>" /proc/filesystems > + if [ $? -ne 0 ]; then > + echo "$fstype is not listed in /proc/filesystems" >&2 > + echo no > + return > + fi > + > + vgscan | grep -q "Found volume group \"$vgname\"" > + if [ $? -ne 0 ]; then > + echo "could not find volume group \"$vgname\"" >&2 > + echo no > + return > + fi > + > + echo lvm > +} > + > +# if no backingstore is specified, auto-detect if $lxc_path is btrfs or zfs > +detect_backingstore() { > + if [ `verify_btrfs` = "btrfs" ]; then > + echo btrfs > + elif [ `verify_zfs` = "zfs" ]; then > + echo zfs > + else > + echo none > + fi > +} > + > usage() { > echo "usage: $(basename $0) -n NAME [-f CONFIG_FILE] [-t TEMPLATE] > [FS_OPTIONS] --" >&2 > echo " [-P lxcpath] [TEMPLATE_OPTIONS]" >&2 > @@ -32,6 +85,7 @@ usage() { > echo " -B lvm [--lvname LV_NAME] [--vgname VG_NAME] [--fstype FS_TYPE]" > >&2 > echo " [--fssize FS_SIZE]" >&2 > echo " -B btrfs" >&2 > + echo " -B zfs [--zfsroot PATH]" >&2 > } > > help() { > @@ -51,6 +105,7 @@ help() { > echo " --vgname VG_NAME specify the LVM volume group name (default: > lxc)" >&2 > echo " --fstype FS_TYPE specify the filesystem type (default: ext4)" > >&2 > echo " --fssize FS_SIZE specify the filesystem size (default: 500M)" > >&2 > + echo " --zfsroot PATH specify the zfs path for lxcpath (default: > tank/lxc)" >&2 > echo >&2 > if [ -z "$lxc_template" ]; then > echo "To see template-specific options, specify a template. For > example:" >&2 > @@ -140,6 +195,11 @@ while [ $# -gt 0 ]; do > fssize=$1 > shift > ;; > + --zfsroot) > + optarg_check $opt "$1" > + zfs_root=$1 > + shift > + ;; > --) > break;; > -?) > @@ -187,6 +247,10 @@ if [ -z "$lvname" ]; then > lvname="$lxc_name" > fi > > +if [ -z "$zfs_root" ]; then > + zfs_root="tank/lxc" > +fi > + > if [ "$(id -u)" != "0" ]; then > echo "$(basename $0): must be run as root" >&2 > exit 1 > @@ -196,10 +260,39 @@ if [ -n "$custom_rootfs" ] && [ "$backingstore" != > "dir" ]; then > echo "--dir is only valid with -B dir" > fi > > +# detect / verify backing store > case "$backingstore" in > - dir|lvm|none|btrfs|_unset) :;; > + btrfs) > + if [ `verify_btrfs` != 'btrfs' ]; then > + echo "missing 'btrfs' command or $lxc_path is not btrfs" >&2 > + exit 1 > + fi > + ;; > + zfs) > + if [ `verify_zfs` != 'zfs' ]; then > + echo "missing 'zfs' command or $zfs_root is not zfs" >&2 > + exit 1 > + fi > + ;; > + lvm) > + if [ `verify_lvm` != 'lvm' ]; then > + echo "system is missing 'lvm' support, or VG does not exist." >&2 > + exit 1 > + fi > + rootdev=/dev/$vgname/$lvname > + lvdisplay $rootdev > /dev/null 2>&1 > + if [ $? -eq 0 ]; then > + echo "LV $rootdev already exists" >&2 > + exit 1 > + fi > + ;; > + _unset) > + backingstore=`detect_backingstore` > + ;; > + dir|lvm|none) > + :;; > *) > - echo "$(basename $0): '$backingstore' is not known (try 'none', > 'dir', 'lvm', 'btrfs')" >&2 > + echo "$(basename $0): '$backingstore' is not known (try 'none', > 'dir', 'lvm', 'btrfs', 'zfs')" >&2 > usage > exit 1 > ;; > @@ -212,61 +305,14 @@ fi > > rootfs="$lxc_path/$lxc_name/rootfs" > > -if [ "$backingstore" = "_unset" ] || [ "$backingstore" = "btrfs" ]; then > -# if no backing store was given, then see if btrfs would work > - if which btrfs >/dev/null 2>&1 && \ > - btrfs filesystem df "$lxc_path/" >/dev/null 2>&1; then > - backingstore="btrfs" > - else > - if [ "$backingstore" = "btrfs" ]; then > - echo "$(basename $0): missing 'btrfs' command or $lxc_path is > not btrfs" >&2 > - exit 1; > - fi > - backingstore="none" > - fi > -fi > - > -if [ "$backingstore" = "lvm" ]; then > - which vgscan > /dev/null 2>&1 > - if [ $? -ne 0 ]; then > - echo "$(basename $0): vgscan not found (is lvm2 installed?)" >&2 > - exit 1 > - fi > - > - grep -q "\<$fstype\>" /proc/filesystems > - if [ $? -ne 0 ]; then > - echo "$(basename $0): $fstype is not listed in /proc/filesystems" >&2 > - exit 1 > - fi > - > - vgscan | grep -q "Found volume group \"$vgname\"" > - if [ $? -ne 0 ]; then > - echo "$(basename $0): could not find volume group \"$vgname\"" >&2 > - exit 1 > - fi > - > - rootdev=/dev/$vgname/$lvname > - lvdisplay $rootdev > /dev/null 2>&1 > - if [ $? -eq 0 ]; then > - echo "$(basename $0): backing store already exists: $rootdev" >&2 > - echo "please delete it (using \"lvremove $rootdev\") and try again" > >&2 > - exit 1 > - fi > - > -elif [ "$backingstore" = "btrfs" ]; then > - mkdir "$lxc_path/$lxc_name" > - if ! out=$(btrfs subvolume create "$rootfs" 2>&1); then > - echo "$(basename $0): failed to create subvolume in $rootfs: $out" > >&2 > - exit 1; > - fi > -fi > - > cleanup() { > if [ "$backingstore" = "lvm" ]; then > - umount $rootfs > - lvremove -f $rootdev > + umount -l $rootfs || true > + lvremove -f $rootdev || true > elif [ "$backingstore" = "btrfs" ]; then > - btrfs subvolume delete "$rootfs" > + btrfs subvolume delete "$rootfs" || true > + elif [ "$backingstore" = "zfs" ]; then > + zfs destroy "$zfs_root/$lxc_name" || true > fi > > ${bindir}/lxc-destroy -n $lxc_name > @@ -276,7 +322,18 @@ cleanup() { > > trap cleanup HUP INT TERM > > -mkdir -p $lxc_path/$lxc_name > +# set up container dir per backing store > +if [ "$backingstore" = "zfs" ]; then > + zfs create -omountpoint=$lxc_path/$lxc_name/rootfs "$zfs_root/$lxc_name" > +elif [ "$backingstore" = "btrfs" ]; then > + mkdir "$lxc_path/$lxc_name" > + if ! out=$(btrfs subvolume create "$rootfs" 2>&1); then > + echo "$(basename $0): failed to create subvolume in $rootfs: $out" > >&2 > + exit 1; > + fi > +else > + mkdir -p $lxc_path/$lxc_name > +fi > > if [ -z "$lxc_config" ]; then > lxc_config="@SYSCONFDIR@/lxc/default.conf" > diff --git a/src/lxc/lxc-destroy.in b/src/lxc/lxc-destroy.in > index 6514085..fc164c2 100644 > --- a/src/lxc/lxc-destroy.in > +++ b/src/lxc/lxc-destroy.in > @@ -46,6 +46,15 @@ usage_err() { > exit 1 > } > > +verify_zfs() { > + path=$1 > + if which zfs >/dev/null 2>&1 && zfs list | grep -q $path; then > + echo zfs > + else > + echo no > + fi > +} > + > optarg_check() { > if [ -z "$2" ]; then > usage_err "option '$1' requires an argument" > @@ -123,7 +132,7 @@ fi > # Deduce the type of rootfs > # If LVM partition, destroy it. For btrfs, we delete the subvolue. If > anything > # else, ignore it. We'll support deletion of others later. > -rootdev=`grep lxc.rootfs $lxc_path/$lxc_name/config 2>/dev/null | sed -e > 's/^[^/]*/\//'` > +rootdev=`grep lxc.rootfs $lxc_path/$lxc_name/config 2>/dev/null | sed -e > 's/^[^/]*//'` > if [ -n "$rootdev" ]; then > if [ -b "$rootdev" -o -h "$rootdev" ]; then > lvdisplay $rootdev > /dev/null 2>&1 > @@ -131,6 +140,8 @@ if [ -n "$rootdev" ]; then > echo "removing backing store: $rootdev" > lvremove -f $rootdev > fi > + elif [ `verify_zfs $rootdev` = "zfs" ]; then > + zfs destroy $(zfs list | grep $rootdev | awk '{ print $1 }') > elif [ -h "$rootdev" -o -d "$rootdev" ]; then > if which btrfs >/dev/null 2>&1 && > btrfs subvolume list "$rootdev" >/dev/null 2>&1; then > -- Stéphane Graber Ubuntu developer http://www.ubuntu.com
signature.asc
Description: OpenPGP digital signature
------------------------------------------------------------------------------ Try New Relic Now & We'll Send You this Cool Shirt New Relic is the only SaaS-based application performance monitoring service that delivers powerful full stack analytics. Optimize and monitor your browser, app, & servers with just a few lines of code. Try New Relic and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr
_______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel