#!/bin/bash # # lxc: linux Container library # Authors: # Daniel Lezcano # 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: lxc-create -n [-f configuration] [-t template] [-h] [fsopts] -- [template_options]" echo " fsopts: -B none" echo " fsopts: -B lvm [--lvname lvname] [--vgname vgname] [--fstype fstype] [--fssize fssize]" echo " fsopts: -B btrfs" echo " flag is not necessary, if possible btrfs support will be used" # echo " fsopts: -B union [--uniontype overlayfs]" # echo " fsopts: -B loop [--fstype fstype] [--fssize fssize]" # echo " fsopts: -B qemu-nbd [--type qed|qcow2|raw] [--fstype fstype] [--fssize fssize] # Qemu qed disk format" } help() { usage echo echo "creates a lxc system object." echo echo "Options:" echo "name : name of the container" echo "configuration: lxc configuration" echo "template : lxc-template is an accessible template script" echo echo "The container backing store can be altered using '-B'. By default it" echo "is 'none', which is a simple directory tree under /var/lib/lxc//rootfs" echo "Otherwise, the following option values may be relevant:" echo "lvname : [for -lvm] name of lv in which to create lv," echo " container-name by default" echo "vgname : [for -lvm] name of vg in which to create lv, 'lxc' by default" echo "fstype : name of filesystem to create, ext4 by default" echo "fssize : size of filesystem to create, 500M by default" echo if [ -z $lxc_template ]; then echo "for template-specific help, specify a template, for instance:" echo "lxc-create -t ubuntu -h" exit 0 fi type ${templatedir}/lxc-$lxc_template >/dev/null echo echo "template-specific help follows: (these options follow '--')" if [ $? -eq 0 ]; then ${templatedir}/lxc-$lxc_template -h fi } shortoptions='hn:f:t:B:' longoptions='help,name:,config:,template:,backingstore:,fstype:,lvname:,vgname:,fssize:' localstatedir=@LOCALSTATEDIR@ lxc_path=@LXCPATH@ bindir=@BINDIR@ libdir=@LIBDIR@ templatedir=@LXCTEMPLATEDIR@ backingstore=_unset fstype=ext4 fssize=500M vgname=lxc 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 ;; --lvname) shift lvname=$1 shift ;; --vgname) shift vgname=$1 shift ;; --fstype) shift fstype=$1 shift ;; --fssize) shift fssize=$1 shift ;; --) shift break;; *) echo $1 usage exit 1 ;; esac done if [ -z "$lxc_path" ]; then echo "no configuration path defined !" exit 1 fi if [ ! -r $lxc_path ]; then echo "configuration path '$lxc_path' not found" exit 1 fi if [ -z "$lxc_name" ]; then echo "no container name specified" usage exit 1 fi if [ -z "$lvname" ]; then lvname="$lxc_name" fi if [ "$(id -u)" != "0" ]; then echo "This command has to be run as root" exit 1 fi case "$backingstore" in lvm|none|btrfs|_unset) :;; *) echo "'$backingstore' is not known ('none', 'lvm', 'btrfs')" usage exit 1 ;; esac if [ -d "$lxc_path/$lxc_name" ]; then echo "'$lxc_name' already exists" 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 "missing 'btrfs' command or $lxc_path is not btrfs"; exit 1; fi backingstore="none" fi fi if [ $backingstore = "lvm" ]; then which vgscan > /dev/null if [ $? -ne 0 ]; then echo "vgscan not found. Please install lvm2 package" exit 1 fi grep -q "\<$fstype\>" /proc/filesystems if [ $? -ne 0 ]; then echo "$fstype is not listed in /proc/filesystems" usage exit 1 fi vgscan | grep -q "Found volume group \"$vgname\"" if [ $? -ne 0 ]; then echo "Could not find volume group \"$vgname\"" usage exit 1 fi rootdev=/dev/$vgname/$lvname lvdisplay $rootdev > /dev/null 2>&1 if [ $? -eq 0 ]; then echo "backing store already exists: $rootdev" echo "please delete it (using \"lvremove $rootdev\") and try again" exit 1 fi elif [ "$backingstore" = "btrfs" ]; then mkdir "$lxc_path/$lxc_name" if ! out=$(btrfs subvolume create "$rootfs" 2>&1); then echo "failed to create subvolume in $rootfs: $out"; exit 1; fi fi cleanup() { if [ $backingstore = "lvm" ]; then umount $rootfs lvremove -f $rootdev fi ${bindir}/lxc-destroy -n $lxc_name echo aborted exit 1 } trap cleanup SIGHUP SIGINT SIGTERM mkdir -p $lxc_path/$lxc_name if [ -z "$lxc_config" ]; then touch $lxc_path/$lxc_name/config else if [ ! -r "$lxc_config" ]; then echo "'$lxc_config' configuration file not found" exit 1 fi cp $lxc_config $lxc_path/$lxc_name/config fi # Create the fs as needed [ -d "$rootfs" ] || mkdir $rootfs if [ $backingstore = "lvm" ]; then 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 >/dev/null if [ $? -ne 0 ]; then echo "unknown template '$lxc_template'" cleanup fi if [ -z "$lxc_config" ]; then echo echo "Warning:" echo "-------" echo "Usually the template option is called with a configuration" echo "file option too, mostly to configure the network." echo "eg. lxc-create -n foo -f lxc.conf -t debian" echo "The configuration file is often:" echo echo "lxc.network.type=macvlan" echo "lxc.network.link=eth0" echo "lxc.network.flags=up" echo echo "or alternatively:" echo echo "lxc.network.type=veth" echo "lxc.network.link=br0" echo "lxc.network.flags=up" echo echo "For more information look at lxc.conf (5)" echo echo "At this point, I assume you know what you do." echo "Press to continue ..." read dummy fi ${templatedir}/lxc-$lxc_template --path=$lxc_path/$lxc_name --name=$lxc_name $* if [ $? -ne 0 ]; then echo "failed to execute template '$lxc_template'" 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"