lxc-opensuse.in revision c63c04fcaf1c3a78c70500eae253d72fa9c8358a
7126N/A#!/bin/bash
7126N/A
7126N/A#
7126N/A# template script for generating suse container for LXC
7126N/A#
7126N/A
7126N/A#
7126N/A# lxc: linux Container library
7126N/A
7126N/A# Authors:
7126N/A# Daniel Lezcano <daniel.lezcano@free.fr>
7126N/A# Frederic Crozat <fcrozat@suse.com>
7126N/A
7126N/A# This library is free software; you can redistribute it and/or
7126N/A# modify it under the terms of the GNU Lesser General Public
7126N/A# License as published by the Free Software Foundation; either
7126N/A# version 2.1 of the License, or (at your option) any later version.
7126N/A
7126N/A# This library is distributed in the hope that it will be useful,
7126N/A# but WITHOUT ANY WARRANTY; without even the implied warranty of
7126N/A# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7126N/A# Lesser General Public License for more details.
7126N/A
7126N/A# You should have received a copy of the GNU Lesser General Public
7126N/A# License along with this library; if not, write to the Free Software
7126N/A# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
7126N/A
7261N/A# Detect use under userns (unsupported)
7261N/Afor arg in "$@"; do
7141N/A [ "$arg" == "--" ] && break
7169N/A if [ "$arg" == "--mapped-uid" -o "$arg" == "--mapped-gid" ]; then
7126N/A echo "This template can't be used for unprivileged containers." 1>&2
7126N/A echo "You may want to try the \"download\" template instead." 1>&2
7126N/A exit 1
7126N/A fi
7126N/Adone
7126N/A
7126N/ADISTRO=12.3
7169N/A
7126N/Aconfigure_opensuse()
7126N/A{
7126N/A rootfs=$1
7126N/A hostname=$2
7126N/A
7141N/A # set network as static, but everything is done by LXC outside the container
7126N/A cat <<EOF > $rootfs/etc/sysconfig/network/ifcfg-eth0
7126N/ASTARTMODE='auto'
7126N/ABOOTPROTO='none'
7164N/AEOF
7164N/A
7126N/A # create empty fstab
7141N/A touch $rootfs/etc/fstab
7141N/A
7141N/A # set the hostname
7141N/A cat <<EOF > $rootfs/etc/HOSTNAME
7141N/A$hostname
7141N/AEOF
7141N/A # ensure /etc/hostname is available too
7141N/A ln -s -f HOSTNAME $rootfs/etc/hostname
7141N/A
7141N/A # do not use hostname from HOSTNAME variable
7141N/A cat <<EOF >> $rootfs/etc/sysconfig/cron
7126N/Aunset HOSTNAME
7126N/AEOF
7126N/A
7126N/A # set minimal hosts
7126N/A cat <<EOF > $rootfs/etc/hosts
7126N/A127.0.0.1 localhost $hostname
7126N/AEOF
7126N/A
7126N/A # disable yast->bootloader in container
7126N/A cat <<EOF > $rootfs/etc/sysconfig/bootloader
7141N/ALOADER_TYPE=none
7126N/ALOADER_LOCATION=none
7126N/AEOF
7126N/A
7164N/A # set /dev/console as securetty
7126N/A cat << EOF >> $rootfs/etc/securetty
7141N/Aconsole
7141N/AEOF
7164N/A
7141N/A cat <<EOF >> $rootfs/etc/sysconfig/boot
7164N/A# disable root fsck
7126N/AROOTFS_FSCK="0"
7126N/AROOTFS_BLKDEV="/dev/null"
7126N/AEOF
7126N/A
7126N/A
7126N/A # remove pointless services in a container
7126N/A ln -s /dev/null $rootfs/etc/systemd/system/proc-sys-fs-binfmt_misc.automount
7141N/A ln -s /dev/null $rootfs/etc/systemd/system/console-shell.service
7141N/A ln -s /dev/null $rootfs/etc/systemd/system/systemd-vconsole-setup.service
7126N/A sed -e 's/ConditionPathExists=.*//' /usr/lib/systemd/system/getty@.service > $rootfs/etc/systemd/system/getty@.service
7126N/A ln -s getty@.service $rootfs/etc/systemd/system/getty@tty1.service
7126N/A ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@console.service
7126N/A ln -s -f ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty1.service
7126N/A ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty2.service
7126N/A ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty3.service
7126N/A ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty4.service
7126N/A
7141N/A # copy host poweroff target as sigpwr target to make shutdown work
7126N/A # see https://wiki.archlinux.org/index.php/Linux_Containers#Container_cannot_be_shutdown_if_using_systemd
7126N/A cp /usr/lib/systemd/system/poweroff.target $rootfs/usr/lib/systemd/system/sigpwr.target
7261N/A
7141N/A touch $rootfs/etc/sysconfig/kernel
7126N/A
7126N/A echo "Please change root-password !"
7164N/A echo "root:root" | chpasswd -R $rootfs
7169N/A
7169N/A return 0
7169N/A}
7169N/A
7169N/Adownload_opensuse()
7169N/A{
7169N/A cache=$1
7169N/A arch=$2
7169N/A
7164N/A if [ ! -x /usr/bin/build ]; then
7126N/A echo "Could not create openSUSE template :"
7126N/A echo "you need to install \"build\" package"
7126N/A return 1
7126N/A fi
7126N/A
7126N/A # check the mini opensuse was not already downloaded
7126N/A mkdir -p "$cache/partial-$arch"
7126N/A
7126N/A if [ $? -ne 0 ]; then
7141N/A echo "Failed to create '$cache/partial-$arch' directory"
7141N/A return 1
7126N/A fi
7126N/A
7126N/A # download a mini opensuse into a cache
7126N/A echo "Downloading opensuse minimal ..."
7126N/A mkdir -p "$cache/partial-$arch-packages"
7126N/A zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar http://download.opensuse.org/distribution/$DISTRO/repo/oss/ repo-oss || return 1
7141N/A zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar http://download.opensuse.org/update/$DISTRO/ update || return 1
7126N/A zypper --quiet --root $cache/partial-$arch-packages --non-interactive --gpg-auto-import-keys update || return 1
7126N/A zypper --root $cache/partial-$arch-packages --non-interactive in --auto-agree-with-licenses --download-only zypper lxc patterns-openSUSE-base bash iputils sed tar rsyslog || return 1
7141N/A cat > $cache/partial-$arch-packages/opensuse.conf << EOF
7126N/APreinstall: aaa_base bash coreutils diffutils
7126N/APreinstall: filesystem fillup glibc grep insserv-compat perl-base
7126N/APreinstall: libbz2-1 libgcc_s1 libncurses5 pam
7126N/APreinstall: permissions libreadline6 rpm sed tar libz1 libselinux1
7126N/APreinstall: liblzma5 libcap2 libacl1 libattr1
7126N/APreinstall: libpopt0 libelf1 liblua5_1
7126N/APreinstall: libpcre1
7126N/A
7126N/ARunScripts: aaa_base
7126N/A
7141N/ASupport: zypper
7141N/ASupport: patterns-openSUSE-base
7126N/ASupport: lxc
7126N/ASupport: ncurses-utils
7126N/ASupport: iputils
7126N/ASupport: udev
7126N/ASupport: netcfg
7126N/ASupport: dhcpcd hwinfo insserv-compat module-init-tools openSUSE-release openssh
7141N/ASupport: pwdutils rpcbind sysconfig
7126N/A
7126N/AIgnore: rpm:suse-build-key,build-key
7141N/AIgnore: systemd:systemd-presets-branding
7126N/AEOF
7126N/A if [ "$arch" = "i686" ]; then
7126N/A mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i686/
7141N/A for i in "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i586/*" ; do
7126N/A ln -s $i $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i686/
7141N/A done
7126N/A mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/update/i686
7141N/A for i in "$cache/partial-$arch-packages/var/cache/zypp/packages/update/i586/*" ; do
7126N/A ln -s $i $cache/partial-$arch-packages/var/cache/zypp/packages/update/i686/
7141N/A done
7126N/A fi
7126N/A
7126N/A CLEAN_BUILD=1 BUILD_ARCH="$arch" BUILD_ROOT="$cache/partial-$arch" BUILD_DIST="$cache/partial-$arch-packages/opensuse.conf" PATH="$PATH:/usr/lib/build" /usr/lib/build/init_buildsystem --clean --configdir /usr/lib/build/configs --cachedir $cache/partial-$arch-cache --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 --repository $cache/partial-$arch-packages/var/cache/zypp/packages/update/$arch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch || return 1
7126N/A chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar http://download.opensuse.org/distribution/$DISTRO/repo/oss repo-oss || return 1
7126N/A chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar http://download.opensuse.org/update/$DISTRO/ update || return 1
7126N/A# really clean the image
7141N/A rm -fr $cache/partial-$arch/{.build,.guessed_dist,.srcfiles*,installed-pkg}
7126N/A rm -fr $cache/partial-$arch/dev
7126N/A# make sure we have a minimal /dev
7126N/A mkdir -p "$cache/partial-$arch/dev"
7126N/A mknod -m 666 $cache/partial-$arch/dev/null c 1 3
7126N/A mknod -m 666 $cache/partial-$arch/dev/zero c 1 5
7126N/A# create mtab symlink
7126N/A rm -f $cache/partial-$arch/etc/mtab
7126N/A ln -sf /proc/self/mounts $cache/partial-$arch/etc/mtab
7126N/A
7126N/A# ensure /var/run and /run are symlinked
7126N/A rm -fr $cache/partial-$arch/var/run
7126N/A ln -s -f ../run $cache/partial-$arch/var/run
7126N/A if [ $? -ne 0 ]; then
7126N/A echo "Failed to download the rootfs, aborting."
7126N/A return 1
7126N/A fi
7126N/A
7126N/A rm -fr "$cache/partial-$arch-packages"
7126N/A mv "$1/partial-$arch" "$1/rootfs-$arch"
7169N/A echo "Download complete."
7169N/A
7169N/A return 0
7169N/A}
7169N/A
7169N/Acopy_opensuse()
7169N/A{
7169N/A cache=$1
7169N/A arch=$2
7169N/A rootfs=$3
7169N/A
7169N/A # make a local copy of the mini opensuse
7169N/A echo "Copying rootfs to $rootfs ..."
7169N/A mkdir -p $rootfs
7169N/A rsync -Ha $cache/rootfs-$arch/ $rootfs/ || return 1
7169N/A return 0
7169N/A}
7169N/A
7169N/Ainstall_opensuse()
7169N/A{
7169N/A cache="@LOCALSTATEDIR@/cache/lxc/opensuse"
7169N/A rootfs=$1
7169N/A mkdir -p @LOCALSTATEDIR@/lock/subsys/
7169N/A (
7169N/A flock -x 9
7169N/A if [ $? -ne 0 ]; then
7169N/A echo "Cache repository is busy."
7169N/A return 1
7169N/A fi
7169N/A
7169N/A arch=$(uname -m)
7169N/A
7169N/A echo "Checking cache download in $cache/rootfs-$arch ... "
7169N/A if [ ! -e "$cache/rootfs-$arch" ]; then
7169N/A download_opensuse $cache $arch
7169N/A if [ $? -ne 0 ]; then
7169N/A echo "Failed to download 'opensuse base'"
7169N/A return 1
7126N/A fi
7126N/A fi
7126N/A
7126N/A echo "Copy $cache/rootfs-$arch to $rootfs ... "
7126N/A copy_opensuse $cache $arch $rootfs
7126N/A if [ $? -ne 0 ]; then
7126N/A echo "Failed to copy rootfs"
7126N/A return 1
7126N/A fi
7126N/A
7126N/A return 0
7141N/A ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-opensuse
7126N/A
7126N/A return $?
7164N/A}
7126N/A
7126N/Acopy_configuration()
7126N/A{
7141N/A path=$1
7126N/A rootfs=$2
7126N/A name=$3
7126N/A
7126N/A if grep -q "^lxc.network.type" $path/config; then
7126N/A TYPE=$(sed '/^#/d; /lxc.network.type/!d; s/.*=[ \t]*//' $path/config)
7126N/A grep -q "^lxc.network.ipv4" $path/config
7141N/A IPV4_NOT_CONFIGURED=$?
7126N/A
7126N/A if [ ! grep -q "^lxc.network.*.gateway" $path/config ]; then
7126N/A [ $IPV4_NOT_CONFIGURED -eq 0 ] && IPV4=$(sed '/^#/d; /lxc.network.ipv4/!d; /gateway/d; s/.*=[ \t]*//; s/\([[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+\).*/\1/' $path/config)
7126N/A if [ "$TYPE" = "veth" -o "$TYPE" = "macvlan" ]; then
7126N/A if [ $IPV4_NOT_CONFIGURED -eq 0 -a "$IPV4" != "0.0.0.0" ]; then
7126N/A # set default route
7126N/A IP=$(/sbin/ip route | awk '/default/ { print $3 }')
7126N/A echo "lxc.network.ipv4.gateway = $IP " >> $path/config
7126N/A else
7126N/A # set network as dhcp
7141N/A sed -i -e 's/BOOTPROTO=.*/BOOTPROTO=dhcp/' $rootfs/etc/sysconfig/network/ifcfg-eth0
7126N/A fi
7126N/A fi
7126N/A fi
7126N/A if [ "$TYPE" != "empty" ]; then
7126N/A echo "#remove next line if host DNS configuration should not be available to container" >> $path/config
7126N/A echo "lxc.mount.entry = /etc/resolv.conf etc/resolv.conf none bind,ro 0 0" >> $path/config
7126N/A fi
7126N/A else
7126N/A echo 'lxc.network.type = empty' >> $path/config
7141N/A fi
7126N/A
7126N/A grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config
7126N/A cat <<EOF >> $path/config
7126N/Alxc.utsname = $name
7126N/Alxc.autodev=1
7126N/Alxc.tty = 4
7126N/Alxc.pts = 1024
7126N/Alxc.mount = $path/fstab
7126N/Alxc.cap.drop = sys_module mac_admin mac_override mknod sys_time
7126N/A
7126N/A# When using LXC with apparmor, uncomment the next line to run unconfined:
7126N/A#lxc.aa_profile = unconfined
7126N/A
7126N/Alxc.cgroup.devices.deny = a
7126N/A# /dev/null and zero
7126N/Alxc.cgroup.devices.allow = c 1:3 rwm
7126N/Alxc.cgroup.devices.allow = c 1:5 rwm
7141N/A# consoles
7126N/Alxc.cgroup.devices.allow = c 5:1 rwm
7141N/Alxc.cgroup.devices.allow = c 5:0 rwm
7126N/Alxc.cgroup.devices.allow = c 4:0 rwm
7126N/Alxc.cgroup.devices.allow = c 4:1 rwm
7126N/A# /dev/{,u}random
7126N/Alxc.cgroup.devices.allow = c 1:9 rwm
7126N/Alxc.cgroup.devices.allow = c 1:8 rwm
7126N/Alxc.cgroup.devices.allow = c 136:* rwm
7141N/Alxc.cgroup.devices.allow = c 5:2 rwm
7126N/A# rtc
7126N/Alxc.cgroup.devices.allow = c 254:0 rm
7126N/AEOF
7126N/A
7126N/A cat <<EOF > $path/fstab
7126N/Aproc proc proc nodev,noexec,nosuid 0 0
7126N/Asysfs sys sysfs defaults 0 0
7126N/Atmpfs run tmpfs mode=0755,nodev,nosuid 0 0
7126N/AEOF
7126N/A
7126N/A if [ $? -ne 0 ]; then
7141N/A echo "Failed to add configuration"
7126N/A return 1
7141N/A fi
7126N/A
7126N/A return 0
7126N/A}
7141N/A
7141N/Aclean()
7141N/A{
7141N/A cache="@LOCALSTATEDIR@/cache/lxc/opensuse"
7141N/A
7141N/A if [ ! -e $cache ]; then
7141N/A exit 0
7141N/A fi
7141N/A
7141N/A # lock, so we won't purge while someone is creating a repository
7141N/A (
7141N/A flock -x 9
7141N/A if [ $? != 0 ]; then
7126N/A echo "Cache repository is busy."
7126N/A exit 1
7126N/A fi
7126N/A
7126N/A echo -n "Purging the download cache..."
7126N/A rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
7126N/A exit 0
7126N/A ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-opensuse
7126N/A}
7126N/A
7141N/Ausage()
7126N/A{
7126N/A cat <<EOF
7126N/A$1 -h|--help -p|--path=<path> --clean
7126N/AEOF
7126N/A return 0
7182N/A}
7126N/A
7126N/Aoptions=$(getopt -o hp:n:c -l help,rootfs:,path:,name:,clean -- "$@")
7126N/Aif [ $? -ne 0 ]; then
7126N/A usage $(basename $0)
7126N/A exit 1
7126N/Afi
7126N/Aeval set -- "$options"
7126N/A
7126N/Awhile true
7126N/Ado
7126N/A case "$1" in
7126N/A -h|--help) usage $0 && exit 0;;
7126N/A -p|--path) path=$2; shift 2;;
7126N/A --rootfs) rootfs=$2; shift 2;;
7141N/A -n|--name) name=$2; shift 2;;
7126N/A -c|--clean) clean=$2; shift 2;;
7126N/A --) shift 1; break ;;
7126N/A *) break ;;
7126N/A esac
7126N/Adone
7126N/A
7182N/Aif [ ! -z "$clean" -a -z "$path" ]; then
7126N/A clean || exit 1
7126N/A exit 0
7126N/Afi
7126N/A
7126N/Atype zypper > /dev/null
7126N/Aif [ $? -ne 0 ]; then
7126N/A echo "'zypper' command is missing"
7126N/A exit 1
7126N/Afi
7126N/A
7126N/Aif [ -z "$path" ]; then
7126N/A echo "'path' parameter is required"
7126N/A exit 1
7126N/Afi
7126N/A
7126N/Aif [ "$(id -u)" != "0" ]; then
7126N/A echo "This script should be run as 'root'"
7126N/A exit 1
7126N/Afi
7126N/A
7126N/A# detect rootfs
7126N/Aconfig="$path/config"
7126N/Aif [ -z "$rootfs" ]; then
7126N/A if grep -q '^lxc.rootfs' $config 2>/dev/null ; then
7126N/A rootfs=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $config)
7126N/A else
7182N/A rootfs=$path/rootfs
7126N/A fi
7126N/Afi
7126N/A
7126N/Ainstall_opensuse $rootfs
7126N/Aif [ $? -ne 0 ]; then
7126N/A echo "failed to install opensuse"
7126N/A exit 1
7126N/Afi
7126N/A
7126N/Aconfigure_opensuse $rootfs $name
7126N/Aif [ $? -ne 0 ]; then
7126N/A echo "failed to configure opensuse for a container"
7126N/A exit 1
7126N/Afi
7126N/A
7141N/Acopy_configuration $path $rootfs $name
7126N/Aif [ $? -ne 0 ]; then
7141N/A echo "failed write configuration file"
7126N/A exit 1
7141N/Afi
7126N/A
7141N/Aif [ ! -z $clean ]; then
7126N/A clean || exit 1
7141N/A exit 0
7126N/Afi
7141N/A