Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

319 lines (277 sloc) 8.072 kb
#!/bin/bash
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
usage() {
echo "usage: $(basename $0) -n NAME [-f CONFIG_FILE] [-t TEMPLATE] [FS_OPTIONS] --" >&2
echo " [TEMPLATE_OPTIONS]" >&2
echo >&2
echo "where FS_OPTIONS is one of:" >&2
echo " -B none" >&2
echo " -B dir [--dir rootfs_dir]" >&2
echo " -B lvm [--lvname LV_NAME] [--vgname VG_NAME] [--fstype FS_TYPE]" >&2
echo " [--fssize FS_SIZE]" >&2
echo " -B btrfs" >&2
}
help() {
usage
echo >&2
echo "Create a new container on the system." >&2
echo >&2
echo "Options:" >&2
echo " -n NAME specify the name of the container" >&2
echo " -f CONFIG_FILE use an existing configuration file" >&2
echo " -t TEMPLATE use an accessible template script" >&2
echo " -B BACKING_STORE alter the container backing store (default: none)" >&2
echo " --lvname LV_NAME specify the LVM logical volume name" >&2
echo " (default: container name)" >&2
echo " --dir ROOTFS_DIR specify path for custom rootfs directory location" >&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 " --fssize FS_SIZE specify the filesystem size (default: 500M)" >&2
echo >&2
if [ -z $lxc_template ]; then
echo "To see template-specific options, specify a template. For example:" >&2
echo " $(basename $0) -t ubuntu -h" >&2
exit 0
fi
type ${templatedir}/lxc-$lxc_template 2>/dev/null
if [ $? -eq 0 ]; then
echo >&2
echo "Template-specific options (TEMPLATE_OPTIONS):" >&2
${templatedir}/lxc-$lxc_template -h
fi
}
shortoptions='hn:f:t:B:'
longoptions='help,name:,config:,template:,backingstore:,fstype:,dir:,lvname:,vgname:,fssize:'
lxc_path=@LXCPATH@
bindir=@BINDIR@
templatedir=@LXCTEMPLATEDIR@
backingstore=_unset
fstype=ext4
fssize=500M
vgname=lxc
custom_rootfs=""
getopt=$(getopt -o $shortoptions --longoptions $longoptions -- "$@")
if [ $? != 0 ]; then
usage
exit 1;
fi
eval set -- "$getopt"
while true; do
case "$1" in
-h|--help)
help
exit 1
;;
-n|--name)
shift
lxc_name=$1
shift
;;
-f|--config)
shift
lxc_config=$1
shift
;;
-t|--template)
shift
lxc_template=$1
shift
;;
-B|--backingstore)
shift
backingstore=$1
shift
;;
--dir)
shift
custom_rootfs=$1
shift
;;
--lvname)
shift
lvname=$1
shift
;;
--vgname)
shift
vgname=$1
shift
;;
--fstype)
shift
fstype=$1
shift
;;
--fssize)
shift
fssize=$1
shift
;;
--)
shift
break;;
*)
usage
exit 1
;;
esac
done
# If -h or --help was passed into the container, we'll want to cleanup
# afterward
wantedhelp=0
for var in "$@"
do
if [ "$var" = "-h" -o "$var" = "--help" ]; then
help
exit 1
fi
done
if [ -z "$lxc_path" ]; then
echo "$(basename $0): no configuration path defined" >&2
exit 1
fi
if [ ! -r $lxc_path ]; then
echo "$(basename $0): configuration path '$lxc_path' not found" >&2
exit 1
fi
if [ -z "$lxc_name" ]; then
echo "$(basename $0): no container name specified" >&2
usage
exit 1
fi
if [ -z "$lvname" ]; then
lvname="$lxc_name"
fi
if [ "$(id -u)" != "0" ]; then
echo "$(basename $0): must be run as root" >&2
exit 1
fi
if [ -n "$custom_rootfs" -a "$backingstore" != "dir" ]; then
echo "--dir is only valid with -B dir"
fi
case "$backingstore" in
dir|lvm|none|btrfs|_unset) :;;
*) echo "$(basename $0): '$backingstore' is not known (try 'none', 'dir', 'lvm', 'btrfs')" >&2
usage
exit 1
;;
esac
if [ -d "$lxc_path/$lxc_name" ]; then
echo "$(basename $0): '$lxc_name' already exists" >&2
exit 1
fi
rootfs="$lxc_path/$lxc_name/rootfs"
if [ "$backingstore" = "_unset" -o "$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
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
fi
${bindir}/lxc-destroy -n $lxc_name
echo "$(basename $0): aborted" >&2
exit 1
}
trap cleanup HUP INT TERM
mkdir -p $lxc_path/$lxc_name
if [ -z "$lxc_config" ]; then
lxc_config="@SYSCONFDIR@/lxc/lxc.conf"
echo
echo "$(basename $0): No config file specified, using the default config $lxc_config"
fi
if [ ! -r "$lxc_config" ]; then
echo "$(basename $0): '$lxc_config' configuration file not found" >&2
exit 1
fi
cp $lxc_config $lxc_path/$lxc_name/config
if [ -n "$custom_rootfs" ]; then
if grep -q "lxc.rootfs" $lxc_path/$lxc_name/config ; then
echo "configuration file already specifies a lxc.rootfs"
exit 1
fi
echo "lxc.rootfs = $custom_rootfs" >> $lxc_path/$lxc_name/config
fi
# Create the fs as needed
if [ $backingstore = "lvm" ]; then
[ -d "$rootfs" ] || mkdir $rootfs
lvcreate -L $fssize -n $lvname $vgname || exit 1
udevadm settle
mkfs -t $fstype $rootdev || exit 1
mount -t $fstype $rootdev $rootfs
fi
if [ ! -z $lxc_template ]; then
type ${templatedir}/lxc-$lxc_template 2>/dev/null
if [ $? -ne 0 ]; then
echo "$(basename $0): unknown template '$lxc_template'" >&2
cleanup
fi
${templatedir}/lxc-$lxc_template --path=$lxc_path/$lxc_name --name=$lxc_name $*
if [ $? -ne 0 ]; then
echo "$(basename $0): failed to execute template '$lxc_template'" >&2
cleanup
fi
echo "'$lxc_template' template installed"
fi
if [ $backingstore = "lvm" ]; then
echo "Unmounting LVM"
umount $rootfs
# TODO: make the templates set this right from the start?
sed -i '/lxc.rootfs/d' $lxc_path/$lxc_name/config
echo "lxc.rootfs = $rootdev" >> $lxc_path/$lxc_name/config
fi
echo "'$lxc_name' created"
Jump to Line
Something went wrong with that request. Please try again.