Commit 33c2c3ec by Serge Hallyn Committed by Stéphane Graber

add zfs support to lxc-create and lxc-destroy

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: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com> Cc: Papp Tamas <tompos@martos.bme.hu> Acked-by: 's avatarStéphane Graber <stgraber@ubuntu.com>
parent f485f377
...@@ -22,6 +22,59 @@ ...@@ -22,6 +22,59 @@
. @DATADIR@/lxc/lxc.functions . @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() { usage() {
echo "usage: $(basename $0) -n NAME [-f CONFIG_FILE] [-t TEMPLATE] [FS_OPTIONS] --" >&2 echo "usage: $(basename $0) -n NAME [-f CONFIG_FILE] [-t TEMPLATE] [FS_OPTIONS] --" >&2
echo " [-P lxcpath] [TEMPLATE_OPTIONS]" >&2 echo " [-P lxcpath] [TEMPLATE_OPTIONS]" >&2
...@@ -32,6 +85,7 @@ usage() { ...@@ -32,6 +85,7 @@ usage() {
echo " -B lvm [--lvname LV_NAME] [--vgname VG_NAME] [--fstype FS_TYPE]" >&2 echo " -B lvm [--lvname LV_NAME] [--vgname VG_NAME] [--fstype FS_TYPE]" >&2
echo " [--fssize FS_SIZE]" >&2 echo " [--fssize FS_SIZE]" >&2
echo " -B btrfs" >&2 echo " -B btrfs" >&2
echo " -B zfs [--zfsroot PATH]" >&2
} }
help() { help() {
...@@ -51,6 +105,7 @@ help() { ...@@ -51,6 +105,7 @@ help() {
echo " --vgname VG_NAME specify the LVM volume group name (default: lxc)" >&2 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 " --fstype FS_TYPE specify the filesystem type (default: ext4)" >&2
echo " --fssize FS_SIZE specify the filesystem size (default: 500M)" >&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 echo >&2
if [ -z "$lxc_template" ]; then if [ -z "$lxc_template" ]; then
echo "To see template-specific options, specify a template. For example:" >&2 echo "To see template-specific options, specify a template. For example:" >&2
...@@ -140,6 +195,11 @@ while [ $# -gt 0 ]; do ...@@ -140,6 +195,11 @@ while [ $# -gt 0 ]; do
fssize=$1 fssize=$1
shift shift
;; ;;
--zfsroot)
optarg_check $opt "$1"
zfs_root=$1
shift
;;
--) --)
break;; break;;
-?) -?)
...@@ -187,6 +247,10 @@ if [ -z "$lvname" ]; then ...@@ -187,6 +247,10 @@ if [ -z "$lvname" ]; then
lvname="$lxc_name" lvname="$lxc_name"
fi fi
if [ -z "$zfs_root" ]; then
zfs_root="tank/lxc"
fi
if [ "$(id -u)" != "0" ]; then if [ "$(id -u)" != "0" ]; then
echo "$(basename $0): must be run as root" >&2 echo "$(basename $0): must be run as root" >&2
exit 1 exit 1
...@@ -196,10 +260,39 @@ if [ -n "$custom_rootfs" ] && [ "$backingstore" != "dir" ]; then ...@@ -196,10 +260,39 @@ if [ -n "$custom_rootfs" ] && [ "$backingstore" != "dir" ]; then
echo "--dir is only valid with -B dir" echo "--dir is only valid with -B dir"
fi fi
# detect / verify backing store
case "$backingstore" in 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 usage
exit 1 exit 1
;; ;;
...@@ -212,61 +305,14 @@ fi ...@@ -212,61 +305,14 @@ fi
rootfs="$lxc_path/$lxc_name/rootfs" 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() { cleanup() {
if [ "$backingstore" = "lvm" ]; then if [ "$backingstore" = "lvm" ]; then
umount $rootfs umount -l $rootfs || true
lvremove -f $rootdev lvremove -f $rootdev || true
elif [ "$backingstore" = "btrfs" ]; then 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 fi
${bindir}/lxc-destroy -n $lxc_name ${bindir}/lxc-destroy -n $lxc_name
...@@ -276,7 +322,18 @@ cleanup() { ...@@ -276,7 +322,18 @@ cleanup() {
trap cleanup HUP INT TERM 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 if [ -z "$lxc_config" ]; then
lxc_config="@SYSCONFDIR@/lxc/default.conf" lxc_config="@SYSCONFDIR@/lxc/default.conf"
......
...@@ -46,6 +46,15 @@ usage_err() { ...@@ -46,6 +46,15 @@ usage_err() {
exit 1 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() { optarg_check() {
if [ -z "$2" ]; then if [ -z "$2" ]; then
usage_err "option '$1' requires an argument" usage_err "option '$1' requires an argument"
...@@ -123,7 +132,7 @@ fi ...@@ -123,7 +132,7 @@ fi
# Deduce the type of rootfs # Deduce the type of rootfs
# If LVM partition, destroy it. For btrfs, we delete the subvolue. If anything # If LVM partition, destroy it. For btrfs, we delete the subvolue. If anything
# else, ignore it. We'll support deletion of others later. # 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 [ -n "$rootdev" ]; then
if [ -b "$rootdev" -o -h "$rootdev" ]; then if [ -b "$rootdev" -o -h "$rootdev" ]; then
lvdisplay $rootdev > /dev/null 2>&1 lvdisplay $rootdev > /dev/null 2>&1
...@@ -131,6 +140,8 @@ if [ -n "$rootdev" ]; then ...@@ -131,6 +140,8 @@ if [ -n "$rootdev" ]; then
echo "removing backing store: $rootdev" echo "removing backing store: $rootdev"
lvremove -f $rootdev lvremove -f $rootdev
fi fi
elif [ `verify_zfs $rootdev` = "zfs" ]; then
zfs destroy $(zfs list | grep $rootdev | awk '{ print $1 }')
elif [ -h "$rootdev" -o -d "$rootdev" ]; then elif [ -h "$rootdev" -o -d "$rootdev" ]; then
if which btrfs >/dev/null 2>&1 && if which btrfs >/dev/null 2>&1 &&
btrfs subvolume list "$rootdev" >/dev/null 2>&1; then btrfs subvolume list "$rootdev" >/dev/null 2>&1; then
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment