1
0
mirror of https://github.com/lxc/lxc-templates.git synced 2024-12-22 22:40:16 +00:00
lxc-templates/templates/lxc-opensuse.in

546 lines
16 KiB
Plaintext
Raw Normal View History

#!/bin/bash
#
# template script for generating OpenSUSE container for LXC
#
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# Frederic Crozat <fcrozat@suse.com>
# Michael H. Warfield <mhw@WittsEnd.com>
# Johannes Kastl <mail@ojkastl.de>
# Thomas Lamprecht <t.lamprecht@proxmox.com>
# 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
# 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
if [ -x /usr/bin/obs-build ]; then
BUILD=/usr/bin/obs-build
export BUILD_DIR=/usr/lib/obs-build
else
BUILD=/usr/bin/build
export BUILD_DIR=/usr/lib/build
fi
configure_opensuse()
{
rootfs=$1
hostname=$2
# set first network adapter as dhcp. This is the most common config.
cat <<EOF > $rootfs/etc/sysconfig/network/ifcfg-eth0
STARTMODE='auto'
BOOTPROTO='dhcp'
EOF
# create empty fstab
touch $rootfs/etc/fstab
# set the hostname
cat <<EOF > $rootfs/etc/HOSTNAME
$hostname
EOF
# ensure /etc/hostname is available too
ln -s -f HOSTNAME $rootfs/etc/hostname
# do not use hostname from HOSTNAME variable
cat <<EOF >> $rootfs/etc/sysconfig/cron
unset HOSTNAME
EOF
# set minimal hosts
cat <<EOF > $rootfs/etc/hosts
127.0.0.1 localhost $hostname
EOF
# disable yast->bootloader in container
cat <<EOF > $rootfs/etc/sysconfig/bootloader
LOADER_TYPE=none
LOADER_LOCATION=none
EOF
# set /dev/console as securetty
cat << EOF >> $rootfs/etc/securetty
console
EOF
cat <<EOF >> $rootfs/etc/sysconfig/boot
# disable root fsck
ROOTFS_FSCK="0"
ROOTFS_BLKDEV="/dev/null"
EOF
# remove pointless services in a container
ln -s /dev/null $rootfs/etc/systemd/system/proc-sys-fs-binfmt_misc.automount
ln -s /dev/null $rootfs/etc/systemd/system/console-shell.service
ln -s /dev/null $rootfs/etc/systemd/system/systemd-vconsole-setup.service
# enable getty and console services
sed -e 's/ConditionPathExists=.*//' $rootfs/usr/lib/systemd/system/getty@.service > $rootfs/etc/systemd/system/getty@.service
ln -s getty@.service $rootfs/etc/systemd/system/getty@tty1.service
mkdir -p $rootfs/etc/systemd/system/getty.target.wants/
ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@console.service
ln -s -f ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty1.service
ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty2.service
ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty3.service
ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty4.service
touch $rootfs/etc/sysconfig/kernel
echo "Please change root-password !"
return 0
}
download_opensuse()
{
cache=$1
arch=$2
if [ ! -x ${BUILD} ]; then
echo "Could not create openSUSE template :"
echo "you need to install \"build\" package"
return 1
fi
# check the mini opensuse was not already downloaded
mkdir -p "$cache/partial-$arch"
if [ $? -ne 0 ]; then
echo "Failed to create '$cache/partial-$arch' directory"
return 1
fi
# download a mini opensuse into a cache
echo "Downloading opensuse minimal ..."
mkdir -p "$cache/partial-$arch-packages"
oss_repo_url="http://download.opensuse.org/distribution/$DISTRO/repo/oss/"
if [[ $DISTRO == "tumbleweed" ]]; then
oss_repo_url="http://download.opensuse.org/$DISTRO/repo/oss/"
fi
zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar "$oss_repo_url" repo-oss || return 1
# Leap update repos were rearranged
if [[ $DISTRO != "tumbleweed" ]]; then
update_repo_url="http://download.opensuse.org/update/$DISTRO/oss/"
zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar "$update_repo_url" update || return 1
fi
support_packages=(zypper patterns-openSUSE-base lxc ncurses-utils iputils udev netcfg hwinfo insserv-compat module-init-tools openSUSE-release openssh pwdutils sysconfig net-tools iproute2)
zypper --quiet --root $cache/partial-$arch-packages --non-interactive --gpg-auto-import-keys update || return 1
zypper --root $cache/partial-$arch-packages --non-interactive in --no-recommends --auto-agree-with-licenses --download-only zypper lxc patterns-openSUSE-base bash iputils sed tar rsyslog ${support_packages[*]} || return 1
cat > $cache/partial-$arch-packages/opensuse.conf << EOF
Preinstall: aaa_base bash coreutils diffutils
Preinstall: filesystem fillup glibc grep insserv-compat perl-base
Preinstall: libbz2-1 pam
Preinstall: permissions rpm sed tar libz1 libselinux1
Preinstall: liblzma5 libcap2 libacl1 libattr1
Preinstall: libpopt0 libelf1
Preinstall: libpcre1
RunScripts: aaa_base
Support: ${support_packages[*]}
Ignore: rpm:suse-build-key,build-key
Ignore: systemd:systemd-presets-branding
EOF
if [[ $DISTRO == "tumbleweed" ]]; then
echo "Preinstall: liblua5_3 libncurses6 libreadline7" >> $cache/partial-$arch-packages/opensuse.conf
elif [[ $DISTRO == "leap/1"* ]]; then
echo "Preinstall: liblua5_3-5 libncurses6 libreadline7" >> $cache/partial-$arch-packages/opensuse.conf
elif [[ $DISTRO == "leap/4"* ]]; then
echo "Preinstall: liblua5_1 libncurses5 libreadline6" >> $cache/partial-$arch-packages/opensuse.conf
echo "Support: rpcbind" >> $cache/partial-$arch-packages/opensuse.conf
fi
if [ "$arch" = "i686" ]; then
mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i686/
for i in "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i586/*" ; do
ln -s $i $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i686/
done
mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/update/i686
for i in "$cache/partial-$arch-packages/var/cache/zypp/packages/update/i586/*" ; do
ln -s $i $cache/partial-$arch-packages/var/cache/zypp/packages/update/i686/
done
fi
# openSUSE 13.2 has no noarch directory in update
[ -d $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch ] || mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch
if [[ $DISTRO == "leap/4"* ]]; then
repos=("--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/$arch" "--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/noarch")
else
# Leap 15 has a different repo structure compared to 42.3
repos=("--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/$arch" "--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/noarch")
fi
if [[ $DISTRO != "tumbleweed" ]]; then # tumbleweed has no update repo
repos+=("--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/update/$arch" "--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch")
fi
CLEAN_BUILD=1 BUILD_ARCH="$arch" BUILD_ROOT="$cache/partial-$arch" BUILD_DIST="$cache/partial-$arch-packages/opensuse.conf" PATH="$PATH:$BUILD_DIR" $BUILD_DIR/init_buildsystem --clean --configdir $BUILD_DIR/configs --cachedir $cache/partial-$arch-cache ${repos[*]} || return 1
chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar "$oss_repo_url" repo-oss || return 1
if [[ $DISTRO != "tumbleweed" ]]; then
chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar "$update_repo_url" update || return 1
fi
# really clean the image
rm -fr $cache/partial-$arch/{.build,.guessed_dist,.srcfiles*,installed-pkg}
rm -fr $cache/partial-$arch/dev
# make sure we have a minimal /dev
mkdir -p "$cache/partial-$arch/dev"
mknod -m 666 $cache/partial-$arch/dev/null c 1 3
mknod -m 666 $cache/partial-$arch/dev/zero c 1 5
# create mtab symlink
rm -f $cache/partial-$arch/etc/mtab
ln -sf /proc/self/mounts $cache/partial-$arch/etc/mtab
# ensure /var/run and /run are symlinked
rm -fr $cache/partial-$arch/var/run
ln -s -f ../run $cache/partial-$arch/var/run
if [ $? -ne 0 ]; then
echo "Failed to download the rootfs, aborting."
return 1
fi
rm -fr "$cache/partial-$arch-packages"
mv "$1/partial-$arch" "$1/rootfs-$arch"
echo "Download complete."
return 0
}
copy_opensuse()
{
cache=$1
arch=$2
rootfs=$3
# make a local copy of the mini opensuse
echo "Copying rootfs to $rootfs ..."
mkdir -p $rootfs
rsync -SHaAX $cache/rootfs-$arch/ $rootfs/ || return 1
return 0
}
install_opensuse()
{
# Allow the cache base to be set by environment variable
cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/opensuse/$DISTRO}"
rootfs=$1
mkdir -p @LOCALSTATEDIR@/lock/subsys/
(
flock -x 9
if [ $? -ne 0 ]; then
echo "Cache repository is busy."
return 1
fi
echo "Checking cache download in $cache/rootfs-$arch ... "
if [ ! -e "$cache/rootfs-$arch" ]; then
download_opensuse $cache $arch
if [ $? -ne 0 ]; then
echo "Failed to download 'opensuse base'"
return 1
fi
fi
echo "Copy $cache/rootfs-$arch to $rootfs ... "
copy_opensuse $cache $arch $rootfs
if [ $? -ne 0 ]; then
echo "Failed to copy rootfs"
return 1
fi
return 0
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-opensuse
return $?
}
# Generate a random hardware (MAC) address composed of FE followed by
# 5 random bytes...
create_hwaddr()
{
openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/'
}
copy_configuration()
{
path=$1
rootfs=$2
name=$3
grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "
lxc.rootfs.path = $rootfs_path
" >> $path/config
# The following code is to create static MAC addresses for each
# interface in the container. This code will work for multiple
# interfaces in the default config. It will also strip any
# hwaddr stanzas out of the default config since we can not share
# MAC addresses between containers.
#
# This code is largely mimiced from the Fedora Template.
mv $path/config $path/config.def
while read LINE
do
# This should catch variable expansions from the default config...
if expr "${LINE}" : '.*\$' > /dev/null 2>&1
then
LINE=$(eval "echo \"${LINE}\"")
fi
# There is a tab and a space in the regex bracket below!
# Seems that \s doesn't work in brackets.
KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=')
if [[ "${KEY}" != "lxc.net.0.hwaddr" ]]
then
echo "${LINE}" >> $path/config
if [[ "${KEY}" == "lxc.net.0.link" ]]
then
echo "lxc.net.0.hwaddr = $(create_hwaddr)" >> $path/config
fi
fi
done < $path/config.def
rm -f $path/config.def
if [ -e "@LXCTEMPLATECONFIG@/opensuse.common.conf" ]; then
echo "
# Include common configuration
lxc.include = @LXCTEMPLATECONFIG@/opensuse.common.conf
" >> $path/config
fi
# Append things which require expansion here...
cat <<EOF >> $path/config
lxc.arch = $arch
lxc.uts.name = $name
lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
# When using LXC with apparmor, uncomment the next line to run unconfined:
lxc.apparmor.profile = unconfined
# example simple networking setup, uncomment to enable
#lxc.net.0.type = $lxc_network_type
#lxc.net.0.flags = up
#lxc.net.0.link = $lxc_network_link
#lxc.net.0.name = eth0
# Additional example for veth network type
# static MAC address,
#lxc.net.0.hwaddr = 00:16:3e:77:52:20
# persistent veth device name on host side
# Note: This may potentially collide with other containers of same name!
#lxc.net.0.veth.pair = v-$name-e0
EOF
if [ $? -ne 0 ]; then
echo "Failed to add configuration"
return 1
fi
return 0
}
clean()
{
cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/opensuse}"
if [ ! -e $cache ]; then
exit 0
fi
# lock, so we won't purge while someone is creating a repository
(
flock -x 9
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
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-opensuse
}
usage()
{
cat <<EOF
$1 -h|--help -p|--path=<path> -r|--release nn.n --clean
Please give the release as 13.1, 13.2 etc.
If no release is given, openSUSE Leap 42.2 is installed.
EOF
return 0
}
# Make arch a global. This may become configurable?
arch=$(uname -m)
options=$(getopt -o hp:n:r:c -l help,rootfs:,path:,name:,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;;
-n|--name) name=$2; shift 2;;
-r|--release) DISTRO=$2; shift 2;;
-c|--clean) clean=1; shift 1;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ ! -z "$clean" -a -z "$path" ]; then
clean || exit 1
exit 0
fi
type zypper > /dev/null
if [ $? -ne 0 ]; then
echo "'zypper' command is missing"
exit 1
fi
if [ -z "$path" ]; then
echo "'path' parameter is required"
exit 1
fi
if grep -q Harlequin /etc/os-release || grep -q Tumbleweed /etc/os-release ; then
BVER=`rpm -q --qf '%{version}\n' build`
if [ $? -ne 0 -o "$BVER" -lt "20141120" ]; then
echo "Building openSUSE containers with your version of the build package is broken. Please install the update to version 20141120 or newer."
exit 1
fi
fi
if [ -z "$DISTRO" ]; then
echo ""
echo "No release selected, using openSUSE Leap 15.0"
DISTRO="leap/15.0"
else
echo ""
case "$DISTRO" in
13.1)
echo "Selected openSUSE 13.1"
;;
13.2)
echo "Selected openSUSE 13.2"
;;
42.1|leap/42.1|421)
echo "Selected openSUSE Leap 42.1"
DISTRO="leap/42.1"
;;
42.2|leap/42.2|422)
echo "Selected openSUSE Leap 42.2"
DISTRO="leap/42.2"
;;
42.3|leap/42.3|423)
echo "Selected openSUSE Leap 42.3"
DISTRO="leap/42.3"
;;
15.0|leap/15.0|150|leap)
echo "Selected openSUSE Leap 15.0"
DISTRO="leap/15.0"
;;
tumbleweed|factory)
echo "Selected openSUSE Leap Tumbleweed"
DISTRO="tumbleweed"
;;
*)
echo "You have chosen an invalid release, quitting..."
exit 1
;;
esac
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.path' $config 2>/dev/null ; then
rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config)
else
rootfs=$path/rootfs
fi
fi
install_opensuse $rootfs
if [ $? -ne 0 ]; then
echo "failed to install opensuse"
exit 1
fi
configure_opensuse $rootfs $name
if [ $? -ne 0 ]; then
echo "failed to configure opensuse 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