]> git.proxmox.com Git - mirror_lxc.git/blame - templates/lxc-fedora.in
lxc-ubuntu-cloud: Fix cache and lock location
[mirror_lxc.git] / templates / lxc-fedora.in
CommitLineData
54b1eb68 1#!/bin/bash
54b1eb68 2
b6e91b67
DL
3#
4# template script for generating fedora container for LXC
5#
54b1eb68 6
b6e91b67
DL
7#
8# lxc: linux Container library
54b1eb68 9
b6e91b67
DL
10# Authors:
11# Daniel Lezcano <daniel.lezcano@free.fr>
579ebf12 12# Ramez Hanna <rhanna@informatiq.org>
449989ac 13# Michael H. Warfield <mhw@WittsEnd.com>
54b1eb68 14
b6e91b67
DL
15# This library is free software; you can redistribute it and/or
16# modify it under the terms of the GNU Lesser General Public
17# License as published by the Free Software Foundation; either
18# version 2.1 of the License, or (at your option) any later version.
54b1eb68 19
b6e91b67
DL
20# This library is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23# Lesser General Public License for more details.
54b1eb68 24
b6e91b67
DL
25# You should have received a copy of the GNU Lesser General Public
26# License along with this library; if not, write to the Free Software
250b1eec 27# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
54b1eb68 28
579ebf12 29#Configurations
ed4616b1 30arch=$(uname -m)
e29bf450
DE
31cache_base=@LOCALSTATEDIR@/cache/lxc/fedora/$arch
32default_path=@LXCPATH@
b4f7af7a
MW
33
34# Some combinations of the tunning knobs below do not exactly make sense.
35# but that's ok.
36#
37# If the "root_password" is non-blank, use it, else set a default.
38# This can be passed to the script as an environment variable and is
39# set by a shell conditional assignment. Looks weird but it is what it is.
40#
41# If the root password contains a ding ($) then try to expand it.
42# That will pick up things like ${name} and ${RANDOM}.
43# If the root password contians more than 3 consecutive X's, pass it as
44# a template to mktemp and take the result.
45#
46# If root_display_password = yes, display the temporary root password at exit.
47# If root_store_password = yes, store it in the configuration directory
48# If root_prompt_password = yes, invoke "passwd" to force the user to change
49# the root password after the container is created.
50#
51# These are conditional assignments... The can be overridden from the
52# preexisting environment variables...
53#
54# Make sure this is in single quotes to defer expansion to later!
55# :{root_password='Root-${name}-${RANDOM}'}
56: ${root_password='Root-${name}-XXXXXX'}
57
58# Now, it doesn't make much sense to display, store, and force change
59# together. But, we gotta test, right???
60: ${root_display_password='no'}
61: ${root_store_password='yes'}
62# Prompting for something interactive has potential for mayhem
63# with users running under the API... Don't default to "yes"
64: ${root_prompt_password='no'}
65
66# These are only going into comments in the resulting config...
67lxc_network_type=veth
68lxc_network_link=lxcbr0
579ebf12
I
69
70# is this fedora?
627fe3b4 71# Alow for weird remixes like the Raspberry Pi
b9b3a92f
MW
72#
73# Use the Mitre standard CPE identifier for the release ID if possible...
74# This may be in /etc/os-release or /etc/system-release-cpe. We
75# should be able to use EITHER. Give preference to /etc/os-release for now.
76
77if [ -e /etc/os-release ]
78then
79# This is a shell friendly configuration file. We can just source it.
80# What we're looking for in here is the ID, VERSION_ID and the CPE_NAME
81 . /etc/os-release
82 echo "Host CPE ID from /etc/os-release: ${CPE_NAME}"
83fi
84
85if [ "${CPE_NAME}" = "" -a -e /etc/system-release-cpe ]
86then
87 CPE_NAME=$(head -n1 /etc/system-release-cpe)
53bd92ea 88 CPE_URI=$(expr ${CPE_NAME} : '\([^:]*:[^:]*\)')
b9b3a92f
MW
89 if [ "${CPE_URI}" != "cpe:/o" ]
90 then
91 CPE_NAME=
92 else
93 echo "Host CPE ID from /etc/system-release-cpe: ${CPE_NAME}"
94 # Probably a better way to do this but sill remain posix
95 # compatible but this works, shrug...
96 # Must be nice and not introduce convenient bashisms here.
97 ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:\([^:]*\)')
98 VERSION_ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\)')
99 fi
100fi
101
dfa7aa3a 102if [ "${CPE_NAME}" != "" -a "${ID}" = "fedora" -a "${VERSION_ID}" != "" ]
627fe3b4 103then
b9b3a92f
MW
104 fedora_host_ver=${VERSION_ID}
105 is_fedora=true
106elif [ -e /etc/redhat-release ]
107then
108 # Only if all other methods fail, try to parse the redhat-release file.
627fe3b4
MW
109 fedora_host_ver=$( sed -e '/^Fedora /!d' -e 's/Fedora.*\srelease\s*\([0-9][0-9]*\)\s.*/\1/' < /etc/redhat-release )
110 if [ "$fedora_host_ver" != "" ]
111 then
112 is_fedora=true
113 fi
7d303dea
TS
114fi
115
627fe3b4
MW
116# Map a few architectures to their generic Fedora repository archs.
117# The two ARM archs are a bit of a guesstimate for the v5 and v6
118# archs. V6 should have hardware floating point (Rasberry Pi).
119# The "arm" arch is safer (no hardware floating point). So
120# there may be cases where we "get it wrong" for some v6 other
121# than RPi.
122case "$arch" in
123i686) arch=i386 ;;
124armv3l|armv4l|armv5l) arch=arm ;;
125armv6l|armv7l|armv8l) arch=armhfp ;;
126esac
127
b6e91b67
DL
128configure_fedora()
129{
b6e91b67
DL
130
131 # disable selinux in fedora
579ebf12
I
132 mkdir -p $rootfs_path/selinux
133 echo 0 > $rootfs_path/selinux/enforce
54b1eb68 134
5266cf0a
MW
135 # Also kill it in the /etc/selinux/config file if it's there...
136 if [[ -f $rootfs_path/etc/selinux/config ]]
137 then
138 sed -i '/^SELINUX=/s/.*/SELINUX=disabled/' $rootfs_path/etc/selinux/config
139 fi
140
141 # Nice catch from Dwight Engen in the Oracle template.
142 # Wantonly plagerized here with much appreciation.
143 if [ -f $rootfs_path/usr/sbin/selinuxenabled ]; then
144 mv $rootfs_path/usr/sbin/selinuxenabled $rootfs_path/usr/sbin/selinuxenabled.lxcorig
145 ln -s /bin/false $rootfs_path/usr/sbin/selinuxenabled
146 fi
147
148 # This is a known problem and documented in RedHat bugzilla as relating
67660331
MW
149 # to a problem with auditing enabled. This prevents an error in
150 # the container "Cannot make/remove an entry for the specified session"
151 sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/login
5266cf0a 152 sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/sshd
67660331 153
53bd92ea
MW
154 if [ -f ${rootfs_path}/etc/pam.d/crond ]
155 then
156 sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/crond
157 fi
158
159 # In addition to disabling pam_loginuid in the above config files
160 # we'll also disable it by linking it to pam_permit to catch any
161 # we missed or any that get installed after the container is built.
162 #
163 # Catch either or both 32 and 64 bit archs.
164 if [ -f ${rootfs_path}/lib/security/pam_loginuid.so ]
165 then
166 ( cd ${rootfs_path}/lib/security/
167 mv pam_loginuid.so pam_loginuid.so.disabled
168 ln -s pam_permit.so pam_loginuid.so
169 )
170 fi
171
172 if [ -f ${rootfs_path}/lib64/security/pam_loginuid.so ]
173 then
174 ( cd ${rootfs_path}/lib64/security/
175 mv pam_loginuid.so pam_loginuid.so.disabled
176 ln -s pam_permit.so pam_loginuid.so
177 )
178 fi
179
99c2fb07
MW
180 # Deal with some dain bramage in the /etc/init.d/halt script.
181 # Trim it and make it our own and link it in before the default
182 # halt script so we can intercept it. This also preventions package
183 # updates from interferring with our interferring with it.
184 #
185 # There's generally not much in the halt script that useful but what's
186 # in there from resetting the hardware clock down is generally very bad.
187 # So we just eliminate the whole bottom half of that script in making
188 # ourselves a copy. That way a major update to the init scripts won't
189 # trash what we've set up.
190 #
191 # This is mostly for legacy distros since any modern systemd Fedora
192 # release will not have this script so we won't try to intercept it.
193 if [ -f ${rootfs_path}/etc/init.d/halt ]
194 then
195 sed -e '/hwclock/,$d' \
196 < ${rootfs_path}/etc/init.d/halt \
197 > ${rootfs_path}/etc/init.d/lxc-halt
198
199 echo '$command -f' >> ${rootfs_path}/etc/init.d/lxc-halt
200 chmod 755 ${rootfs_path}/etc/init.d/lxc-halt
201
202 # Link them into the rc directories...
203 (
204 cd ${rootfs_path}/etc/rc.d/rc0.d
205 ln -s ../init.d/lxc-halt S00lxc-halt
206 cd ${rootfs_path}/etc/rc.d/rc6.d
207 ln -s ../init.d/lxc-halt S00lxc-reboot
208 )
209 fi
210
67660331 211 # configure the network using the dhcp
579ebf12
I
212 cat <<EOF > ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0
213DEVICE=eth0
214BOOTPROTO=dhcp
215ONBOOT=yes
b9b3a92f 216HOSTNAME=${utsname}
579ebf12
I
217NM_CONTROLLED=no
218TYPE=Ethernet
219MTU=${MTU}
54b1eb68 220EOF
54b1eb68 221
b6e91b67 222 # set the hostname
579ebf12
I
223 cat <<EOF > ${rootfs_path}/etc/sysconfig/network
224NETWORKING=yes
b9b3a92f 225HOSTNAME=${utsname}
b6e91b67 226EOF
54b1eb68 227
627fe3b4
MW
228 # set hostname on systemd Fedora systems
229 if [ $release -gt 14 ]; then
b9b3a92f 230 echo "${utsname}" > ${rootfs_path}/etc/hostname
627fe3b4
MW
231 fi
232
579ebf12
I
233 # set minimal hosts
234 cat <<EOF > $rootfs_path/etc/hosts
b9b3a92f 235127.0.0.1 localhost.localdomain localhost $utsname
627fe3b4 236::1 localhost6.localdomain6 localhost6
b6e91b67 237EOF
54b1eb68 238
5266cf0a
MW
239 # These mknod's really don't make any sense with modern releases of
240 # Fedora with systemd, devtmpfs, and autodev enabled. They are left
241 # here for legacy reasons and older releases with upstart and sysv init.
579ebf12
I
242 dev_path="${rootfs_path}/dev"
243 rm -rf $dev_path
244 mkdir -p $dev_path
245 mknod -m 666 ${dev_path}/null c 1 3
246 mknod -m 666 ${dev_path}/zero c 1 5
247 mknod -m 666 ${dev_path}/random c 1 8
248 mknod -m 666 ${dev_path}/urandom c 1 9
249 mkdir -m 755 ${dev_path}/pts
250 mkdir -m 1777 ${dev_path}/shm
251 mknod -m 666 ${dev_path}/tty c 5 0
252 mknod -m 666 ${dev_path}/tty0 c 4 0
253 mknod -m 666 ${dev_path}/tty1 c 4 1
254 mknod -m 666 ${dev_path}/tty2 c 4 2
255 mknod -m 666 ${dev_path}/tty3 c 4 3
256 mknod -m 666 ${dev_path}/tty4 c 4 4
257 mknod -m 600 ${dev_path}/console c 5 1
258 mknod -m 666 ${dev_path}/full c 1 7
259 mknod -m 600 ${dev_path}/initctl p
260 mknod -m 666 ${dev_path}/ptmx c 5 2
261
b4f7af7a
MW
262 if [ ${root_display_password} = "yes" ]
263 then
264 echo "Setting root password to '$root_password'"
265 fi
266 if [ ${root_store_password} = "yes" ]
267 then
268 touch ${config_path}/tmp_root_pass
269 chmod 600 ${config_path}/tmp_root_pass
270 echo ${root_password} > ${config_path}/tmp_root_pass
271 echo "Storing root password in '${config_path}/tmp_root_pass'"
272 fi
273
579ebf12 274 echo "root:$root_password" | chroot $rootfs_path chpasswd
b4f7af7a
MW
275 # Also set this password as expired to force the user to change it!
276 chroot $rootfs_path passwd -e root
54b1eb68 277
cb26f1a5 278 # specifying this in the initial packages doesn't always work.
449989ac 279 # Even though it should have...
cb26f1a5 280 echo "installing fedora-release package"
449989ac
MW
281 mount -o bind /dev ${rootfs_path}/dev
282 mount -t proc proc ${rootfs_path}/proc
283 # Always make sure /etc/resolv.conf is up to date in the target!
284 cp /etc/resolv.conf ${rootfs_path}/etc/
285 # Rebuild the rpm database based on the target rpm version...
286 rm -f ${rootfs_path}/var/lib/rpm/__db*
287 chroot ${rootfs_path} rpm --rebuilddb
288 chroot ${rootfs_path} yum -y install fedora-release
67660331
MW
289
290 if [[ ! -e ${rootfs_path}/sbin/NetworkManager ]]
291 then
292 # NetworkManager has not been installed. Use the
293 # legacy chkconfig command to enable the network startup
294 # scripts in the container.
295 chroot ${rootfs_path} chkconfig network on
296 fi
297
449989ac
MW
298 umount ${rootfs_path}/proc
299 umount ${rootfs_path}/dev
cb26f1a5
SG
300
301 # silence some needless startup errors
302 touch ${rootfs_path}/etc/fstab
303
304 # give us a console on /dev/console
305 sed -i 's/ACTIVE_CONSOLES=.*$/ACTIVE_CONSOLES="\/dev\/console \/dev\/tty[1-4]"/' \
306 ${rootfs_path}/etc/sysconfig/init
307
b6e91b67
DL
308 return 0
309}
5266cf0a 310
f9d0d2cb
I
311configure_fedora_init()
312{
313 sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.sysinit
314 sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.d/rc.sysinit
cb26f1a5
SG
315 # don't mount devpts, for pete's sake
316 sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.sysinit
317 sed -i 's/^.*dev.pts.*$/#\0/' ${rootfs_path}/etc/rc.d/rc.sysinit
f9d0d2cb
I
318 chroot ${rootfs_path} chkconfig udev-post off
319 chroot ${rootfs_path} chkconfig network on
320}
321
322configure_fedora_systemd()
323{
b4f7af7a 324 rm -f ${rootfs_path}/etc/systemd/system/default.target
f9d0d2cb 325 touch ${rootfs_path}/etc/fstab
5bb4a226 326 chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/udev.service
f9d0d2cb
I
327 chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
328 #dependency on a device unit fails it specially that we disabled udev
d1240f03
MW
329 # sed -i 's/After=dev-%i.device/After=/' ${rootfs_path}/lib/systemd/system/getty\@.service
330 #
331 # Actually, the After=dev-%i.device line does not appear in the
332 # Fedora 17 or Fedora 18 systemd getty\@.service file. It may be left
333 # over from an earlier version and it's not doing any harm. We do need
334 # to disable the "ConditionalPathExists=/dev/tty0" line or no gettys are
335 # started on the ttys in the container. Lets do it in an override copy of
336 # the service so it can still pass rpm verifies and not be automatically
337 # updated by a new systemd version. -- mhw /\/\|=mhw=|\/\/
338
339 sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \
340 -e 's/After=dev-%i.device/After=/' \
8983aa6e
SG
341 < ${rootfs_path}/lib/systemd/system/getty\@.service \
342 > ${rootfs_path}/etc/systemd/system/getty\@.service
d1240f03
MW
343 # Setup getty service on the 4 ttys we are going to allow in the
344 # default config. Number should match lxc.tty
345 ( cd ${rootfs_path}/etc/systemd/system/getty.target.wants
346 for i in 1 2 3 4 ; do ln -sf ../getty\@.service getty@tty${i}.service; done )
f9d0d2cb 347}
54b1eb68 348
449989ac
MW
349### BEGIN Bootstrap Environment Code... Michael H. Warfield /\/\|=mhw=|\/\/
350
351# Ok... Heads up. If you're reading these comments, you're either a
352# template owner or someone wondering how the hell I did this (or, worse,
353# someone in the future trying to maintain it). This code is slightly
354# "evil coding bastard" code with one significant hack / dirty trick
355# that you would probably miss just reading the code below. I'll mark
356# it out with comments.
0655a606 357#
449989ac
MW
358# Because of what this code does, it deserves a lot of comments so people
359# can understand WHY I did it this way...
360#
361# Ultimate Objective - Build a Fedora container on a host system which does
362# not have a (complete compatible) version of rpm and/or yum. That basically
363# means damn near any distro other than Fedora and Ubuntu (which has rpm and
364# yum available). Only requirements for this function are rsync and
365# squashfs available to the kernel. If you don't have those, why are you
366# even attempting to build containers?
367#
368# Challenge for this function - Bootstrap a Fedora install bootstrap
369# run time environment which has all the pieces to run rpm and yum and
370# from which we can build targets containers even where the host system
371# has no support for rpm, yum, or fedora.
372#
373# Steps:
374# Stage 0 - Download a Fedora LiveOS squashfs core (netinst core).
375# Stage 1 - Extract filesystem from Stage 0 and update to full rpm & yum
376# Stage 2 - Use Stage 1 to build a rootfs with python, rpm, and yum.
377#
378# Stage 2 becomes our bootstrap file system which can be cached
379# and then used to build other arbitrary vesions of Fedora of a
380# given architecture. Not that this only has to run once for
381# Fedora on a given architecture since rpm and yum can build other
382# versions. We'll arbitrarily pick Fedora 19 to build this. This
383# will need to change as time goes on.
384
385# Programmers Note... A future fall back may be to download the netinst
386# iso image instead of the LiveOS squasfs image and work from that.
387# That may be more general but will introduce another substep
388# (mounting the iso) to the stage0 setup.
389
390# This system is designed to be as autonomous as possible so all whitelists
391# and controlls are self-contained.
392
393# Initial testing - Whitelist nobody. Build for everybody...
394# Initial deployment - Whitelist Fedora.
395# Long term - Whitelist Fedora, Debian, Ubuntu, CentOs, Scientific, and NST.
396
397# List of distros which do not (should not) need a bootstrap (but we will test
398# for rpm and yum none the less... OS SHOULD be taken from CPE values but
399# Debian / Ubuntu doesn't support CPE yet.
400
401# BOOTSTRAP_WHITE_LIST=""
402BOOTSTRAP_WHITE_LIST="fedora"
403# BOOTSTRAP_WHITE_LIST="fedora debian ubuntu centos scientific sl nst"
404
405BOOTSTRAP=0
406BOOTSTRAP_DIR=
407BOOTSTRAP_CHROOT=
408
409fedora_get_bootstrap()
410{
411 echo "Bootstrap Environment testing..."
412
413 WHITE_LISTED=1
414
415 # We need rpm. No rpm - not possible to white list...
416 if ! which rpm > /dev/null 2>&1
417 then
418 WHITE_LISTED=0
419 fi
420
421 # We need yum No yum - not possible to white list...
422 if ! which yum > /dev/null 2>&1
423 then
424 WHITE_LISTED=0
425 fi
426
427 if [[ ${WHITE_LISTED} != 0 ]]
428 then
429 for OS in ${BOOTSTRAP_WHITE_LIST}
430 do
431 if [[ ${ID} = ${OS} ]]
432 then
433 echo "
434OS ${ID} is whitelisted. Installation Bootstrap Environment not required.
435"
436 return 0;
437 fi
438 done
439 fi
440
441 echo "
442Fedora Installation Bootstrap Build..."
443
444 if ! which rsync > /dev/null 2>&1
445 then
446 echo "
447Unable to locate rsync. Cravely bailing out before even attempting to build
448an Installation Bootstrap Please install rsync and then rerun this process.
449"
450
451 return 255
452 fi
453
454 [[ -d ${cache_base} ]] || mkdir -p ${cache_base}
455
456 cd ${cache_base}
457
458 # We know we don't have a cache directory of this version or we
459 # would have never reached this code to begin with. But we may
460 # have another Fedora cache directory from which we could run...
461 # We'll give a preference for close matches prefering higher over
462 # lower - which makes for really ugly code...
463
464 # Is this a "bashism" that will need cleaning up????
465 BOOTSTRAP_LIST="$(( $release + 1 ))/rootfs $(( $release - 1 ))/rootfs \
466$(( $release + 2 ))/rootfs $(( $release - 2 ))/rootfs \
467$(( $release + 3 ))/rootfs $(( $release - 3 ))/rootfs \
468bootstrap"
469
470 for bootstrap in ${BOOTSTRAP_LIST}
471 do
472 if [[ -d ${bootstrap} ]]
473 then
474 echo "
475Existing Bootstrap found. Testing..."
476
477 mount -o bind /dev ${bootstrap}/dev
478 mount -t proc proc ${bootstrap}/proc
479 # Always make sure /etc/resolv.conf is up to date in the target!
480 cp /etc/resolv.conf ${bootstrap}/etc/
481 rm -f ${bootstrap}/var/lib/rpm/__db*
482 chroot ${bootstrap} rpm --rebuilddb
483 chroot ${bootstrap} yum -y update
484 RC=$?
485 umount ${bootstrap}/proc
486 umount ${bootstrap}/dev
487
488 if [[ 0 == ${RC} ]]
489 then
490 BOOTSTRAP=1
491 BOOTSTRAP_DIR="${cache_base}/${bootstrap}"
492 BOOTSTRAP_CHROOT="chroot ${BOOTSTRAP_DIR} "
493 BOOTSTRAP_INSTALL_ROOT=/run/install
494
495 echo "
496Functional Installation Bootstrap exists and appears to be completed.
497Will use existing Bootstrap: ${BOOTSTRAP_DIR}
498"
499 return 0
500 fi
501 echo "
502Installation Bootstrap in ${BOOTSTRAP_DIR} exists
503but appears to be non-functional. Skipping... It should be removed.
504"
505 fi
506 done
507
508 TMP_BOOTSTRAP_DIR=$( mktemp -d --tmpdir=${cache_base} bootstrap_XXXXXX )
509
510 cd ${TMP_BOOTSTRAP_DIR}
511
512 mkdir squashfs stage0 stage1 bootstrap
513
514### Stage 0 setup.
515# Download the LiveOS squashfs image
516# mount image to "squashfs"
517# mount contained LiveOS to stage0
518
519# We're going to use the kernel.org mirror for the initial stages...
520# 1 - It's generally up to date and comnplete
521# 2 - It's has high bandwidth access
522# 3 - It supports rsync and wildcarding (and we need both)
523# 4 - Not all the mirrors carry the LiveOS images
524
525 if [[ ! -f ../LiveOS/squashfs.img ]]
526 then
527 echo "
528Downloading stage 0 LiveOS squashfs file system from mirrors.kernel.org...
529Have a beer or a cup of coffee. This will take a bit (~300MB).
530"
531 sleep 3 # let him read it...
532
533 # Right now, we are using Fedora 19 for the inial bootstrap.
534 # We could make this the "current" Fedora rev (F > 15).
535
6a59920b 536 rsync -av mirrors.kernel.org::fedora/releases/19/Fedora/$arch/os/LiveOS .
449989ac
MW
537
538 if [[ 0 == $? ]]
539 then
540 echo "Download of squashfs image complete."
541 mv LiveOS ..
542 else
543 echo "
544Download of squashfs image failed.
545"
546 return 255
547 fi
548 else
549 echo "Using cached stage 0 LiveOS squashfs file system."
550 fi
551
552 mount -o loop ../LiveOS/squashfs.img squashfs
553
554 if [[ $? != 0 ]]
555 then
556 echo "
557Mount of LiveOS squashfs image failed! You mush have squashfs support
558available to mount image. Unable to continue. Correct and retry
559process later! LiveOS image not removed. Process may be rerun
560without penalty of downloading LiveOS again. If LiveOS is corrupt,
561remove ${cache_base}/LiveOS before rerunning to redownload.
562"
563 return 255
564 fi
565
566 mount -o loop squashfs/LiveOS/rootfs.img stage0
567
568 if [[ $? != 0 ]]
569 then
570 echo "
571Mount of LiveOS stage0 rootfs image failed! LiveOS download may be corrupt.
572Remove ${cache_base}/LiveOS to force a new download or
573troubleshoot cached image and then rerun process.
574"
575 return 255
576 fi
577
578
579### Stage 1 setup.
580# Copy stage0 (which is ro) to stage1 area (rw) for modification.
581# Unmount stage0 mounts - we're done with stage 0 at this point.
582# Download our rpm and yum rpm packages.
583# Force install of rpm and yum into stage1 image (dirty hack!)
584
585 echo "Stage 0 complete, building Stage 1 image...
586This will take a couple of minutes. Patience..."
587
588 echo "Creating Stage 1 r/w copy of r/o Stage 0 squashfs image from LiveOS."
589
590 rsync -aAHS stage0/. stage1/
591
592 umount stage0
593 umount squashfs
594
595 cd stage1
596
597 # Setup stage1 image with pieces to run installs...
598
599
600 mount -o bind /dev dev
601 mount -t proc proc proc
602 # Always make sure /etc/resolv.conf is up to date in the target!
603 cp /etc/resolv.conf etc/
604
605 mkdir run/install
606
607 echo "Updating Stage 1 image with full rpm and yum packages"
608
609 # Retrieve our 2 rpm packages we need to force down the throat
610 # of this LiveOS image we're camped out on. This is the beginning
611 # of the butt ugly hack. Look close or you may missing it...
612
6a59920b
MW
613 rsync -av mirrors.kernel.org::fedora/releases/19/Fedora/$arch/os/Packages/r/rpm-[0-9]* \
614 mirrors.kernel.org::fedora/releases/19/Fedora/$arch/os/Packages/y/yum-[0-9]* .
449989ac
MW
615
616 # And here it is...
617 # The --nodeps is STUPID but F15 had a bogus dependency on RawHide?!?!
618 chroot . rpm -ivh --nodeps rpm-* yum-*
619 # Did you catch it?
620
621 # The LiveOS image contains rpm (but not rpmdb) and yum (but not
622 # yummain.py - What the hell good does yum do with no
623 # yummain.py?!?! - Sigh...). It contains all the supporting
624 # pieces but the rpm database has not be initialized and it
625 # doesn't know all the dependences (seem to) have been met.
626 # So we do a "--nodeps" rpm install in the chrooted environment
627 # to force the installation of the full rpm and yum packages.
628 #
629 # For the purists - Yes, I know the rpm database is wildly out
630 # of whack now. That's why this is a butt ugly hack / dirty trick.
631 # But, this is just the stage1 image that we are going to discard as
632 # soon as the stage2 image is built, so we don't care. All we care
633 # is that the stage2 image ends up with all the pieces it need to
634 # run yum and rpm and that the stage2 rpm database is coherent.
635 #
636 # NOW we can really go to work!
637
638### Stage 2 setup.
639# Download our Fedora Release rpm packages.
640# Install fedora-release into bootstrap to initialize fs and databases.
641# Install rpm, and yum into bootstrap image using yum
642
643 echo "Stage 1 creation complete. Building stage 2 Installation Bootstrap"
644
645 mount -o bind ../bootstrap run/install
6a59920b 646 rsync -av mirrors.kernel.org::fedora/releases/19/Fedora/$arch/os/Packages/f/fedora-release-19* .
449989ac
MW
647
648 # The --nodeps is STUPID but F15 had a bogus dependency on RawHide?!?!
649 chroot . rpm --root /run/install --nodeps -ivh fedora-release-*
650 chroot . yum -y --nogpgcheck --installroot /run/install install python rpm yum
651
652 umount run/install
653 umount proc
654 umount dev
655
656# That's it! We should now have a viable installation BOOTSTRAP in
657# bootstrap We'll do a yum update in that to verify and then
658# move it to the cache location before cleaning up.
659
660 cd ../bootstrap
661 mount -o bind /dev dev
662 mount -t proc proc proc
663 # Always make sure /etc/resolv.conf is up to date in the target!
664 cp /etc/resolv.conf etc/
665
666 chroot . yum -y update
667
668 RC=$?
669
670 umount proc
671 umount dev
672
673 cd ..
674
675 if [[ ${RC} != 0 ]]
676 then
677 echo "
678Build of Installation Bootstrap failed. Temp directory
679not removed so it can be investigated.
680"
681 return 255
682 fi
683
684 # We know have a working run time environment in rootfs...
685 mv bootstrap ..
686 cd ..
687 rm -rf ${TMP_BOOTSTRAP_DIR}
688
689 echo "
690Build of Installation Bootstrap complete! We now return you to your
691normally scheduled template creation.
692"
693
694 BOOTSTRAP=1
695 BOOTSTRAP_DIR="${cache_base}/bootstrap"
696 BOOTSTRAP_CHROOT="chroot ${BOOTSTRAP_DIR} "
697 BOOTSTRAP_INSTALL_ROOT=/run/install
698
699 return 0
700}
701
702
703fedora_bootstrap_mounts()
704{
705 if [[ ${BOOTSTRAP} -ne 1 ]]
706 then
707 return 0
708 fi
709
710 BOOTSTRAP_CHROOT="chroot ${BOOTSTRAP_DIR} "
711
712 echo "Mounting Bootstrap mount points"
713
714 [[ -d ${BOOTSTRAP_DIR}/run/install ]] || mkdir -p ${BOOTSTRAP_DIR}/run/install
715
716 mount -o bind ${INSTALL_ROOT} ${BOOTSTRAP_DIR}/run/install
717 mount -o bind /dev ${BOOTSTRAP_DIR}/dev
718 mount -t proc proc ${BOOTSTRAP_DIR}/proc
719 # Always make sure /etc/resolv.conf is up to date in the target!
720 cp /etc/resolv.conf ${BOOTSTRAP_DIR}/etc/
721}
722
723fedora_bootstrap_umounts()
724{
725 if [[ ${BOOTSTRAP} -ne 1 ]]
726 then
727 return 0
728 fi
729
730 umount ${BOOTSTRAP_DIR}/proc
731 umount ${BOOTSTRAP_DIR}/dev
732 umount ${BOOTSTRAP_DIR}/run/install
733}
734
735
736# This is the code to create the initial roofs for Fedora. It may
737# require a run time environment by calling the routines above...
738
b6e91b67
DL
739download_fedora()
740{
b44cb779 741
b6e91b67 742 # check the mini fedora was not already downloaded
579ebf12
I
743 INSTALL_ROOT=$cache/partial
744 mkdir -p $INSTALL_ROOT
b6e91b67 745 if [ $? -ne 0 ]; then
14d9c0f0
SG
746 echo "Failed to create '$INSTALL_ROOT' directory"
747 return 1
b44cb779
RT
748 fi
749
b6e91b67
DL
750 # download a mini fedora into a cache
751 echo "Downloading fedora minimal ..."
449989ac 752
0655a606 753 # These will get changed if it's decided that we need a
449989ac
MW
754 # boostrap environment (can not build natively)
755
756 BOOTSTRAP_INSTALL_ROOT=${INSTALL_ROOT}
757 BOOTSTRAP_CHROOT=
758
5266cf0a 759 PKG_LIST="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils fedora-release"
7bd44bf6
TS
760 MIRRORLIST_URL="http://mirrors.fedoraproject.org/mirrorlist?repo=fedora-$release&arch=$arch"
761
449989ac
MW
762 if [[ ${release} -lt 17 ]]
763 then
764 # The reflects the move of db_dump and db_load from db4_utils to
765 # libdb_utils in Fedora 17 and above and it's inclusion as a dep...
766 # Prior to Fedora 11, we need to explicitly include it!
767 PKG_LIST="${PKG_LIST} db4-utils"
768 fi
769
7bd44bf6 770 DOWNLOAD_OK=no
b9b3a92f
MW
771
772 # We're splitting the old loop into two loops plus a directory retrival.
773 # First loop... Try and retrive a mirror list with retries and a slight
774 # delay between attempts...
775 for trynumber in 1 2 3 4; do
7bd44bf6 776 [ $trynumber != 1 ] && echo "Trying again..."
8983aa6e 777 # This code is mildly "brittle" in that it assumes a certain
b9b3a92f
MW
778 # page format and parsing HTML. I've done worse. :-P
779 MIRROR_URLS=$(curl -s -S -f "$MIRRORLIST_URL" | sed -e '/^http:/!d' -e '2,6!d')
780 if [ $? -eq 0 ] && [ -n "$MIRROR_URLS" ]
781 then
8983aa6e
SG
782 break
783 fi
b9b3a92f
MW
784
785 echo "Failed to get a mirror on try $trynumber"
786 sleep 3
787 done
788
789 # This will fall through if we didn't get any URLS above
790 for MIRROR_URL in ${MIRROR_URLS}
791 do
449989ac 792 if [ "$release" -gt "16" ]; then
b9b3a92f 793 RELEASE_URL="$MIRROR_URL/Packages/f"
29e18143 794 else
b9b3a92f
MW
795 RELEASE_URL="$MIRROR_URL/Packages/"
796 fi
797
798 echo "Fetching rpm name from $RELEASE_URL..."
8983aa6e 799 # This code is mildly "brittle" in that it assumes a certain directory
b9b3a92f 800 # page format and parsing HTML. I've done worse. :-P
8983aa6e 801 RELEASE_RPM=$(curl -L -f "$RELEASE_URL" | sed -e "/fedora-release-${release}-/!d" -e 's/.*<a href=\"//' -e 's/\">.*//' )
b9b3a92f
MW
802 if [ $? -ne 0 -o "${RELEASE_RPM}" = "" ]; then
803 echo "Failed to identify fedora release rpm."
804 continue
29e18143 805 fi
b9b3a92f
MW
806
807 echo "Fetching fedora release rpm from ${RELEASE_URL}/${RELEASE_RPM}......"
808 curl -L -f "${RELEASE_URL}/${RELEASE_RPM}" > ${INSTALL_ROOT}/${RELEASE_RPM}
7bd44bf6 809 if [ $? -ne 0 ]; then
b9b3a92f 810 echo "Failed to download fedora release rpm ${RELEASE_RPM}."
7bd44bf6
TS
811 continue
812 fi
b9b3a92f 813
7bd44bf6
TS
814 DOWNLOAD_OK=yes
815 break
816 done
b9b3a92f 817
7bd44bf6
TS
818 if [ $DOWNLOAD_OK != yes ]; then
819 echo "Aborting"
820 return 1
821 fi
579ebf12 822
449989ac 823 mkdir -p ${INSTALL_ROOT}/var/lib/rpm
579ebf12 824
449989ac
MW
825 if ! fedora_get_bootstrap
826 then
827 echo "Fedora Bootstrap setup failed"
828 return 1
829 fi
830
831 fedora_bootstrap_mounts
832
833 ${BOOTSTRAP_CHROOT}rpm --root ${BOOTSTRAP_INSTALL_ROOT} --initdb
834 # The --nodeps is STUPID but F15 had a bogus dependency on RawHide?!?!
835 ${BOOTSTRAP_CHROOT}rpm --root ${BOOTSTRAP_INSTALL_ROOT} --nodeps -ivh ${BOOTSTRAP_INSTALL_ROOT}/${RELEASE_RPM}
836 ${BOOTSTRAP_CHROOT}yum --installroot ${BOOTSTRAP_INSTALL_ROOT} -y --nogpgcheck install ${PKG_LIST}
837
838 RC=$?
839
840 if [[ ${BOOTSTRAP} -eq 1 ]]
841 then
842 # Here we have a bit of a sticky problem. We MIGHT have just installed
843 # this template cache using versions of yum and rpm in the bootstrap
844 # chroot that use a different database version than the target version.
845 # That can be a very big problem. Solution is to rebuild the rpmdatabase
846 # with the target database now that we are done building the cache. In the
847 # vast majority of cases, this is a do-not-care with no harm done if we
848 # didn't do it. But it catches several corner cases with older unsupported
849 # releases and it really doesn't cost us a lot of time for a one shot
850 # install that will never be done again for this rev.
851 #
852 # Thanks and appreciation to Dwight Engen and the Oracle template for the
853 # database rewrite hint!
854
855 echo "Fixing up rpm databases"
856
857 # Change to our target install directory (if we're not already
858 # there) just to simplify some of the logic to follow...
859 cd ${INSTALL_ROOT}
860
861 rm -f var/lib/rpm/__db*
862 # Programmers Note (warning):
863 #
864 # Pay careful attention to the following commands! It
865 # crosses TWO chroot boundaries linked by a bind mount!
866 # In the bootstrap case, that's the bind mount of ${INSTALL_ROOT}
867 # to the ${BOOTSTRAP_CHROOT}/run/install directory! This is
868 # a deliberate hack across that bind mount to do a database
869 # translation between two environments, neither of which may
870 # be the host environment! It's ugly and hard to follow but,
871 # if you don't understand it, don't mess with it! The pipe
872 # is in host space between the two chrooted environments!
873 # This is also why we cd'ed into the INSTALL_ROOT directory
874 # in advance of this loop, so everything is relative to the
875 # current working directory and congruent with the same working
876 # space in both chrooted environments. The output into the new
877 # db is also done in INSTALL_ROOT space but works in either host
878 # space or INSTALL_ROOT space for the mv, so we don't care. It's
879 # just not obvious what's happening in the db_dump and db_load
880 # commands...
881 #
882 for db in var/lib/rpm/* ; do
883 ${BOOTSTRAP_CHROOT} db_dump ${BOOTSTRAP_INSTALL_ROOT}/$db | chroot . db_load $db.new
884 mv $db.new $db
885 done
886 # finish up by rebuilding the database...
887 # This should be redundant but we do it for completeness and
888 # any corner cases I may have missed...
889 mount -t proc proc proc
890 mount -o bind /dev dev
891 chroot . rpm --rebuilddb
892 umount dev
893 umount proc
894 fi
895
896 fedora_bootstrap_umounts
897
898 if [ ${RC} -ne 0 ]; then
14d9c0f0
SG
899 echo "Failed to download the rootfs, aborting."
900 return 1
54b1eb68
MH
901 fi
902
579ebf12 903 mv "$INSTALL_ROOT" "$cache/rootfs"
b6e91b67 904 echo "Download complete."
54b1eb68 905
b6e91b67
DL
906 return 0
907}
54b1eb68 908
b6e91b67
DL
909copy_fedora()
910{
54b1eb68 911
b6e91b67 912 # make a local copy of the minifedora
579ebf12
I
913 echo -n "Copying rootfs to $rootfs_path ..."
914 #cp -a $cache/rootfs-$arch $rootfs_path || return 1
915 # i prefer rsync (no reason really)
916 mkdir -p $rootfs_path
44d39789 917 rsync -Ha $cache/rootfs/ $rootfs_path/
b4f7af7a 918 echo
b6e91b67 919 return 0
54b1eb68
MH
920}
921
579ebf12
I
922update_fedora()
923{
449989ac
MW
924 mount -o bind /dev ${cache}/rootfs/dev
925 mount -t proc proc ${cache}/rootfs/proc
926 # Always make sure /etc/resolv.conf is up to date in the target!
927 cp /etc/resolv.conf ${cache}/rootfs/etc/
928 chroot ${cache}/rootfs yum -y update
929 umount ${cache}/rootfs/proc
930 umount ${cache}/rootfs/dev
579ebf12
I
931}
932
b6e91b67
DL
933install_fedora()
934{
e29bf450 935 mkdir -p @LOCALSTATEDIR@/lock/subsys/
b6e91b67 936 (
14d9c0f0
SG
937 flock -x 200
938 if [ $? -ne 0 ]; then
939 echo "Cache repository is busy."
940 return 1
941 fi
942
943 echo "Checking cache download in $cache/rootfs ... "
944 if [ ! -e "$cache/rootfs" ]; then
945 download_fedora
946 if [ $? -ne 0 ]; then
947 echo "Failed to download 'fedora base'"
948 return 1
949 fi
579ebf12 950 else
14d9c0f0 951 echo "Cache found. Updating..."
579ebf12 952 update_fedora
14d9c0f0
SG
953 if [ $? -ne 0 ]; then
954 echo "Failed to update 'fedora base', continuing with last known good cache"
579ebf12
I
955 else
956 echo "Update finished"
14d9c0f0
SG
957 fi
958 fi
54b1eb68 959
14d9c0f0
SG
960 echo "Copy $cache/rootfs to $rootfs_path ... "
961 copy_fedora
962 if [ $? -ne 0 ]; then
963 echo "Failed to copy rootfs"
964 return 1
965 fi
54b1eb68 966
14d9c0f0 967 return 0
fe253caa 968 ) 200>@LOCALSTATEDIR@/lock/subsys/lxc-fedora
54b1eb68 969
b6e91b67 970 return $?
54b1eb68
MH
971}
972
b4f7af7a
MW
973# Generate a random hardware (MAC) address composed of FE followed by
974# 5 random bytes...
975create_hwaddr()
b6e91b67 976{
b4f7af7a
MW
977 echo $(dd if=/dev/urandom bs=8 count=1 2>/dev/null | md5sum |
978 sed -e 's/\(..\)\(..\)\(..\)\(..\)\(..\).*/fe:\1:\2:\3:\4:\5/')
979}
54b1eb68 980
b4f7af7a
MW
981copy_configuration()
982{
579ebf12 983 mkdir -p $config_path
b4f7af7a
MW
984
985 grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo "
986lxc.rootfs = $rootfs_path
987" >> $config_path/config
988
989 # The following code is to create static MAC addresses for each
990 # interface in the container. This code will work for multiple
991 # interfaces in the default config. It will also strip any
992 # hwaddr stanzas out of the default config since we can not share
993 # MAC addresses between containers.
994 mv $config_path/config $config_path/config.def
995 while read LINE
996 do
997 # This should catch variable expansions from the default config...
998 if expr "${LINE}" : '.*\$' > /dev/null 2>&1
999 then
1000 LINE=$(eval "echo \"${LINE}\"")
1001 fi
1002
1003 # There is a tab and a space in the regex bracket below!
1004 # Seems that \s doesn't work in brackets.
1005 KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=')
1006
1007 if [[ "${KEY}" != "lxc.network.hwaddr" ]]
1008 then
1009 echo "${LINE}" >> $config_path/config
1010
1011 if [[ "${KEY}" == "lxc.network.link" ]]
1012 then
1013 echo "lxc.network.hwaddr = $(create_hwaddr)" >> $config_path/config
1014 fi
1015 fi
1016 done < $config_path/config.def
1017
1018 rm -f $config_path/config.def
1019
579ebf12 1020 cat <<EOF >> $config_path/config
b9b3a92f 1021lxc.utsname = $utsname
b6e91b67
DL
1022lxc.tty = 4
1023lxc.pts = 1024
eba7df9e 1024lxc.mount = $config_path/fstab
eee3ba81 1025lxc.cap.drop = sys_module mac_admin mac_override sys_time
f02ce27d 1026
627fe3b4
MW
1027lxc.autodev = $auto_dev
1028
f02ce27d
SG
1029# When using LXC with apparmor, uncomment the next line to run unconfined:
1030#lxc.aa_profile = unconfined
1031
b4f7af7a
MW
1032# example simple networking setup, uncomment to enable
1033#lxc.network.type = $lxc_network_type
1034#lxc.network.flags = up
1035#lxc.network.link = $lxc_network_link
1036#lxc.network.name = eth0
1037# Additional example for veth network type
1038# static MAC address,
1039#lxc.network.hwaddr = 00:16:3e:77:52:20
1040# persistent veth device name on host side
1041# Note: This may potentially collide with other containers of same name!
1042#lxc.network.veth.pair = v-$name-e0
1043
579ebf12 1044#cgroups
b6e91b67
DL
1045lxc.cgroup.devices.deny = a
1046# /dev/null and zero
1047lxc.cgroup.devices.allow = c 1:3 rwm
1048lxc.cgroup.devices.allow = c 1:5 rwm
1049# consoles
1050lxc.cgroup.devices.allow = c 5:1 rwm
1051lxc.cgroup.devices.allow = c 5:0 rwm
b6e91b67
DL
1052# /dev/{,u}random
1053lxc.cgroup.devices.allow = c 1:9 rwm
1054lxc.cgroup.devices.allow = c 1:8 rwm
1055lxc.cgroup.devices.allow = c 136:* rwm
1056lxc.cgroup.devices.allow = c 5:2 rwm
1057# rtc
eee3ba81 1058lxc.cgroup.devices.allow = c 254:0 rm
b6e91b67 1059EOF
54b1eb68 1060
579ebf12 1061 cat <<EOF > $config_path/fstab
80a881b2 1062proc proc proc nodev,noexec,nosuid 0 0
80a881b2 1063sysfs sys sysfs defaults 0 0
a30ce0ac 1064EOF
b4f7af7a 1065
b6e91b67 1066 if [ $? -ne 0 ]; then
14d9c0f0
SG
1067 echo "Failed to add configuration"
1068 return 1
b6e91b67 1069 fi
54b1eb68 1070
b6e91b67 1071 return 0
54b1eb68
MH
1072}
1073
b6e91b67
DL
1074clean()
1075{
54b1eb68 1076
b6e91b67 1077 if [ ! -e $cache ]; then
14d9c0f0 1078 exit 0
54b1eb68
MH
1079 fi
1080
1081 # lock, so we won't purge while someone is creating a repository
1082 (
14d9c0f0
SG
1083 flock -x 200
1084 if [ $? != 0 ]; then
1085 echo "Cache repository is busy."
1086 exit 1
1087 fi
54b1eb68 1088
14d9c0f0
SG
1089 echo -n "Purging the download cache for Fedora-$release..."
1090 rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
1091 exit 0
fe253caa 1092 ) 200>@LOCALSTATEDIR@/lock/subsys/lxc-fedora
b6e91b67
DL
1093}
1094
1095usage()
1096{
1097 cat <<EOF
579ebf12
I
1098usage:
1099 $1 -n|--name=<container_name>
b9b3a92f 1100 [-p|--path=<path>] [-c|--clean] [-R|--release=<Fedora_release>] [--fqdn=<network name of container>] [-A|--arch=<arch of the container>]
579ebf12
I
1101 [-h|--help]
1102Mandatory args:
1103 -n,--name container name, used to as an identifier for that container from now on
1104Optional args:
1897e3bc
SH
1105 -p,--path path to where the container will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case
1106 --rootfs path for actual rootfs.
579ebf12 1107 -c,--clean clean the cache
627fe3b4 1108 -R,--release Fedora release for the new container. if the host is Fedora, then it will default to the host's release.
b9b3a92f 1109 --fqdn fully qualified domain name (FQDN) for DNS and system naming
579ebf12
I
1110 -A,--arch NOT USED YET. Define what arch the container will be [i686,x86_64]
1111 -h,--help print this help
b6e91b67
DL
1112EOF
1113 return 0
54b1eb68
MH
1114}
1115
b9b3a92f 1116options=$(getopt -o hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,fqdn: -- "$@")
b6e91b67
DL
1117if [ $? -ne 0 ]; then
1118 usage $(basename $0)
1119 exit 1
1120fi
1121eval set -- "$options"
1122
1123while true
1124do
1125 case "$1" in
14d9c0f0
SG
1126 -h|--help) usage $0 && exit 0;;
1127 -p|--path) path=$2; shift 2;;
1897e3bc 1128 --rootfs) rootfs=$2; shift 2;;
14d9c0f0
SG
1129 -n|--name) name=$2; shift 2;;
1130 -c|--clean) clean=$2; shift 2;;
579ebf12 1131 -R|--release) release=$2; shift 2;;
b9b3a92f 1132 --fqdn) utsname=$2; shift 2;;
14d9c0f0 1133 --) shift 1; break ;;
b6e91b67
DL
1134 *) break ;;
1135 esac
1136done
1137
1138if [ ! -z "$clean" -a -z "$path" ]; then
1139 clean || exit 1
1140 exit 0
1141fi
1142
b4f7af7a
MW
1143# Let's do something better for the initial root password.
1144# It's not perfect but it will defeat common scanning brute force
1145# attacks in the case where ssh is exposed. It will also be set to
1146# expired, forcing the user to change it at first login.
1147if [ "${root_password}" = "" ]
1148then
1149 root_password=Root-${name}-${RANDOM}
1150else
1151 # If it's got a ding in it, try and expand it!
1152 if [ $(expr "${root_password}" : '.*$.') != 0 ]
1153 then
1154 root_password=$(eval echo "${root_password}")
1155 fi
1156
1157 # If it has more than 3 consequtive X's in it, feed it
1158 # through mktemp as a template.
1159 if [ $(expr "${root_password}" : '.*XXXX') != 0 ]
1160 then
1161 root_password=$(mktemp -u ${root_password})
1162 fi
1163fi
1164
b9b3a92f
MW
1165if [ -z "${utsname}" ]; then
1166 utsname=${name}
1167fi
1168
1169# This follows a standard "resolver" convention that an FQDN must have
1170# at least two dots or it is considered a local relative host name.
1171# If it doesn't, append the dns domain name of the host system.
1172#
1173# This changes one significant behavior when running
1174# "lxc_create -n Container_Name" without using the
1175# --fqdn option.
1176#
1177# Old behavior:
1178# utsname and hostname = Container_Name
1179# New behavior:
1180# utsname and hostname = Container_Name.Domain_Name
1181
1182if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then
b4f7af7a 1183 if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then
b9b3a92f
MW
1184 utsname=${utsname}.$(dnsdomainname)
1185 fi
1186fi
1187
cb26f1a5 1188needed_pkgs=""
cb26f1a5
SG
1189
1190type curl >/dev/null 2>&1
1191if [ $? -ne 0 ]; then
1192 needed_pkgs="curl $needed_pkgs"
1193fi
1194
1195if [ -n "$needed_pkgs" ]; then
1196 echo "Missing commands: $needed_pkgs"
627fe3b4 1197 echo "Please install these using \"sudo yum install $needed_pkgs\""
b6e91b67
DL
1198 exit 1
1199fi
1200
1201if [ -z "$path" ]; then
5bb4a226 1202 path=$default_path/$name
579ebf12
I
1203fi
1204
1205if [ -z "$release" ]; then
627fe3b4
MW
1206 if [ "$is_fedora" -a "$fedora_host_ver" ]; then
1207 release=$fedora_host_ver
579ebf12 1208 else
53bd92ea
MW
1209 echo "This is not a fedora host and release missing, defaulting to 19. use -R|--release to specify release"
1210 release=19
579ebf12 1211 fi
b6e91b67
DL
1212fi
1213
627fe3b4
MW
1214# Fedora 15 and above run systemd. We need autodev enabled to keep
1215# systemd from causing problems.
1216if [ $release -gt 14 ]; then
1217 auto_dev="1"
1218else
1219 auto_dev="0"
1220fi
1221
54b1eb68 1222if [ "$(id -u)" != "0" ]; then
b6e91b67
DL
1223 echo "This script should be run as 'root'"
1224 exit 1
1225fi
1226
29ec8f84 1227
1897e3bc
SH
1228if [ -z "$rootfs_path" ]; then
1229 rootfs_path=$path/rootfs
1230 # check for 'lxc.rootfs' passed in through default config by lxc-create
1231 if grep -q '^lxc.rootfs' $path/config 2>/dev/null ; then
853d58fd 1232 rootfs_path=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $path/config)
1897e3bc 1233 fi
cb26f1a5 1234fi
579ebf12
I
1235config_path=$default_path/$name
1236cache=$cache_base/$release
1237
29ec8f84
RH
1238revert()
1239{
1240 echo "Interrupted, so cleaning up"
1241 lxc-destroy -n $name
1242 # maybe was interrupted before copy config
f9d0d2cb 1243 rm -rf $path
29ec8f84
RH
1244 rm -rf $default_path/$name
1245 echo "exiting..."
1246 exit 1
1247}
1248
1249trap revert SIGHUP SIGINT SIGTERM
1250
1251copy_configuration
1252if [ $? -ne 0 ]; then
1253 echo "failed write configuration file"
1254 exit 1
1255fi
1256
579ebf12 1257install_fedora
b6e91b67
DL
1258if [ $? -ne 0 ]; then
1259 echo "failed to install fedora"
1260 exit 1
54b1eb68
MH
1261fi
1262
579ebf12 1263configure_fedora
b6e91b67
DL
1264if [ $? -ne 0 ]; then
1265 echo "failed to configure fedora for a container"
1266 exit 1
1267fi
1268
bf7d3153
MW
1269# If the systemd configuration directory exists - set it up for what we need.
1270if [ -d ${rootfs_path}/etc/systemd/system ]
1271then
f9d0d2cb
I
1272 configure_fedora_systemd
1273fi
b6e91b67 1274
bf7d3153
MW
1275# This configuration (rc.sysinit) is not inconsistent with the systemd stuff
1276# above and may actually coexist on some upgraded systems. Let's just make
1277# sure that, if it exists, we update this file, even if it's not used...
1278if [ -f ${rootfs_path}/etc/rc.sysinit ]
1279then
1280 configure_fedora_init
1281fi
1282
b6e91b67
DL
1283if [ ! -z $clean ]; then
1284 clean || exit 1
1285 exit 0
1286fi
b4f7af7a
MW
1287echo "
1288Container rootfs and config have been created.
1289Edit the config file to check/enable networking setup.
1290"
449989ac
MW
1291
1292if [[ -d ${cache_base}/bootstrap ]]
1293then
b4f7af7a 1294 echo "You have successfully built a Fedora container and cache. This cache may
449989ac
MW
1295be used to create future containers of various revisions. The directory
1296${cache_base}/bootstrap contains a bootstrap
1297which may no longer needed and can be removed.
1298"
1299fi
1300
1301if [[ -e ${cache_base}/LiveOS ]]
1302then
1303 echo "A LiveOS directory exists at ${cache_base}/LiveOS.
1304This is only used in the creation of the bootstrap run-time-environment
1305and may be removed.
1306"
1307fi
b4f7af7a
MW
1308
1309if [ ${root_display_password} = "yes" ]
1310then
1311 echo "The temporary password for root is: '$root_password'
1312
1313You may want to note that password down before starting the container.
1314"
1315fi
1316
1317if [ ${root_store_password} = "yes" ]
1318then
1319 echo "The temporary root password is stored in:
1320
1321 '${config_path}/tmp_root_pass'
1322"
1323fi
1324
1325if [ ${root_prompt_password} = "yes" ]
1326then
1327 echo "Invoking the passwd command in the container to set the root password.
1328
1329 chroot ${rootfs_path} passwd
1330"
1331 chroot ${rootfs_path} passwd
1332else
1333 echo "
1334The root password is set up as "expired" and will require it to be changed
1335at first login, which you should do as soon as possible. If you lose the
1336root password or wish to change it without starting the container, you
1337can change it from the host by running the following command (which will
1338also reset the expired flag):
1339
1340 chroot ${rootfs_path} passwd
1341"
1342fi