4 # template script for generating OpenSUSE container for LXC
8 # lxc: linux Container library
11 # Daniel Lezcano <daniel.lezcano@free.fr>
12 # Frederic Crozat <fcrozat@suse.com>
13 # Michael H. Warfield <mhw@WittsEnd.com>
14 # Johannes Kastl <mail@ojkastl.de>
16 # This library is free software; you can redistribute it and/or
17 # modify it under the terms of the GNU Lesser General Public
18 # License as published by the Free Software Foundation; either
19 # version 2.1 of the License, or (at your option) any later version.
21 # This library is distributed in the hope that it will be useful,
22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 # Lesser General Public License for more details.
26 # You should have received a copy of the GNU Lesser General Public
27 # License along with this library; if not, write to the Free Software
28 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 # Detect use under userns (unsupported)
32 [ "$arg" = "--" ] && break
33 if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
34 echo "This template can't be used for unprivileged containers." 1>&2
35 echo "You may want to try the \"download\" template instead." 1>&2
40 # Make sure the usual locations are in PATH
41 export PATH
=$PATH:/usr
/sbin
:/usr
/bin
:/sbin
:/bin
43 if [ -x /usr
/bin
/obs-build
]; then
44 BUILD
=/usr
/bin
/obs-build
45 export BUILD_DIR
=/usr
/lib
/obs-build
48 export BUILD_DIR
=/usr
/lib
/build
56 # set first network adapter as dhcp. This is the most common config.
57 cat <<EOF > $rootfs/etc/sysconfig/network/ifcfg-eth0
63 touch $rootfs/etc
/fstab
66 cat <<EOF > $rootfs/etc/HOSTNAME
69 # ensure /etc/hostname is available too
70 ln -s -f HOSTNAME
$rootfs/etc
/hostname
72 # do not use hostname from HOSTNAME variable
73 cat <<EOF >> $rootfs/etc/sysconfig/cron
78 cat <<EOF > $rootfs/etc/hosts
79 127.0.0.1 localhost $hostname
82 # disable yast->bootloader in container
83 cat <<EOF > $rootfs/etc/sysconfig/bootloader
88 # set /dev/console as securetty
89 cat << EOF >> $rootfs/etc/securetty
93 cat <<EOF >> $rootfs/etc/sysconfig/boot
96 ROOTFS_BLKDEV="/dev/null"
100 # remove pointless services in a container
101 ln -s /dev
/null
$rootfs/etc
/systemd
/system
/proc-sys-fs-binfmt_misc.automount
102 ln -s /dev
/null
$rootfs/etc
/systemd
/system
/console-shell.service
103 ln -s /dev
/null
$rootfs/etc
/systemd
/system
/systemd-vconsole-setup.service
104 sed -e 's/ConditionPathExists=.*//' $rootfs/usr
/lib
/systemd
/system
/getty@.service
> $rootfs/etc
/systemd
/system
/getty@.service
105 ln -s getty@.service
$rootfs/etc
/systemd
/system
/getty@tty1.service
106 ln -s ..
/getty@.service
$rootfs/etc
/systemd
/system
/getty.target.wants
/getty@console.service
107 ln -s -f ..
/getty@.service
$rootfs/etc
/systemd
/system
/getty.target.wants
/getty@tty1.service
108 ln -s ..
/getty@.service
$rootfs/etc
/systemd
/system
/getty.target.wants
/getty@tty2.service
109 ln -s ..
/getty@.service
$rootfs/etc
/systemd
/system
/getty.target.wants
/getty@tty3.service
110 ln -s ..
/getty@.service
$rootfs/etc
/systemd
/system
/getty.target.wants
/getty@tty4.service
112 touch $rootfs/etc
/sysconfig
/kernel
114 echo "Please change root-password !"
124 if [ ! -x ${BUILD} ]; then
125 echo "Could not create openSUSE template :"
126 echo "you need to install \"build\" package"
130 # check the mini opensuse was not already downloaded
131 mkdir
-p "$cache/partial-$arch"
133 if [ $?
-ne 0 ]; then
134 echo "Failed to create '$cache/partial-$arch' directory"
138 # download a mini opensuse into a cache
139 echo "Downloading opensuse minimal ..."
140 mkdir
-p "$cache/partial-$arch-packages"
141 if [[ $DISTRO == "tumbleweed" ]]; then
142 zypper
--quiet --root $cache/partial-
$arch-packages --non-interactive ar http
://download.opensuse.org
/$DISTRO/repo
/oss
/ repo-oss ||
return 1
144 zypper
--quiet --root $cache/partial-
$arch-packages --non-interactive ar http
://download.opensuse.org
/distribution
/$DISTRO/repo
/oss
/ repo-oss ||
return 1
146 # Leap update repos were rearranged
147 if [[ $DISTRO == "leap/4"* ]]; then
148 zypper
--quiet --root $cache/partial-
$arch-packages --non-interactive ar http
://download.opensuse.org
/update
/$DISTRO/oss
/ update ||
return 1
150 zypper
--quiet --root $cache/partial-
$arch-packages --non-interactive ar http
://download.opensuse.org
/update
/$DISTRO/ update ||
return 1
152 zypper
--quiet --root $cache/partial-
$arch-packages --non-interactive --gpg-auto-import-keys update ||
return 1
153 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
154 cat > $cache/partial-
$arch-packages/opensuse.conf
<< EOF
155 Preinstall: aaa_base bash coreutils diffutils
156 Preinstall: filesystem fillup glibc grep insserv-compat perl-base
157 Preinstall: libbz2-1 libncurses5 pam
158 Preinstall: permissions libreadline6 rpm sed tar libz1 libselinux1
159 Preinstall: liblzma5 libcap2 libacl1 libattr1
160 Preinstall: libpopt0 libelf1 liblua5_1
166 Support: patterns-openSUSE-base
168 Support: ncurses-utils
172 Support: hwinfo insserv-compat module-init-tools openSUSE-release openssh
173 Support: pwdutils rpcbind sysconfig
175 Ignore: rpm:suse-build-key,build-key
176 Ignore: systemd:systemd-presets-branding
179 if [ $DISTRO = "13.2" ]
181 echo "Support: python3-base" >> $cache/partial-
$arch-packages/opensuse.conf
184 # dhcpcd is not in the default repos since Leap 42.1
185 if [[ $DISTRO != "leap/4"* ]]
187 echo "Support: dhcpcd" >> $cache/partial-
$arch-packages/opensuse.conf
190 # Leap doesn't seem to have iproute2 utils installed
191 if [[ $DISTRO == "leap/4"* ]]
193 echo "Support: net-tools iproute2" >> $cache/partial-
$arch-packages/opensuse.conf
196 if [ "$arch" = "i686" ]; then
197 mkdir
-p $cache/partial-
$arch-packages/var
/cache
/zypp
/packages
/repo-oss
/suse
/i686
/
198 for i
in "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i586/*" ; do
199 ln -s $i $cache/partial-
$arch-packages/var
/cache
/zypp
/packages
/repo-oss
/suse
/i686
/
201 mkdir
-p $cache/partial-
$arch-packages/var
/cache
/zypp
/packages
/update
/i686
202 for i
in "$cache/partial-$arch-packages/var/cache/zypp/packages/update/i586/*" ; do
203 ln -s $i $cache/partial-
$arch-packages/var
/cache
/zypp
/packages
/update
/i686
/
207 # openSUSE 13.2 has no noarch directory in update
208 [ -d $cache/partial-
$arch-packages/var
/cache
/zypp
/packages
/update
/noarch
] || mkdir
-p $cache/partial-
$arch-packages/var
/cache
/zypp
/packages
/update
/noarch
210 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 --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
211 chroot
$cache/partial-
$arch /usr
/bin
/zypper
--quiet --non-interactive ar http
://download.opensuse.org
/distribution
/$DISTRO/repo
/oss repo-oss ||
return 1
213 if [[ $DISTRO == "leap/4"* ]]; then
214 chroot
$cache/partial-
$arch /usr
/bin
/zypper
--quiet --non-interactive ar http
://download.opensuse.org
/update
/$DISTRO/oss update ||
return 1
216 chroot
$cache/partial-
$arch /usr
/bin
/zypper
--quiet --non-interactive ar http
://download.opensuse.org
/update
/$DISTRO/ update ||
return 1
219 # really clean the image
220 rm -fr $cache/partial-
$arch/{.build
,.guessed_dist
,.srcfiles
*,installed-pkg
}
221 rm -fr $cache/partial-
$arch/dev
222 # make sure we have a minimal /dev
223 mkdir
-p "$cache/partial-$arch/dev"
224 mknod
-m 666 $cache/partial-
$arch/dev
/null c
1 3
225 mknod
-m 666 $cache/partial-
$arch/dev
/zero c
1 5
226 # create mtab symlink
227 rm -f $cache/partial-
$arch/etc
/mtab
228 ln -sf /proc
/self
/mounts
$cache/partial-
$arch/etc
/mtab
230 # ensure /var/run and /run are symlinked
231 rm -fr $cache/partial-
$arch/var
/run
232 ln -s -f ..
/run
$cache/partial-
$arch/var
/run
233 if [ $?
-ne 0 ]; then
234 echo "Failed to download the rootfs, aborting."
238 rm -fr "$cache/partial-$arch-packages"
239 mv "$1/partial-$arch" "$1/rootfs-$arch"
240 echo "Download complete."
251 # make a local copy of the mini opensuse
252 echo "Copying rootfs to $rootfs ..."
254 rsync
-Ha $cache/rootfs-
$arch/ $rootfs/ ||
return 1
260 # Allow the cache base to be set by environment variable
261 cache
="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/opensuse/$DISTRO}"
263 mkdir
-p @LOCALSTATEDIR@
/lock
/subsys
/
266 if [ $?
-ne 0 ]; then
267 echo "Cache repository is busy."
271 echo "Checking cache download in $cache/rootfs-$arch ... "
272 if [ ! -e "$cache/rootfs-$arch" ]; then
273 download_opensuse
$cache $arch
274 if [ $?
-ne 0 ]; then
275 echo "Failed to download 'opensuse base'"
280 echo "Copy $cache/rootfs-$arch to $rootfs ... "
281 copy_opensuse
$cache $arch $rootfs
282 if [ $?
-ne 0 ]; then
283 echo "Failed to copy rootfs"
288 ) 9>@LOCALSTATEDIR@
/lock
/subsys
/lxc-opensuse
293 # Generate a random hardware (MAC) address composed of FE followed by
297 openssl rand
-hex 5 |
sed -e 's/\(..\)/:\1/g; s/^/fe/'
306 grep -q "^lxc.rootfs" $path/config
2>/dev
/null ||
echo "
307 lxc.rootfs = $rootfs_path
310 # The following code is to create static MAC addresses for each
311 # interface in the container. This code will work for multiple
312 # interfaces in the default config. It will also strip any
313 # hwaddr stanzas out of the default config since we can not share
314 # MAC addresses between containers.
316 # This code is largely mimiced from the Fedora Template.
317 mv $path/config
$path/config.def
320 # This should catch variable expansions from the default config...
321 if expr "${LINE}" : '.*\$' > /dev
/null
2>&1
323 LINE
=$
(eval "echo \"${LINE}\"")
326 # There is a tab and a space in the regex bracket below!
327 # Seems that \s doesn't work in brackets.
328 KEY
=$
(expr "${LINE}" : '\s*\([^ ]*\)\s*=')
330 if [[ "${KEY}" != "lxc.net.0.hwaddr" ]]
332 echo "${LINE}" >> $path/config
334 if [[ "${KEY}" == "lxc.net.0.link" ]]
336 echo "lxc.net.0.hwaddr = $(create_hwaddr)" >> $path/config
339 done < $path/config.def
341 rm -f $path/config.def
343 if [ -e "@LXCTEMPLATECONFIG@/opensuse.common.conf" ]; then
345 # Include common configuration
346 lxc.include = @LXCTEMPLATECONFIG@/opensuse.common.conf
350 # Append things which require expansion here...
351 cat <<EOF >> $path/config
355 lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
357 # When using LXC with apparmor, uncomment the next line to run unconfined:
358 lxc.aa_profile = unconfined
360 # example simple networking setup, uncomment to enable
361 #lxc.net.0.type = $lxc_network_type
362 #lxc.net.0.flags = up
363 #lxc.net.0.link = $lxc_network_link
364 #lxc.net.0.name = eth0
365 # Additional example for veth network type
366 # static MAC address,
367 #lxc.net.0.hwaddr = 00:16:3e:77:52:20
368 # persistent veth device name on host side
369 # Note: This may potentially collide with other containers of same name!
370 #lxc.net.0.veth.pair = v-$name-e0
374 if [ $?
-ne 0 ]; then
375 echo "Failed to add configuration"
384 cache
="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/opensuse}"
386 if [ ! -e $cache ]; then
390 # lock, so we won't purge while someone is creating a repository
394 echo "Cache repository is busy."
398 echo -n "Purging the download cache..."
399 rm --preserve-root --one-file-system -rf $cache && echo "Done." ||
exit 1
401 ) 9>@LOCALSTATEDIR@
/lock
/subsys
/lxc-opensuse
407 $1 -h|--help -p|--path=<path> -r|--release nn.n --clean
408 Please give the release as 13.1, 13.2 etc.
409 If no release is given, openSUSE Leap 42.2 is installed.
414 # Make arch a global. This may become configurable?
417 options
=$
(getopt
-o hp
:n
:r
:c
-l help,rootfs
:,path
:,name
:,release
:,clean
-- "$@")
418 if [ $?
-ne 0 ]; then
422 eval set -- "$options"
427 -h|
--help) usage
$0 && exit 0;;
428 -p|
--path) path
=$2; shift 2;;
429 --rootfs) rootfs
=$2; shift 2;;
430 -n|
--name) name
=$2; shift 2;;
431 -r|
--release) DISTRO
=$2; shift 2;;
432 -c|
--clean) clean
=1; shift 1;;
433 --) shift 1; break ;;
438 if [ ! -z "$clean" -a -z "$path" ]; then
443 type zypper
> /dev
/null
444 if [ $?
-ne 0 ]; then
445 echo "'zypper' command is missing"
449 if [ -z "$path" ]; then
450 echo "'path' parameter is required"
454 if grep -q Harlequin
/etc
/os-release ||
grep -q Tumbleweed
/etc
/os-release
; then
455 BVER
=`rpm -q --qf '%{version}\n' build`
456 if [ $?
-ne 0 -o "$BVER" -lt "20141120" ]; then
457 echo "Building openSUSE containers with your version of the build package is broken. Please install the update to version 20141120 or newer."
462 if [ -z "$DISTRO" ]; then
464 echo "No release selected, using openSUSE Leap 42.2"
470 echo "Selected openSUSE 13.1"
474 echo "Selected openSUSE 13.2"
478 echo "Selected openSUSE Leap 42.1"
483 echo "Selected openSUSE Leap 42.2"
487 echo "Selected openSUSE Leap Tumbleweed"
492 echo "You have chosen an invalid release, quitting..."
499 if [ "$(id -u)" != "0" ]; then
500 echo "This script should be run as 'root'"
505 config
="$path/config"
506 if [ -z "$rootfs" ]; then
507 if grep -q '^lxc.rootfs' $config 2>/dev
/null
; then
508 rootfs
=$
(awk -F= '/^lxc.rootfs =/{ print $2 }' $config)
514 install_opensuse
$rootfs
515 if [ $?
-ne 0 ]; then
516 echo "failed to install opensuse"
520 configure_opensuse
$rootfs $name
521 if [ $?
-ne 0 ]; then
522 echo "failed to configure opensuse for a container"
526 copy_configuration
$path $rootfs $name
527 if [ $?
-ne 0 ]; then
528 echo "failed write configuration file"
532 if [ ! -z "$clean" ]; then