[lxc-devel] [PATCH 1/1] lxc-create: add zfs support

Serge Hallyn serge.hallyn at ubuntu.com
Sun Apr 21 03:59:53 UTC 2013


<ping> Any feedback on this patch?

I also have a question on behavior details.  Until now, we've set up
btrfs containers so that $lxcpath is a subvolume, and then each
$rootfs is a subvolume.  With zfs, per Papp's request, we're making
the (zfs equivalent of a subvolume) at the $lxcpath/$lxc_name.  So
that means when we make a snapshot clone, we'll be doing them
differently for different filesystems.

I don't really care which we do - and even if we keep them different
for hysterical raisins it's not biggie technically, since the
filesystems have to be handled differently at clone anyway.  But
it'll be harder to explain to users what's going on.

With the btrfs way, when we snapshot-clone a container we have to
manually copy all the config and hooks files.  We have to process
them anyway (s/oldname/newname etc) though.  With the zfs way we
wouldn't have to copy them - so files which we didn't predict won't
be copied.  That may be a good thing - if we didn't predict it, then
we probably didn't process it anyway so it may not be safe.  Still
the zfs way feels elegant...

Preferences?

-serge

Quoting Serge Hallyn (serge.hallyn at ubuntu.com):
> 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 didn't test on btrfs or zfs, but did test that '-B btrfs' and
> '-B zfs' properly fail when needed, and that lvm and dir and
> _unset still work as they should.
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
> Cc: Papp Tamas <tompos at martos.bme.hu>
> ---
>  src/lxc/lxc-create.in | 167 +++++++++++++++++++++++++++++++++-----------------
>  1 file changed, 112 insertions(+), 55 deletions(-)
> 
> diff --git a/src/lxc/lxc-create.in b/src/lxc/lxc-create.in
> index ebbdd7b..de403da 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"
> +            zfsroot=$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 "$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"
> -- 
> 1.8.1.2
> 
> 
> ------------------------------------------------------------------------------
> Precog is a next-generation analytics platform capable of advanced
> analytics on semi-structured data. The platform includes APIs for building
> apps and a phenomenal toolset for data science. Developers can use
> our toolset for easy data analysis & visualization. Get a free account!
> http://www2.precog.com/precogplatform/slashdotnewsletter
> _______________________________________________
> Lxc-devel mailing list
> Lxc-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel




More information about the lxc-devel mailing list