You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
490 lines
11 KiB
490 lines
11 KiB
6 years ago
|
#!/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
|