[lxc-devel] [PATCH] add zfs support to lxc-create and lxc-destroy
Stéphane Graber
stgraber at ubuntu.com
Fri Apr 26 07:59:53 UTC 2013
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.hallyn at ubuntu.com>
> Cc: Papp Tamas <tompos at 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 <stgraber at 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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 901 bytes
Desc: OpenPGP digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20130426/7c98dd66/attachment.pgp>
More information about the lxc-devel
mailing list