diff options
Diffstat (limited to 'source/ap/lxc/lxc-slackware.in')
-rw-r--r-- | source/ap/lxc/lxc-slackware.in | 489 |
1 files changed, 489 insertions, 0 deletions
diff --git a/source/ap/lxc/lxc-slackware.in b/source/ap/lxc/lxc-slackware.in new file mode 100644 index 00000000..6049d2a5 --- /dev/null +++ b/source/ap/lxc/lxc-slackware.in @@ -0,0 +1,489 @@ +#!/bin/bash + +# +# lxc: linux Container library + +# Authors: +# Daniel Lezcano <daniel.lezcano@free.fr> + +# Template for slackware by Matteo Bernardini <ponce@slackbuilds.org> +# some parts are taken from the debian one (used as model) + +# 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 + +cache=${cache:-/var/cache/lxc/slackware} + +# Use the primary Slackware site by default, but please consider changing +# this to a closer mirror site. +MIRROR=${MIRROR:-http://ftp.slackware.com/pub/slackware} + +if [ -z "$arch" ]; then +case "$( uname -m )" in + i?86) arch=i486 ;; + arm*) arch=arm ;; + *) arch=$( uname -m ) ;; +esac +fi + +configure_slackware() +{ +rootfs=$1 +hostname=$2 + +echo "Configuring..." ; echo + +# The next part contains excerpts taken from SeTconfig (written by +# Patrick Volkerding) from the slackware setup disk. +# But before pasting them just set a variable to use them as they are +T_PX=$rootfs + +( cd $T_PX ; chmod 755 ./ ) +( cd $T_PX ; chmod 755 ./var ) +if [ -d $T_PX/usr/src/linux ]; then + chmod 755 $T_PX/usr/src/linux +fi +if [ ! -d $T_PX/proc ]; then + mkdir $T_PX/proc + chown root.root $T_PX/proc +fi +if [ ! -d $T_PX/sys ]; then + mkdir $T_PX/sys + chown root.root $T_PX/sys +fi +chmod 1777 $T_PX/tmp +if [ ! -d $T_PX/var/spool/mail ]; then + mkdir -p $T_PX/var/spool/mail + chmod 755 $T_PX/var/spool + chown root.mail $T_PX/var/spool/mail + chmod 1777 $T_PX/var/spool/mail +fi + +echo "#!/bin/sh" > $T_PX/etc/rc.d/rc.keymap +echo "# Load the keyboard map. More maps are in /usr/share/kbd/keymaps." \ + >> $T_PX/etc/rc.d/rc.keymap +echo "if [ -x /usr/bin/loadkeys ]; then" >> $T_PX/etc/rc.d/rc.keymap +echo " /usr/bin/loadkeys us" >> $T_PX/etc/rc.d/rc.keymap +echo "fi" >> $T_PX/etc/rc.d/rc.keymap +chmod 755 $T_PX/etc/rc.d/rc.keymap + +# Network configuration is left to the user, that have to edit +# /etc/rc.d/rc.inet1.conf and /etc/resolv.conf of the container +# just set the hostname +cat <<EOF > $rootfs/etc/HOSTNAME +$hostname.example.net +EOF +cp $rootfs/etc/HOSTNAME $rootfs/etc/hostname + +# make needed devices, from Chris Willing's MAKEDEV.sh +# http://www.vislab.uq.edu.au/howto/lxc/MAKEDEV.sh +DEV=$rootfs/dev +mkdir -p ${DEV} +mknod -m 666 ${DEV}/null c 1 3 +mknod -m 666 ${DEV}/zero c 1 5 +mknod -m 666 ${DEV}/random c 1 8 +mknod -m 666 ${DEV}/urandom c 1 9 +mkdir -m 755 ${DEV}/pts +mkdir -m 1777 ${DEV}/shm +mknod -m 666 ${DEV}/tty c 5 0 +mknod -m 600 ${DEV}/console c 5 1 +mknod -m 666 ${DEV}/tty0 c 4 0 +mknod -m 666 ${DEV}/tty1 c 4 1 +mknod -m 666 ${DEV}/tty2 c 4 2 +mknod -m 666 ${DEV}/tty3 c 4 3 +mknod -m 666 ${DEV}/tty4 c 4 4 +mknod -m 666 ${DEV}/tty5 c 4 5 +mknod -m 666 ${DEV}/full c 1 7 +mknod -m 600 ${DEV}/initctl p +mknod -m 660 ${DEV}/loop0 b 7 0 +mknod -m 660 ${DEV}/loop1 b 7 1 +ln -s pts/ptmx ${DEV}/ptmx +ln -s /proc/self/fd ${DEV}/fd + +echo "Adding an etc/fstab that must be modified later with the" +echo "full path of the container's rootfs if you decide to move it." +cat >$rootfs/etc/fstab <<EOF +lxcpts $rootfs/dev/pts devpts defaults,newinstance 0 0 +none $rootfs/proc proc defaults 0 0 +none $rootfs/sys sysfs defaults 0 0 +none /dev/shm tmpfs defaults 0 0 +none /run tmpfs defaults,mode=0755 0 0 +EOF + +# Back up the existing init scripts and install the lxc versions: +( cd $rootfs/etc/rc.d + cp -a /usr/share/lxc/scripts/slackware/* . + chmod 755 *.lxc + for file in *.lxc ; do + cp -a $(basename $file .lxc) $(basename $file .lxc).orig + cp -a $file $(basename $file .lxc) + done +) + +# restart rc.inet1 to have routing for the loop device +echo "/etc/rc.d/rc.inet1 restart" >> $rootfs/etc/rc.d/rc.local + +# reduce the number of local consoles: two should be enough +sed -i '/^c3\|^c4\|^c5\|^c6/s/^/# /' $rootfs/etc/inittab + +# In a container, use shutdown for powerfail conditions. LXC sends the SIGPWR +# signal to init to shut down the container with lxc-stop and without this the +# container will be force stopped after a one minute timeout. +sed -i "s,pf::powerfail:/sbin/genpowerfail start,pf::powerfail:/sbin/shutdown -h now,g" $rootfs/etc/inittab +sed -i "s,pg::powerokwait:/sbin/genpowerfail stop,pg::powerokwait:/sbin/shutdown -c,g" $rootfs/etc/inittab + +# set a default combination for the luggage +echo "root:root" | chroot $rootfs chpasswd +echo "Root default password is 'root', please change it!" + +# borrow the time configuration from the local machine +cp -a /etc/localtime $rootfs/etc/localtime + +return 0 +} + +copy_slackware() +{ +rootfs=$1 + +# make a local copy of the installed filesystem +echo -n "Copying rootfs to $rootfs..." +mkdir -p $rootfs +cp -a $cache/rootfs-$release-$arch/* $rootfs/ || exit 1 + +# fix fstab with the actual path +sed -i "s|$cache/rootfs-$release-$arch|$rootfs|" $rootfs/etc/fstab + +return 0 +} + +install_slackware() +{ +rootfs=$1 +mkdir -p /var/lock/subsys/ +( +flock -n -x 200 +if [ $? -ne 0 ]; then + echo "Cache repository is busy." + return 1 +fi + +if [ "$arch" == "x86_64" ]; then + PKGMAIN=slackware64 +elif [ "$arch" == "arm" ]; then + PKGMAIN=slackwarearm +else + PKGMAIN=slackware +fi + +export CONF=$cache/slackpkg-conf +export ROOT=$cache/rootfs-$release-$arch + +mkdir -p $cache/cache-$release-$arch $cache/rootfs-$release-$arch \ + $cache/slackpkg-$release-$arch $CONF/templates + +echo "$MIRROR/$PKGMAIN-$release/" > $CONF/mirrors +touch $CONF/blacklist + +cat <<EOF > $CONF/slackpkg.conf +# v2.8 +ARCH=$arch +TEMP=$cache/cache-$release-$arch +WORKDIR=$cache/slackpkg-$release-$arch +DELALL=off +CHECKMD5=on +CHECKGPG=on +CHECKSIZE=off +PRIORITY=( patches %PKGMAIN extra pasture testing ) +POSTINST=on +ONLY_NEW_DOTNEW=off +ONOFF=on +DOWNLOAD_ALL=on +DIALOG=off +BATCH=on +DEFAULT_ANSWER=y +USE_INCLUDES=on +SPINNING=off +EOF + +# thanks to Vincent Batts for this list of packages +# (that I modified a little :P) +# http://connie.slackware.com/~vbatts/minimal/ +cat <<EOF > $CONF/templates/minimal-lxc.template +aaa_base +aaa_elflibs +aaa_terminfo +bash +bin +bzip2 +coreutils +dcron +dhcpcd +dialog +diffutils +e2fsprogs +elvis +etc +eudev +findutils +gawk +glibc-solibs +gnupg +grep +gzip +iputils +logrotate +mpfr +net-tools +network-scripts +ncurses +openssh +openssl-solibs +pkgtools +procps-ng +sed +shadow +sharutils +slackpkg +sysklogd +sysvinit +sysvinit-functions +sysvinit-scripts +tar +util-linux +wget +which +xz +EOF + +TEMPLATE=${TEMPLATE:-minimal-lxc} +if [ ! "$TEMPLATE" = "minimal-lxc" ]; then + if [ -f /etc/slackpkg/templates/$TEMPLATE.template ]; then + cat /etc/slackpkg/templates/$TEMPLATE.template \ + > $CONF/templates/$TEMPLATE.template + else + TEMPLATE="minimal-lxc" + fi +fi + +# clean previous installs +rm -fR $ROOT/* + +slackpkg -default_answer=n update +slackpkg install-template $TEMPLATE + +# add a slackpkg default mirror +echo "$MIRROR/$PKGMAIN-$release/" >> $ROOT/etc/slackpkg/mirrors + +# blacklist the devs package (we have to use our premade devices). +# do the same with the kernel packages (we use the host's one), +# but leave available headers and sources +echo "devs" >> $ROOT/etc/slackpkg/blacklist +sed -i \ + -e "s|^#kernel-|kernel-|" \ + -e "s|^kernel-headers|#kernel-headers|" \ + -e "s|^kernel-source|#kernel-source|" \ + $ROOT/etc/slackpkg/blacklist + +return 0 + +) 200>/var/lock/subsys/lxc + +return $? +} + +copy_configuration() +{ +path=$1 +rootfs=$2 +name=$3 + +cat <<EOF >> $path/config + +lxc.utsname = $name + +lxc.mount = $rootfs/etc/fstab + +lxc.tty = 4 +lxc.pts = 1024 +lxc.rootfs = $rootfs + +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 rwm + +# we don't trust even the root user in the container, better safe than sorry. +# comment out only if you know what you're doing. +lxc.cap.drop = sys_module mknod mac_override mac_admin sys_time setfcap setpcap + +# you can try also this alternative to the line above, whatever suits you better. +# lxc.cap.drop=sys_admin +EOF + +if [ $? -ne 0 ]; then + echo "Failed to add configuration." + return 1 +fi + +return 0 +} + +clean() +{ +if [ ! -e $cache ]; then + exit 0 +fi + +# lock, so we won't purge while someone is creating a repository +( +flock -n -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>/var/lock/subsys/lxc +} + +usage() +{ +cat <<EOF +$1 -h|--help -p|--path=<path> --clean +EOF +return 0 +} + +options=$(getopt -o hp:n:a:r:c -l help,rootfs:,path:,name:,arch:,release:,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;; + -a|--arch) arch=$2; shift 2;; + -r|--release) release=$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 installpkg +if [ $? -ne 0 ]; then + echo "'installpkg' command is missing." + exit 1 +fi + +type slackpkg +if [ $? -ne 0 ]; then + echo "'slackpkg' 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 + +# If no release version was specified, use current +release=${release:-current} + +if [ -z "$name" ]; then + # no name given? set a default one + name=slackwarecontainer +fi + +# detect rootfs +config="$path/config" +if [ -z "$rootfs" ]; then + if grep -q '^lxc.rootfs' $config 2>/dev/null ; then + rootfs=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $config) + else + rootfs=$path/rootfs + fi +fi + +echo + +set -e + +install_slackware $rootfs +if [ $? -ne 0 ]; then + echo "Failed to install slackware." + exit 1 +fi + +echo + +configure_slackware $cache/rootfs-$release-$arch $name +if [ $? -ne 0 ]; then + echo "Failed to configure slackware for a container." + exit 1 +fi + +echo + +rootfs=$path/rootfs +copy_slackware $rootfs +if [ $? -ne 0 ]; then + echo "Failed to copy rootfs." + exit 1 +fi + +echo + +copy_configuration $path $rootfs $name +if [ $? -ne 0 ]; then + echo "Failed to write configuration file." + exit 1 +fi + +if [ ! -z $clean ]; then + clean || exit 1 + exit 0 +fi |