Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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.