mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-06 08:23:57 +00:00

1. implement bdev->create: python and lua: send NULL for bdevtype and bdevspecs. They'll want to be updated to pass those in in a way that makes sense, but I can't think about that right now. 2. templates: pass --rootfs If the container is backed by a device which must be mounted (i.e. lvm) then pass the actual rootfs mount destination to the templates. Note that the lxc.rootfs can be a mounted block device. The template should actually be installing the rootfs under the path where the lxc.rootfs is *mounted*. Still, some people like to run templates by hand and assume purely directory backed containers, so continue to support that use case (i.e. if no --rootfs is listed). Make sure the templates don't re-write lxc.rootfs if it is already in the config. (Most were already checking for that) 3. Replace lxc-create script with lxc_create.c program. Changelog: May 24: when creating a container, create $lxcpath/$name/partial, and flock it. When done, close that file and unlink it. In lxc_container_new() and lxcapi_start(), check for this file. If it is locked, create is ongoing. If it exists but is not locked, create() was killed - remove the container. May 24: dont disk-lock during lxcapi_create. The partial lock is sufficient. Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
361 lines
8.4 KiB
Bash
361 lines
8.4 KiB
Bash
#!/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
|
|
|
|
SUITE=${SUITE:-squeeze}
|
|
MIRROR=${MIRROR:-http://cdn.debian.net/debian}
|
|
|
|
configure_debian()
|
|
{
|
|
rootfs=$1
|
|
hostname=$2
|
|
|
|
# squeeze only has /dev/tty and /dev/tty0 by default,
|
|
# therefore creating missing device nodes for tty1-4.
|
|
for tty in $(seq 1 4); do
|
|
if [ ! -e $rootfs/dev/tty$tty ]; then
|
|
mknod $rootfs/dev/tty$tty c 4 $tty
|
|
fi
|
|
done
|
|
|
|
# configure the inittab
|
|
cat <<EOF > $rootfs/etc/inittab
|
|
id:3:initdefault:
|
|
si::sysinit:/etc/init.d/rcS
|
|
l0:0:wait:/etc/init.d/rc 0
|
|
l1:1:wait:/etc/init.d/rc 1
|
|
l2:2:wait:/etc/init.d/rc 2
|
|
l3:3:wait:/etc/init.d/rc 3
|
|
l4:4:wait:/etc/init.d/rc 4
|
|
l5:5:wait:/etc/init.d/rc 5
|
|
l6:6:wait:/etc/init.d/rc 6
|
|
# Normally not reached, but fallthrough in case of emergency.
|
|
z6:6:respawn:/sbin/sulogin
|
|
1:2345:respawn:/sbin/getty 38400 console
|
|
c1:12345:respawn:/sbin/getty 38400 tty1 linux
|
|
c2:12345:respawn:/sbin/getty 38400 tty2 linux
|
|
c3:12345:respawn:/sbin/getty 38400 tty3 linux
|
|
c4:12345:respawn:/sbin/getty 38400 tty4 linux
|
|
p6::ctrlaltdel:/sbin/init 6
|
|
p0::powerfail:/sbin/init 0
|
|
EOF
|
|
|
|
# disable selinux in debian
|
|
mkdir -p $rootfs/selinux
|
|
echo 0 > $rootfs/selinux/enforce
|
|
|
|
# configure the network using the dhcp
|
|
cat <<EOF > $rootfs/etc/network/interfaces
|
|
auto lo
|
|
iface lo inet loopback
|
|
|
|
auto eth0
|
|
iface eth0 inet dhcp
|
|
EOF
|
|
|
|
# set the hostname
|
|
cat <<EOF > $rootfs/etc/hostname
|
|
$hostname
|
|
EOF
|
|
|
|
# reconfigure some services
|
|
if [ -z "$LANG" ]; then
|
|
chroot $rootfs locale-gen en_US.UTF-8 UTF-8
|
|
chroot $rootfs update-locale LANG=en_US.UTF-8
|
|
else
|
|
chroot $rootfs locale-gen $LANG $(echo $LANG | cut -d. -f2)
|
|
chroot $rootfs update-locale LANG=$LANG
|
|
fi
|
|
|
|
# remove pointless services in a container
|
|
chroot $rootfs /usr/sbin/update-rc.d -f checkroot.sh remove
|
|
chroot $rootfs /usr/sbin/update-rc.d -f umountfs remove
|
|
chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh remove
|
|
chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh remove
|
|
|
|
echo "root:root" | chroot $rootfs chpasswd
|
|
echo "Root password is 'root', please change !"
|
|
|
|
return 0
|
|
}
|
|
|
|
cleanup()
|
|
{
|
|
rm -rf $cache/partial-$SUITE-$arch
|
|
rm -rf $cache/rootfs-$SUITE-$arch
|
|
}
|
|
|
|
download_debian()
|
|
{
|
|
packages=\
|
|
ifupdown,\
|
|
locales,\
|
|
libui-dialog-perl,\
|
|
dialog,\
|
|
isc-dhcp-client,\
|
|
netbase,\
|
|
net-tools,\
|
|
iproute,\
|
|
openssh-server
|
|
|
|
cache=$1
|
|
arch=$2
|
|
|
|
trap cleanup EXIT SIGHUP SIGINT SIGTERM
|
|
# check the mini debian was not already downloaded
|
|
mkdir -p "$cache/partial-$SUITE-$arch"
|
|
if [ $? -ne 0 ]; then
|
|
echo "Failed to create '$cache/partial-$SUITE-$arch' directory"
|
|
return 1
|
|
fi
|
|
|
|
# download a mini debian into a cache
|
|
echo "Downloading debian minimal ..."
|
|
debootstrap --verbose --variant=minbase --arch=$arch \
|
|
--include=$packages \
|
|
"$SUITE" "$cache/partial-$SUITE-$arch" $MIRROR
|
|
if [ $? -ne 0 ]; then
|
|
echo "Failed to download the rootfs, aborting."
|
|
return 1
|
|
fi
|
|
|
|
mv "$1/partial-$SUITE-$arch" "$1/rootfs-$SUITE-$arch"
|
|
echo "Download complete."
|
|
trap EXIT
|
|
trap SIGINT
|
|
trap SIGTERM
|
|
trap SIGHUP
|
|
|
|
return 0
|
|
}
|
|
|
|
copy_debian()
|
|
{
|
|
cache=$1
|
|
arch=$2
|
|
rootfs=$3
|
|
|
|
# make a local copy of the minidebian
|
|
echo -n "Copying rootfs to $rootfs..."
|
|
mkdir -p $rootfs
|
|
rsync -Ha "$cache/rootfs-$SUITE-$arch"/ $rootfs/ || return 1
|
|
return 0
|
|
}
|
|
|
|
install_debian()
|
|
{
|
|
cache="@LOCALSTATEDIR@/cache/lxc/debian"
|
|
rootfs=$1
|
|
mkdir -p @LOCALSTATEDIR@/lock/subsys/
|
|
(
|
|
flock -x 200
|
|
if [ $? -ne 0 ]; then
|
|
echo "Cache repository is busy."
|
|
return 1
|
|
fi
|
|
|
|
if which dpkg >/dev/null 2>&1 ; then
|
|
arch=$(dpkg --print-architecture)
|
|
else
|
|
arch=$(uname -m)
|
|
if [ "$arch" = "i686" ]; then
|
|
arch="i386"
|
|
elif [ "$arch" = "x86_64" ]; then
|
|
arch="amd64"
|
|
elif [ "$arch" = "armv7l" ]; then
|
|
arch="armhf"
|
|
fi
|
|
fi
|
|
|
|
echo "Checking cache download in $cache/rootfs-$SUITE-$arch ... "
|
|
if [ ! -e "$cache/rootfs-$SUITE-$arch" ]; then
|
|
download_debian $cache $arch
|
|
if [ $? -ne 0 ]; then
|
|
echo "Failed to download 'debian base'"
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
copy_debian $cache $arch $rootfs
|
|
if [ $? -ne 0 ]; then
|
|
echo "Failed to copy rootfs"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
|
|
) 200>@LOCALSTATEDIR@/lock/subsys/lxc-debian
|
|
|
|
return $?
|
|
}
|
|
|
|
copy_configuration()
|
|
{
|
|
path=$1
|
|
rootfs=$2
|
|
hostname=$3
|
|
|
|
grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config
|
|
cat <<EOF >> $path/config
|
|
lxc.tty = 4
|
|
lxc.pts = 1024
|
|
lxc.utsname = $hostname
|
|
lxc.cap.drop = sys_module mac_admin mac_override sys_time
|
|
|
|
# When using LXC with apparmor, uncomment the next line to run unconfined:
|
|
#lxc.aa_profile = unconfined
|
|
|
|
lxc.cgroup.devices.deny = a
|
|
# /dev/null and zero
|
|
lxc.cgroup.devices.allow = c 1:3 rwm
|
|
lxc.cgroup.devices.allow = c 1:5 rwm
|
|
# consoles
|
|
lxc.cgroup.devices.allow = c 5:1 rwm
|
|
lxc.cgroup.devices.allow = c 5:0 rwm
|
|
lxc.cgroup.devices.allow = c 4:0 rwm
|
|
lxc.cgroup.devices.allow = c 4:1 rwm
|
|
# /dev/{,u}random
|
|
lxc.cgroup.devices.allow = c 1:9 rwm
|
|
lxc.cgroup.devices.allow = c 1:8 rwm
|
|
lxc.cgroup.devices.allow = c 136:* rwm
|
|
lxc.cgroup.devices.allow = c 5:2 rwm
|
|
# rtc
|
|
lxc.cgroup.devices.allow = c 254:0 rm
|
|
|
|
# mounts point
|
|
lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0
|
|
lxc.mount.entry = sysfs sys sysfs defaults 0 0
|
|
EOF
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo "Failed to add configuration"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
clean()
|
|
{
|
|
cache="@LOCALSTATEDIR@/cache/lxc/debian"
|
|
|
|
if [ ! -e $cache ]; then
|
|
exit 0
|
|
fi
|
|
|
|
# lock, so we won't purge while someone is creating a repository
|
|
(
|
|
flock -x 200
|
|
if [ $? != 0 ]; then
|
|
echo "Cache repository is busy."
|
|
exit 1
|
|
fi
|
|
|
|
echo -n "Purging the download cache..."
|
|
rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
|
|
exit 0
|
|
|
|
) 200>@LOCALSTATEDIR@/lock/subsys/lxc-debian
|
|
}
|
|
|
|
usage()
|
|
{
|
|
cat <<EOF
|
|
$1 -h|--help -p|--path=<path> --clean
|
|
EOF
|
|
return 0
|
|
}
|
|
|
|
options=$(getopt -o hp:n:c -l help,rootfs:,path:,name:,clean -- "$@")
|
|
if [ $? -ne 0 ]; then
|
|
usage $(basename $0)
|
|
exit 1
|
|
fi
|
|
eval set -- "$options"
|
|
|
|
while true
|
|
do
|
|
case "$1" in
|
|
-h|--help) usage $0 && exit 0;;
|
|
-p|--path) path=$2; shift 2;;
|
|
--rootfs) rootfs=$2; shift 2;;
|
|
-n|--name) name=$2; shift 2;;
|
|
-c|--clean) clean=$2; shift 2;;
|
|
--) shift 1; break ;;
|
|
*) break ;;
|
|
esac
|
|
done
|
|
|
|
if [ ! -z "$clean" -a -z "$path" ]; then
|
|
clean || exit 1
|
|
exit 0
|
|
fi
|
|
|
|
type debootstrap
|
|
if [ $? -ne 0 ]; then
|
|
echo "'debootstrap' command is missing"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "$path" ]; then
|
|
echo "'path' parameter is required"
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$(id -u)" != "0" ]; then
|
|
echo "This script should be run as 'root'"
|
|
exit 1
|
|
fi
|
|
|
|
# detect rootfs
|
|
config="$path/config"
|
|
if [ -z "$rootfs" ]; then
|
|
if grep -q '^lxc.rootfs' $config 2>/dev/null ; then
|
|
rootfs=`grep 'lxc.rootfs =' $config | awk -F= '{ print $2 }'`
|
|
else
|
|
rootfs=$path/rootfs
|
|
fi
|
|
fi
|
|
|
|
|
|
install_debian $rootfs
|
|
if [ $? -ne 0 ]; then
|
|
echo "failed to install debian"
|
|
exit 1
|
|
fi
|
|
|
|
configure_debian $rootfs $name
|
|
if [ $? -ne 0 ]; then
|
|
echo "failed to configure debian for a container"
|
|
exit 1
|
|
fi
|
|
|
|
copy_configuration $path $rootfs $name
|
|
if [ $? -ne 0 ]; then
|
|
echo "failed write configuration file"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -z $clean ]; then
|
|
clean || exit 1
|
|
exit 0
|
|
fi
|