forked from neil/lxc-templates
d9f1b169bc
The previous patch had incomplete support for pkgtools8. Signed-off-by: KATOH Yasufumi <karma@jazz.email.ne.jp>
481 lines
14 KiB
Bash
481 lines
14 KiB
Bash
#!/bin/bash -eu
|
|
|
|
#
|
|
# template script for generating Plamo Linux container for LXC
|
|
#
|
|
|
|
#
|
|
# lxc: linux Container library
|
|
|
|
# Authors:
|
|
# KATOH Yasufumi <karma@jazz.email.ne.jp>
|
|
# TAMUKI Shoichi <tamuki@linet.gr.jp>
|
|
|
|
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
# ref. https://github.com/Ponce/lxc-slackware/blob/master/lxc-slackware
|
|
# lxc-ubuntu script
|
|
|
|
# Detect use under userns (unsupported)
|
|
for arg in "$@"; do
|
|
[ "$arg" = "--" ] && break
|
|
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
|
|
echo "This template can't be used for unprivileged containers." 1>&2
|
|
echo "You may want to try the \"download\" template instead." 1>&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Make sure the usual locations are in PATH
|
|
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
|
|
|
|
[ -r /etc/default/lxc ] && . /etc/default/lxc
|
|
|
|
download_plamo() {
|
|
# check the mini plamo was not already downloaded
|
|
if ! mkdir -p $ptcache ; then
|
|
echo "Failed to create '$ptcache' directory."
|
|
return 1
|
|
fi
|
|
# download a mini plamo into a cache
|
|
echo "Downloading Plamo-$release minimal..."
|
|
cd $ptcache
|
|
case $DLSCHEME in
|
|
http|https) depth=2 ;;
|
|
ftp) depth=3 ;;
|
|
esac
|
|
rej=${IGNOREPKGS%% *} ; [ -n "$rej" ] && rej="$rej-*"
|
|
if [ `echo $IGNOREPKGS | wc -w` -gt 1 ] ; then
|
|
for p in ${IGNOREPKGS#* } ; do rej="$rej,$p-*" ; done
|
|
fi
|
|
for i in $CATEGORIES ; do
|
|
wget -nv -e robots=off -r -l $depth -nd -A .tgz,.txz,.tzst -R "$rej" \
|
|
-I $MIRRORPATH/Plamo-$release/$arch/plamo/$i \
|
|
-X $MIRRORPATH/Plamo-$release/$arch/plamo/$i/old \
|
|
$DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/plamo/$i
|
|
if [ $? -ne 0 ] ; then
|
|
echo "Failed to download the rootfs, aborting."
|
|
return 1
|
|
fi
|
|
done
|
|
for i in $EXTRACTGRS ; do
|
|
wget -nv -e robots=off -r -l $depth -nd -A .tgz,.txz,.tzst -R "$rej" \
|
|
-I $MIRRORPATH/Plamo-$release/$arch/contrib/$i \
|
|
-X $MIRRORPATH/Plamo-$release/$arch/contrib/$i/old \
|
|
$DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/contrib/$i
|
|
if [ $? -ne 0 ] ; then
|
|
echo "Failed to download the rootfs, aborting."
|
|
return 1
|
|
fi
|
|
done
|
|
for p in $ADDONPKGS ; do
|
|
wget -nv -e robots=off -r -l $depth -nd -A "`basename $p`-*" \
|
|
-I $MIRRORPATH/Plamo-$release/$arch/`dirname $p` \
|
|
-X $MIRRORPATH/Plamo-$release/$arch/`dirname $p`/old \
|
|
$DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/`dirname $p`
|
|
if [ $? -ne 0 ] ; then
|
|
echo "Failed to download the rootfs, aborting."
|
|
return 1
|
|
fi
|
|
done
|
|
mv $ptcache $dlcache
|
|
echo "Download complete."
|
|
return 0
|
|
}
|
|
|
|
copy_plamo() {
|
|
# make a local copy of the mini plamo
|
|
echo "Copying $rtcache to $rootfs..."
|
|
mkdir -p $rootfs
|
|
find $rtcache -mindepth 1 -maxdepth 1 -exec cp -a {} $rootfs \; || return 1
|
|
return 0
|
|
}
|
|
|
|
install_plamo() {
|
|
mkdir -p @LOCALSTATEDIR@/lock/subsys
|
|
(
|
|
if ! flock -n 9 ; then
|
|
echo "Cache repository is busy."
|
|
return 1
|
|
fi
|
|
echo "Checking cache download in $dlcache..."
|
|
if [ ! -d $dlcache ] ; then
|
|
if ! download_plamo ; then
|
|
echo "Failed to download plamo $release base packages."
|
|
return 1
|
|
fi
|
|
fi
|
|
# install "installpkg" command temporarily with static linked tar
|
|
# command into the lxc cache directory to keep the original uid/
|
|
# gid of files/directories.
|
|
echo "Installing 'installpkg' command into $dlcache/sbin..."
|
|
|
|
if [ $majorver -ge 7 ]; then
|
|
pkgtool="pkgtools"
|
|
pkgtool=$( cd $dlcache ; ls "$pkgtool"* )
|
|
pkgtool=${pkgtool%%-*}
|
|
pkgtool=${pkgtool:0:-1}
|
|
else
|
|
pkgtool="hdsetup"
|
|
LANG=C
|
|
fi
|
|
|
|
( cd $dlcache ; tar xpf "$pkgtool"*-*.t*z* ; rm -rf tmp usr var )
|
|
if [ $pkgtool = "pkgtools" ]; then
|
|
( cd $dlcache/sbin
|
|
mv installer_new installer
|
|
pkg_scripts="installpkg installpkg2 installpkg2.mes makepkg updatepkg removepkg"
|
|
for s in $pkg_scripts
|
|
do
|
|
mv new_"$s" $s
|
|
done
|
|
cd installer
|
|
ln -sf zstd-* zstd
|
|
)
|
|
fi
|
|
|
|
sed -i "/ldconfig/!s@/sbin@$dlcache&@g" $dlcache/sbin/installpkg*
|
|
PATH=$dlcache/sbin:$PATH
|
|
echo "Installing packages to $rtcache..."
|
|
if [ ! -d $rtcache ] ; then
|
|
mkdir -p $rtcache
|
|
for p in `ls -cr $dlcache/*.t*z*` ; do
|
|
installpkg -root $rtcache -priority ADD $p
|
|
done
|
|
fi
|
|
echo "Copy $rtcache to $rootfs..."
|
|
if ! copy_plamo ; then
|
|
echo "Failed to copy rootfs."
|
|
return 1
|
|
fi
|
|
return 0
|
|
) 9> @LOCALSTATEDIR@/lock/subsys/lxc-plamo
|
|
}
|
|
|
|
configure_plamo6() {
|
|
# suppress log level output for udev
|
|
sed -i 's/="err"/=0/' $rootfs/etc/udev/udev.conf
|
|
# /etc/fstab
|
|
cat <<- "EOF" > $rootfs/etc/fstab
|
|
none /proc proc defaults 0 0
|
|
none /sys sysfs defaults 0 0
|
|
none /dev tmpfs defaults 0 0
|
|
none /tmp tmpfs defaults 0 0
|
|
none /dev/pts devpts gid=5,mode=620 0 0
|
|
none /proc/bus/usb usbfs noauto 0 0
|
|
none /var/lib/nfs/rpc_pipefs rpc_pipefs defaults 0 0
|
|
EOF
|
|
# /etc/inittab
|
|
cat <<- "EOF" | patch $rootfs/etc/inittab
|
|
32,33c32,33
|
|
< # What to do when power fails (shutdown to single user).
|
|
< pf::powerfail:/sbin/shutdown -f +5 "THE POWER IS FAILING"
|
|
---
|
|
> # What to do when power fails (shutdown).
|
|
> pf::powerfail:/sbin/shutdown -h +0 "THE POWER IS FAILING"
|
|
47a48
|
|
> 1:1235:respawn:/sbin/agetty 38400 console
|
|
52,53d52
|
|
< c5:1235:respawn:/sbin/agetty 38400 tty5 linux
|
|
< c6:12345:respawn:/sbin/agetty 38400 tty6 linux
|
|
EOF
|
|
# configure the network using the dhcp
|
|
echo "DHCP" > $rootfs/var/run/inet1-scheme
|
|
|
|
# delete unnecessary process from rc.S
|
|
ed - $rootfs/etc/rc.d/rc.S <<- "EOF"
|
|
/^mount -w -n -t proc/;/^mkdir \/dev\/shm/-1d
|
|
/^mknod \/dev\/null/;/^# Clean \/etc\/mtab/-2d
|
|
/^# copy the rules/;/^# Set the hostname/-1d
|
|
/^# Check the integrity/;/^# Clean up temporary/-1d
|
|
w
|
|
EOF
|
|
|
|
# delete unnecessary process from rc.M
|
|
ed - $rootfs/etc/rc.d/rc.M <<- "EOF"
|
|
/^# Screen blanks/;/^# Initialize ip6tables/-1d
|
|
/^# Initialize sysctl/;/^echo "Starting services/-1d
|
|
/^sync/;/^# All done/-1d
|
|
w
|
|
EOF
|
|
|
|
# delete unnecessary process from rc.6
|
|
ed - $rootfs/etc/rc.d/rc.6 <<- "EOF"
|
|
/^# Save system time/;/^# Unmount any remote filesystems/-1d
|
|
/^# Turn off swap/;/^# See if this is a powerfail situation/-1d
|
|
w
|
|
EOF
|
|
|
|
# /etc/rc.d/rc.inet1.tradnet
|
|
head -n-93 $rootfs/sbin/netconfig.tradnet > /tmp/netconfig.rconly
|
|
cat <<- EOF >> /tmp/netconfig.rconly
|
|
PCMCIA=n
|
|
RC=$rootfs/etc/rc.d/rc.inet1.tradnet
|
|
IFCONFIG=sbin/ifconfig
|
|
ROUTE=sbin/route
|
|
INET1SCHEME=var/run/inet1-scheme
|
|
IPADDR=127.0.0.1
|
|
NETWORK=127.0.0.0
|
|
DHCPCD=usr/sbin/dhclient
|
|
LOOPBACK=y
|
|
make_config_file
|
|
EOF
|
|
rm -f $rootfs/etc/rc.d/rc.inet1.tradnet
|
|
sh /tmp/netconfig.rconly
|
|
rm -f /tmp/netconfig.rconly
|
|
sed -i '/cmdline/s/if/& false \&\&/' $rootfs/etc/rc.d/rc.inet1.tradnet
|
|
# /etc/rc.d/rc.inet2
|
|
sed -i '/rpc.mountd/s/^/#/' $rootfs/etc/rc.d/rc.inet2
|
|
sed -i '/modprobe/s/^/#/' $rootfs/etc/rc.d/rc.inet2
|
|
# configure to start only the minimum of service
|
|
chmod 644 $rootfs/etc/rc.d/init.d/saslauthd
|
|
chmod 644 $rootfs/etc/rc.d/init.d/open-iscsi
|
|
rm -f $rootfs/etc/rc.d/init.d/postfix
|
|
rm -f $rootfs/var/log/initpkg/shadow
|
|
return 0
|
|
}
|
|
|
|
configure_plamo7() {
|
|
# fstab
|
|
cat <<- "EOF" >> $rootfs/etc/fstab
|
|
proc /proc proc defaults 0 0
|
|
tmpfs /run tmpfs defaults 0 0
|
|
sysfs /sys sysfs defaults 0 0
|
|
tmpfs /tmp tmpfs defaults 0 0
|
|
devpts /dev/pts devpts gid=5,mode=620 0 0
|
|
usbfs /proc/bus/usb usbfs noauto 0 0
|
|
EOF
|
|
|
|
# inittab
|
|
sed -i -e '/^1:2345/i c:1235:respawn:/sbin/agetty console 38400'\
|
|
-e '/^ca:/a pf::powerfail:/sbin/shutdown -h +0 "THE POWER IS FAILING"' \
|
|
-e '/^4:2345/d' \
|
|
-e '/^5:2345/d' \
|
|
-e '/^6:2345/d' $rootfs/etc/inittab
|
|
|
|
# tweak init script on startup
|
|
remove_init_S="S05modules S10eudev S20swap S30checkfs S35setclock S50eudev_retry S70console"
|
|
for f in $remove_init_S
|
|
do
|
|
rm -f $rootfs/etc/rc.d/rcS.d/"$f"
|
|
done
|
|
|
|
# remove init script in runlevel3
|
|
remove_init="rc3.d/S30sshd
|
|
rc6.d/K30sshd rc6.d/K35setclock rc6.d/S65swap rc6.d/S70mountfs
|
|
rc0.d/K30sshd rc0.d/K35setclock rc0.d/S65swap rc0.d/S70mountfs"
|
|
for f in $remove_init
|
|
do
|
|
rm -f $rootfs/etc/rc.d/"$f"
|
|
done
|
|
|
|
# Tweak rc script
|
|
sed -i -e '/wait_for_user/d' \
|
|
-e '/Press Enter to/d' \
|
|
$rootfs/etc/rc.d/init.d/rc
|
|
|
|
# network
|
|
cat <<- "EOF" > $rootfs/etc/sysconfig/ifconfig.eth0
|
|
ONBOOT="yes"
|
|
IFACE="eth0"
|
|
SERVICE="dhclient"
|
|
EOF
|
|
|
|
# remove initpkg that do not execute on containers
|
|
noexec="shadow netconfig7 eudev openssh"
|
|
for f in $noexec
|
|
do
|
|
rm -f $rootfs/var/log/initpkg/"$f"
|
|
done
|
|
}
|
|
|
|
configure_plamo() {
|
|
# set the hostname
|
|
echo "$name" > $rootfs/etc/HOSTNAME
|
|
# set minimal hosts
|
|
echo "127.0.0.1 localhost $name" > $rootfs/etc/hosts
|
|
# localtime (JST)
|
|
ln -s ../usr/share/zoneinfo/Asia/Tokyo $rootfs/etc/localtime
|
|
# disable pam_loginuid.so in /etc/pam.d/login
|
|
sed -i '/pam_loginuid/s/^/#/' $rootfs/etc/pam.d/login
|
|
if [ $majorver -ge 7 ]; then
|
|
configure_plamo7
|
|
else
|
|
configure_plamo6
|
|
fi
|
|
}
|
|
|
|
copy_configuration() {
|
|
ret=0
|
|
cat <<- EOF >> $path/config || let ret++
|
|
lxc.uts.name = $name
|
|
lxc.arch = $arch
|
|
EOF
|
|
if [ -f "@LXCTEMPLATECONFIG@/plamo.common.conf" ] ; then
|
|
cat <<- "EOF" >> $path/config || let ret++
|
|
|
|
lxc.include = @LXCTEMPLATECONFIG@/plamo.common.conf
|
|
EOF
|
|
fi
|
|
if [ $ret -ne 0 ] ; then
|
|
echo "Failed to add configuration."
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
post_process() {
|
|
# nothing do in Plamo Linux
|
|
true
|
|
}
|
|
|
|
do_bindhome() {
|
|
# bind-mount the user's path into the container's /home
|
|
h=`getent passwd $bindhome | cut -d: -f6`
|
|
mkdir -p $rootfs/$h
|
|
echo "lxc.mount.entry = $h $rootfs/$h none bind 0 0" >> $path/config
|
|
# copy /etc/passwd, /etc/shadow, and /etc/group entries into container
|
|
if ! pwd=`getent passwd $bindhome` ; then
|
|
echo "Warning: failed to copy password entry for $bindhome."
|
|
else
|
|
echo $pwd >> $rootfs/etc/passwd
|
|
fi
|
|
echo `getent shadow $bindhome` >> $rootfs/etc/shadow
|
|
}
|
|
|
|
cleanup() {
|
|
[ -d $dlcache -a -d $rtcache ] || return 0
|
|
# lock, so we won't purge while someone is creating a repository
|
|
(
|
|
if ! flock -n 9 ; then
|
|
echo "Cache repository is busy."
|
|
return 1
|
|
fi
|
|
echo "Purging the download cache..."
|
|
rm -rf --one-file-system $dlcache $rtcache || return 1
|
|
echo "Done."
|
|
return 0
|
|
) 9> @LOCALSTATEDIR@/lock/subsys/lxc-plamo
|
|
}
|
|
|
|
usage() {
|
|
cat <<- EOF
|
|
$prog [-h|--help] -p|--path=<path> -n|--name=<name> --rootfs=<rootfs>
|
|
[-c|--clean] [-r|--release=<release>] [-a|--arch=<arch>]
|
|
[-b|--bindhome=<user>]
|
|
release: $release
|
|
arch: x86 or x86_64: defaults to host arch
|
|
bindhome: bind <user>'s home into the container
|
|
EOF
|
|
}
|
|
|
|
prog=`basename $0`
|
|
path="" ; name="" ; rootfs=""
|
|
clean=0
|
|
release=${release:-7.x}
|
|
arch=`uname -m | sed 's/i.86/x86/'` ; hostarch=$arch
|
|
bindhome=""
|
|
sopts=hp:n:cr:a:b:
|
|
lopts=help,path:,name:,rootfs:,clean,release:,arch:,bindhome:
|
|
if ! options=`getopt -o $sopts -l $lopts -- "$@"` ; then
|
|
usage
|
|
exit 1
|
|
fi
|
|
eval set -- "$options"
|
|
while true ; do
|
|
case "$1" in
|
|
-h|--help) usage && exit 0 ;;
|
|
-p|--path) path=$2 ; shift 2 ;;
|
|
-n|--name) name=$2 ; shift 2 ;;
|
|
--rootfs) rootfs=$2 ; shift 2 ;;
|
|
-c|--clean) clean=1 ; shift 1 ;;
|
|
-r|--release) release=$2 ; shift 2 ;;
|
|
-a|--arch) arch=$2 ; shift 2 ;;
|
|
-b|--bindhome) bindhome=$2 ; shift 2 ;;
|
|
--) shift 1 ; break ;;
|
|
*) break ;;
|
|
esac
|
|
done
|
|
if [ $clean -eq 1 -a -z "$path" ] ; then
|
|
cleanup || exit 1
|
|
exit 0
|
|
fi
|
|
if [ $hostarch == "x86" -a $arch == "x86_64" ] ; then
|
|
echo "Can't create x86_64 container on x86."
|
|
exit 1
|
|
fi
|
|
if [ -z "$path" ] ; then
|
|
echo "'path' parameter is required."
|
|
exit 1
|
|
fi
|
|
if [ -z "$name" ] ; then
|
|
echo "'name' parameter is required."
|
|
exit 1
|
|
fi
|
|
if [ `id -u` -ne 0 ] ; then
|
|
echo "This script should be run as 'root'."
|
|
exit 1
|
|
fi
|
|
|
|
majorver=${release%.*}
|
|
if [ $majorver -ge 7 ]; then
|
|
CATEGORIES=${CATEGORIES-"00_base"}
|
|
ADDONPKGS=${ADDONPKGS-""}
|
|
else
|
|
CATEGORIES=${CATEGORIES-"00_base 01_minimum"}
|
|
ADDONPKGS=${ADDONPKGS-"`echo contrib/Hamradio/{morse,qrq}`"}
|
|
fi
|
|
|
|
DLSCHEME=${DLSCHEME:-"https"}
|
|
MIRRORSRV=${MIRRORSRV:-"repository.plamolinux.org"}
|
|
MIRRORPATH=${MIRRORPATH:-"/pub/linux/Plamo"}
|
|
CATEGORIES=${CATEGORIES-"00_base 01_minimum"}
|
|
EXTRACTGRS=${EXTRACTGRS-""}
|
|
IGNOREPKGS=${IGNOREPKGS-"grub kernel lilo linux_firmware microcode_ctl
|
|
linux_firmwares cpufreqd cpufrequtils gpm ntp kmod kmscon"}
|
|
ADDONPKGS=${ADDONPKGS-"`echo contrib/Hamradio/{morse,qrq}`"}
|
|
|
|
cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc}"
|
|
ptcache=$cache/partial-${prog##*-}-$release-$arch
|
|
dlcache=$cache/cache-${prog##*-}-$release-$arch
|
|
rtcache=$cache/rootfs-${prog##*-}-$release-$arch
|
|
if [ -z "$rootfs" ] ; then
|
|
if grep -q "^lxc.rootfs.path" $path/config ; then
|
|
rootfs=`awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config`
|
|
else
|
|
rootfs=$path/rootfs
|
|
fi
|
|
fi
|
|
if ! install_plamo ; then
|
|
echo "Failed to install plamo $release."
|
|
exit 1
|
|
fi
|
|
if ! configure_plamo ; then
|
|
echo "Failed to configure plamo $release for a container."
|
|
exit 1
|
|
fi
|
|
if ! copy_configuration ; then
|
|
echo "Failed to write configuration file."
|
|
exit 1
|
|
fi
|
|
post_process
|
|
if [ -n "$bindhome" ] ; then
|
|
do_bindhome
|
|
fi
|
|
if [ $clean -eq 1 ] ; then
|
|
cleanup || exit 1
|
|
exit 0
|
|
fi
|