]> git.proxmox.com Git - mirror_lxc.git/blame - templates/lxc-centos.in
Fix typo in previous patch
[mirror_lxc.git] / templates / lxc-centos.in
CommitLineData
164105f6
MW
1#!/bin/bash
2
3#
4# template script for generating centos container for LXC
5
6#
7# lxc: linux Container library
8
9# Authors:
10# Daniel Lezcano <daniel.lezcano@free.fr>
11# Ramez Hanna <rhanna@informatiq.org>
12# Fajar A. Nugraha <github@fajar.net>
13# Michael H. Warfield <mhw@WittsEnd.com>
14
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.
19
20# This library is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
96283b54 22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
164105f6
MW
23# Lesser General Public License for more details.
24
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
27# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
29#Configurations
164105f6 30default_path=@LXCPATH@
164105f6 31
826cde7c 32# Some combinations of the tuning knobs below do not exactly make sense.
b4f7af7a
MW
33# but that's ok.
34#
35# If the "root_password" is non-blank, use it, else set a default.
36# This can be passed to the script as an environment variable and is
37# set by a shell conditional assignment. Looks weird but it is what it is.
38#
39# If the root password contains a ding ($) then try to expand it.
40# That will pick up things like ${name} and ${RANDOM}.
41# If the root password contians more than 3 consecutive X's, pass it as
42# a template to mktemp and take the result.
43#
44# If root_display_password = yes, display the temporary root password at exit.
45# If root_store_password = yes, store it in the configuration directory
46# If root_prompt_password = yes, invoke "passwd" to force the user to change
47# the root password after the container is created.
826cde7c
MW
48# If root_expire_password = yes, you will be prompted to change the root
49# password at the first login.
b4f7af7a
MW
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
826cde7c
MW
66# Expire root password? Default to yes, but can be overridden from
67# the environment variable
68: ${root_expire_password='yes'}
69
b4f7af7a 70# These are only going into comments in the resulting config...
164105f6
MW
71lxc_network_type=veth
72lxc_network_link=lxcbr0
73
74# is this centos?
75# Alow for weird remixes like the Raspberry Pi
76#
77# Use the Mitre standard CPE identifier for the release ID if possible...
78# This may be in /etc/os-release or /etc/system-release-cpe. We
79# should be able to use EITHER. Give preference to /etc/os-release for now.
80
8ec981fc 81# Detect use under userns (unsupported)
c63c04fc 82for arg in "$@"; do
96283b54
SG
83 [ "$arg" = "--" ] && break
84 if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
8ec981fc
SG
85 echo "This template can't be used for unprivileged containers." 1>&2
86 echo "You may want to try the \"download\" template instead." 1>&2
87 exit 1
88 fi
89done
90
207bf0e4
SG
91# Make sure the usual locations are in PATH
92export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
93
164105f6
MW
94if [ -e /etc/os-release ]
95then
96# This is a shell friendly configuration file. We can just source it.
97# What we're looking for in here is the ID, VERSION_ID and the CPE_NAME
98 . /etc/os-release
99 echo "Host CPE ID from /etc/os-release: ${CPE_NAME}"
100fi
101
102if [ "${CPE_NAME}" = "" -a -e /etc/system-release-cpe ]
103then
104 CPE_NAME=$(head -n1 /etc/system-release-cpe)
c6df5ca4 105 CPE_URI=$(expr ${CPE_NAME} : '\([^:]*:[^:]*\)')
164105f6
MW
106 if [ "${CPE_URI}" != "cpe:/o" ]
107 then
108 CPE_NAME=
109 else
164105f6
MW
110 # Probably a better way to do this but sill remain posix
111 # compatible but this works, shrug...
112 # Must be nice and not introduce convenient bashisms here.
c6df5ca4
MW
113 #
114 # According to the official registration at Mitre and NIST,
115 # this should have been something like this for CentOS:
116 # cpe:/o:centos:centos:6
117 # or this:
118 # cpe:/o:centos:centos:6.5
119 #
164105f6 120 ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:\([^:]*\)')
c6df5ca4
MW
121 # The "enterprise_linux" is a bone toss back to RHEL.
122 # Since CentOS and RHEL are so tightly coupled, we'll
123 # take the RHEL version if we're running on it and do the
124 # equivalent version for CentOS.
125 if [ ${ID} = "linux" -o ${ID} = "enterprise_linux" ]
126 then
127 # Instead we got this: cpe:/o:centos:linux:6
128 ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:\([^:]*\)')
129 fi
130
164105f6 131 VERSION_ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\)')
c6df5ca4 132 echo "Host CPE ID from /etc/system-release-cpe: ${CPE_NAME}"
164105f6
MW
133 fi
134fi
135
136if [ "${CPE_NAME}" != "" -a "${ID}" = "centos" -a "${VERSION_ID}" != "" ]
137then
138 centos_host_ver=${VERSION_ID}
139 is_centos=true
c6df5ca4
MW
140elif [ "${CPE_NAME}" != "" -a "${ID}" = "redhat" -a "${VERSION_ID}" != "" ]
141then
142 redhat_host_ver=${VERSION_ID}
143 is_redhat=true
144elif [ -e /etc/centos-release ]
164105f6
MW
145then
146 # Only if all other methods fail, try to parse the redhat-release file.
c6df5ca4 147 centos_host_ver=$( sed -e '/^CentOS /!d' -e 's/CentOS.*\srelease\s*\([0-9][0-9.]*\)\s.*/\1/' < /etc/centos-release )
164105f6
MW
148 if [ "$centos_host_ver" != "" ]
149 then
150 is_centos=true
151 fi
152fi
153
164105f6
MW
154force_mknod()
155{
156 # delete a device node if exists, and create a new one
157 rm -f $2 && mknod -m $1 $2 $3 $4 $5
158}
159
160configure_centos()
161{
162
163 # disable selinux in centos
164 mkdir -p $rootfs_path/selinux
165 echo 0 > $rootfs_path/selinux/enforce
166
167 # Also kill it in the /etc/selinux/config file if it's there...
17abf278 168 if [ -f $rootfs_path/etc/selinux/config ]
164105f6
MW
169 then
170 sed -i '/^SELINUX=/s/.*/SELINUX=disabled/' $rootfs_path/etc/selinux/config
171 fi
172
173 # Nice catch from Dwight Engen in the Oracle template.
174 # Wantonly plagerized here with much appreciation.
175 if [ -f $rootfs_path/usr/sbin/selinuxenabled ]; then
176 mv $rootfs_path/usr/sbin/selinuxenabled $rootfs_path/usr/sbin/selinuxenabled.lxcorig
177 ln -s /bin/false $rootfs_path/usr/sbin/selinuxenabled
178 fi
179
180 # This is a known problem and documented in RedHat bugzilla as relating
181 # to a problem with auditing enabled. This prevents an error in
182 # the container "Cannot make/remove an entry for the specified session"
183 sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/login
184 sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/sshd
185
c6df5ca4
MW
186 if [ -f ${rootfs_path}/etc/pam.d/crond ]
187 then
188 sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/crond
189 fi
190
191 # In addition to disabling pam_loginuid in the above config files
192 # we'll also disable it by linking it to pam_permit to catch any
193 # we missed or any that get installed after the container is built.
194 #
195 # Catch either or both 32 and 64 bit archs.
196 if [ -f ${rootfs_path}/lib/security/pam_loginuid.so ]
197 then
198 ( cd ${rootfs_path}/lib/security/
199 mv pam_loginuid.so pam_loginuid.so.disabled
200 ln -s pam_permit.so pam_loginuid.so
201 )
202 fi
203
204 if [ -f ${rootfs_path}/lib64/security/pam_loginuid.so ]
205 then
206 ( cd ${rootfs_path}/lib64/security/
207 mv pam_loginuid.so pam_loginuid.so.disabled
208 ln -s pam_permit.so pam_loginuid.so
209 )
210 fi
211
f5067ecb
MW
212 # Set default localtime to the host localtime if not set...
213 if [ -e /etc/localtime -a ! -e ${rootfs_path}/etc/localtime ]
214 then
215 # if /etc/localtime is a symlink, this should preserve it.
216 cp -a /etc/localtime ${rootfs_path}/etc/localtime
217 fi
218
99c2fb07
MW
219 # Deal with some dain bramage in the /etc/init.d/halt script.
220 # Trim it and make it our own and link it in before the default
221 # halt script so we can intercept it. This also preventions package
222 # updates from interferring with our interferring with it.
223 #
224 # There's generally not much in the halt script that useful but what's
225 # in there from resetting the hardware clock down is generally very bad.
226 # So we just eliminate the whole bottom half of that script in making
227 # ourselves a copy. That way a major update to the init scripts won't
228 # trash what we've set up.
229 if [ -f ${rootfs_path}/etc/init.d/halt ]
230 then
231 sed -e '/hwclock/,$d' \
232 < ${rootfs_path}/etc/init.d/halt \
233 > ${rootfs_path}/etc/init.d/lxc-halt
234
235 echo '$command -f' >> ${rootfs_path}/etc/init.d/lxc-halt
236 chmod 755 ${rootfs_path}/etc/init.d/lxc-halt
237
238 # Link them into the rc directories...
239 (
240 cd ${rootfs_path}/etc/rc.d/rc0.d
241 ln -s ../init.d/lxc-halt S00lxc-halt
242 cd ${rootfs_path}/etc/rc.d/rc6.d
243 ln -s ../init.d/lxc-halt S00lxc-reboot
244 )
245 fi
246
247 # configure the network using the dhcp
164105f6
MW
248 cat <<EOF > ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0
249DEVICE=eth0
250BOOTPROTO=dhcp
251ONBOOT=yes
252HOSTNAME=${UTSNAME}
253NM_CONTROLLED=no
254TYPE=Ethernet
255MTU=${MTU}
256EOF
257
258 # set the hostname
259 cat <<EOF > ${rootfs_path}/etc/sysconfig/network
260NETWORKING=yes
261HOSTNAME=${UTSNAME}
262EOF
263
264 # set minimal hosts
265 cat <<EOF > $rootfs_path/etc/hosts
266127.0.0.1 localhost $name
267EOF
268
269 # set minimal fstab
270 cat <<EOF > $rootfs_path/etc/fstab
271/dev/root / rootfs defaults 0 0
272none /dev/shm tmpfs nosuid,nodev 0 0
273EOF
274
275 # create lxc compatibility init script
276 if [ "$release" = "6" ]; then
277 cat <<EOF > $rootfs_path/etc/init/lxc-sysinit.conf
278start on startup
279env container
280
281pre-start script
282 if [ "x$container" != "xlxc" -a "x$container" != "xlibvirt" ]; then
283 stop;
284 fi
285 initctl start tty TTY=console
286 rm -f /var/lock/subsys/*
287 rm -f /var/run/*.pid
288 telinit 3
289 exit 0;
290end script
291EOF
292 elif [ "$release" = "5" ]; then
293 cat <<EOF > $rootfs_path/etc/rc.d/lxc.sysinit
294#! /bin/bash
295rm -f /etc/mtab /var/run/*.{pid,lock} /var/lock/subsys/*
296rm -rf {/,/var}/tmp/*
297echo "/dev/root / rootfs defaults 0 0" > /etc/mtab
298exit 0
299EOF
300 chmod 755 $rootfs_path/etc/rc.d/lxc.sysinit
301 sed -i 's|si::sysinit:/etc/rc.d/rc.sysinit|si::bootwait:/etc/rc.d/lxc.sysinit|' $rootfs_path/etc/inittab
302 sed -i 's|^1:|co:2345:respawn:/sbin/mingetty console\n1:|' $rootfs_path/etc/inittab
303 sed -i 's|^\([56]:\)|#\1|' $rootfs_path/etc/inittab
304 fi
305
306 dev_path="${rootfs_path}/dev"
307 rm -rf $dev_path
308 mkdir -p $dev_path
309 mknod -m 666 ${dev_path}/null c 1 3
310 mknod -m 666 ${dev_path}/zero c 1 5
311 mknod -m 666 ${dev_path}/random c 1 8
312 mknod -m 666 ${dev_path}/urandom c 1 9
313 mkdir -m 755 ${dev_path}/pts
314 mkdir -m 1777 ${dev_path}/shm
315 mknod -m 666 ${dev_path}/tty c 5 0
316 mknod -m 666 ${dev_path}/tty0 c 4 0
317 mknod -m 666 ${dev_path}/tty1 c 4 1
318 mknod -m 666 ${dev_path}/tty2 c 4 2
319 mknod -m 666 ${dev_path}/tty3 c 4 3
320 mknod -m 666 ${dev_path}/tty4 c 4 4
321 mknod -m 600 ${dev_path}/console c 5 1
322 mknod -m 666 ${dev_path}/full c 1 7
323 mknod -m 600 ${dev_path}/initctl p
324 mknod -m 666 ${dev_path}/ptmx c 5 2
325
1ecee40b
MW
326 # setup console and tty[1-4] for login. note that /dev/console and
327 # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and
328 # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks.
329 # lxc will maintain these links and bind mount ptys over /dev/lxc/*
330 # since lxc.devttydir is specified in the config.
331
332 # allow root login on console, tty[1-4], and pts/0 for libvirt
333 echo "# LXC (Linux Containers)" >>${rootfs_path}/etc/securetty
334 echo "lxc/console" >>${rootfs_path}/etc/securetty
335 echo "lxc/tty1" >>${rootfs_path}/etc/securetty
336 echo "lxc/tty2" >>${rootfs_path}/etc/securetty
337 echo "lxc/tty3" >>${rootfs_path}/etc/securetty
338 echo "lxc/tty4" >>${rootfs_path}/etc/securetty
339 echo "# For libvirt/Virtual Machine Monitor" >>${rootfs_path}/etc/securetty
340 echo "pts/0" >>${rootfs_path}/etc/securetty
341
b4f7af7a
MW
342 if [ ${root_display_password} = "yes" ]
343 then
344 echo "Setting root password to '$root_password'"
345 fi
346 if [ ${root_store_password} = "yes" ]
347 then
348 touch ${config_path}/tmp_root_pass
349 chmod 600 ${config_path}/tmp_root_pass
350 echo ${root_password} > ${config_path}/tmp_root_pass
351 echo "Storing root password in '${config_path}/tmp_root_pass'"
352 fi
353
164105f6 354 echo "root:$root_password" | chroot $rootfs_path chpasswd
826cde7c
MW
355
356 if [ ${root_expire_password} = "yes" ]
357 then
358 # Also set this password as expired to force the user to change it!
359 chroot $rootfs_path passwd -e root
360 fi
164105f6
MW
361
362 # This will need to be enhanced for CentOS 7 when systemd
363 # comes into play... /\/\|=mhw=|\/\/
364
365 return 0
366}
367
368configure_centos_init()
369{
370 sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.sysinit
371 sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.d/rc.sysinit
372 if [ "$release" = "6" ]; then
373 chroot ${rootfs_path} chkconfig udev-post off
374 fi
375 chroot ${rootfs_path} chkconfig network on
779b47fd
MW
376
377 if [ -d ${rootfs_path}/etc/init ]
378 then
379 # This is to make upstart honor SIGPWR
380 cat <<EOF >${rootfs_path}/etc/init/power-status-changed.conf
381# power-status-changed - shutdown on SIGPWR
382#
383start on power-status-changed
384
385exec /sbin/shutdown -h now "SIGPWR received"
386EOF
387 fi
164105f6
MW
388}
389
390download_centos()
391{
392
393 # check the mini centos was not already downloaded
394 INSTALL_ROOT=$cache/partial
395 mkdir -p $INSTALL_ROOT
396 if [ $? -ne 0 ]; then
397 echo "Failed to create '$INSTALL_ROOT' directory"
398 return 1
399 fi
400
401 # download a mini centos into a cache
402 echo "Downloading centos minimal ..."
403 YUM="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
404 PKG_LIST="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils"
405
406 # use temporary repository definition
407 REPO_FILE=$INSTALL_ROOT/etc/yum.repos.d/lxc-centos-temp.repo
408 mkdir -p $(dirname $REPO_FILE)
3a6ef65a
HD
409 if [ -n "$repo" ]; then
410 cat <<EOF > $REPO_FILE
411[base]
412name=local repository
413baseurl="$repo"
414EOF
415else
416 cat <<EOF > $REPO_FILE
164105f6
MW
417[base]
418name=CentOS-$release - Base
08754f30 419mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=os
164105f6
MW
420
421[updates]
422name=CentOS-$release - Updates
08754f30 423mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=updates
164105f6 424EOF
3a6ef65a 425 fi
164105f6
MW
426
427 # create minimal device nodes, needed for "yum install" and "yum update" process
428 mkdir -p $INSTALL_ROOT/dev
429 force_mknod 666 $INSTALL_ROOT/dev/null c 1 3
430 force_mknod 666 $INSTALL_ROOT/dev/urandom c 1 9
431
432 $YUM install $PKG_LIST
433
434 if [ $? -ne 0 ]; then
435 echo "Failed to download the rootfs, aborting."
436 return 1
437 fi
438
439 # use same nameservers as hosts, needed for "yum update later"
440 cp /etc/resolv.conf $INSTALL_ROOT/etc/
441
442 # check whether rpmdb is under $HOME
443 if [ ! -e $INSTALL_ROOT/var/lib/rpm/Packages -a -e $INSTALL_ROOT/$HOME/.rpmdb/Packages ]; then
444 echo "Fixing rpmdb location ..."
445 mv $INSTALL_ROOT/$HOME/.rpmdb/[A-Z]* $INSTALL_ROOT/var/lib/rpm/
446 rm -rf $INSTALL_ROOT/$HOME/.rpmdb
447 chroot $INSTALL_ROOT rpm --rebuilddb 2>/dev/null
448 fi
449
450 # check whether rpmdb version is correct
451 chroot $INSTALL_ROOT rpm --quiet -q yum 2>/dev/null
452 ret=$?
453
454 # if "rpm -q" doesn't work due to rpmdb version difference,
455 # then we need to redo the process using the newly-installed yum
456 if [ $ret -gt 0 ]; then
457 echo "Reinstalling packages ..."
458 mv $REPO_FILE $REPO_FILE.tmp
459 mkdir $INSTALL_ROOT/etc/yum.repos.disabled
460 mv $INSTALL_ROOT/etc/yum.repos.d/*.repo $INSTALL_ROOT/etc/yum.repos.disabled/
461 mv $REPO_FILE.tmp $REPO_FILE
462 mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/etc
463 cp /etc/resolv.conf $INSTALL_ROOT/$INSTALL_ROOT/etc/
464 mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/dev
465 mknod -m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev/null c 1 3
466 mknod -m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev/urandom c 1 9
467 mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/var/cache/yum
468 cp -al $INSTALL_ROOT/var/cache/yum/* $INSTALL_ROOT/$INSTALL_ROOT/var/cache/yum/
469 chroot $INSTALL_ROOT $YUM install $PKG_LIST
470 if [ $? -ne 0 ]; then
471 echo "Failed to download the rootfs, aborting."
472 return 1
473 fi
474 mv $INSTALL_ROOT/$INSTALL_ROOT $INSTALL_ROOT.tmp
475 rm -rf $INSTALL_ROOT
476 mv $INSTALL_ROOT.tmp $INSTALL_ROOT
477 fi
478
479 rm -f $REPO_FILE
480 rm -rf $INSTALL_ROOT/var/cache/yum/*
481
482 mv "$INSTALL_ROOT" "$cache/rootfs"
483 echo "Download complete."
484
485 return 0
486}
487
488copy_centos()
489{
490
491 # make a local copy of the mini centos
492 echo -n "Copying rootfs to $rootfs_path ..."
493 #cp -a $cache/rootfs-$arch $rootfs_path || return 1
494 # i prefer rsync (no reason really)
495 mkdir -p $rootfs_path
496 rsync -a $cache/rootfs/ $rootfs_path/
b4f7af7a 497 echo
164105f6
MW
498 return 0
499}
500
501update_centos()
502{
503 YUM="chroot $cache/rootfs yum -y --nogpgcheck"
504 $YUM update
505 if [ $? -ne 0 ]; then
506 return 1
507 fi
508 $YUM clean packages
509}
510
511install_centos()
512{
513 mkdir -p /var/lock/subsys/
514 (
17abf278 515 flock -x 9
164105f6
MW
516 if [ $? -ne 0 ]; then
517 echo "Cache repository is busy."
518 return 1
519 fi
520
521 echo "Checking cache download in $cache/rootfs ... "
522 if [ ! -e "$cache/rootfs" ]; then
523 download_centos
524 if [ $? -ne 0 ]; then
525 echo "Failed to download 'centos base'"
526 return 1
527 fi
528 else
529 echo "Cache found. Updating..."
530 update_centos
531 if [ $? -ne 0 ]; then
532 echo "Failed to update 'centos base', continuing with last known good cache"
533 else
534 echo "Update finished"
535 fi
536 fi
537
538 echo "Copy $cache/rootfs to $rootfs_path ... "
539 copy_centos
540 if [ $? -ne 0 ]; then
541 echo "Failed to copy rootfs"
542 return 1
543 fi
544
545 return 0
546
17abf278 547 ) 9>/var/lock/subsys/lxc-centos
164105f6
MW
548
549 return $?
550}
551
b4f7af7a 552create_hwaddr()
164105f6 553{
08754f30 554 openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/'
b4f7af7a 555}
164105f6 556
b4f7af7a
MW
557copy_configuration()
558{
164105f6 559 mkdir -p $config_path
b4f7af7a
MW
560
561 grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo "
562lxc.rootfs = $rootfs_path
563" >> $config_path/config
564
565 # The following code is to create static MAC addresses for each
566 # interface in the container. This code will work for multiple
567 # interfaces in the default config.
568 mv $config_path/config $config_path/config.def
569 while read LINE
570 do
571 # This should catch variable expansions from the default config...
572 if expr "${LINE}" : '.*\$' > /dev/null 2>&1
573 then
574 LINE=$(eval "echo \"${LINE}\"")
575 fi
576
577 # There is a tab and a space in the regex bracket below!
578 # Seems that \s doesn't work in brackets.
579 KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=')
580
581 if [[ "${KEY}" != "lxc.network.hwaddr" ]]
582 then
583 echo ${LINE} >> $config_path/config
584
585 if [[ "${KEY}" == "lxc.network.link" ]]
586 then
587 echo "lxc.network.hwaddr = $(create_hwaddr)" >> $config_path/config
588 fi
589 fi
590 done < $config_path/config.def
591
592 rm -f $config_path/config.def
593
1ecee40b
MW
594 if [ -e "@LXCTEMPLATECONFIG@/centos.common.conf" ]; then
595 echo "
596# Include common configuration
597lxc.include = @LXCTEMPLATECONFIG@/centos.common.conf
598" >> $config_path/config
599 fi
600
601 # Append things which require expansion here...
164105f6 602 cat <<EOF >> $config_path/config
e13923c7 603lxc.arch = $arch
164105f6 604lxc.utsname = $utsname
164105f6
MW
605
606lxc.autodev = $auto_dev
607
b4f7af7a
MW
608# When using LXC with apparmor, uncomment the next line to run unconfined:
609#lxc.aa_profile = unconfined
610
164105f6
MW
611# example simple networking setup, uncomment to enable
612#lxc.network.type = $lxc_network_type
613#lxc.network.flags = up
614#lxc.network.link = $lxc_network_link
615#lxc.network.name = eth0
b4f7af7a
MW
616# Additional example for veth network type
617# static MAC address,
164105f6 618#lxc.network.hwaddr = 00:16:3e:77:52:20
b4f7af7a
MW
619# persistent veth device name on host side
620# Note: This may potentially collide with other containers of same name!
164105f6
MW
621#lxc.network.veth.pair = v-$name-e0
622
164105f6
MW
623EOF
624
625 if [ $? -ne 0 ]; then
b4f7af7a
MW
626 echo "Failed to add configuration"
627 return 1
164105f6
MW
628 fi
629
630 return 0
631}
632
633clean()
634{
635
636 if [ ! -e $cache ]; then
b4f7af7a 637 exit 0
164105f6
MW
638 fi
639
640 # lock, so we won't purge while someone is creating a repository
641 (
b4f7af7a
MW
642 flock -x 9
643 if [ $? != 0 ]; then
644 echo "Cache repository is busy."
645 exit 1
646 fi
164105f6 647
b4f7af7a
MW
648 echo -n "Purging the download cache for centos-$release..."
649 rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
650 exit 0
164105f6 651
b4f7af7a 652 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-centos
164105f6
MW
653}
654
655usage()
656{
657 cat <<EOF
658usage:
659 $1 -n|--name=<container_name>
660 [-p|--path=<path>] [-c|--clean] [-R|--release=<CentOS_release>] [-A|--arch=<arch of the container>]
661 [-h|--help]
662Mandatory args:
663 -n,--name container name, used to as an identifier for that container from now on
664Optional args:
08754f30 665 -p,--path path to where the container rootfs will be created, defaults to /var/lib/lxc/name.
164105f6
MW
666 -c,--clean clean the cache
667 -R,--release Centos release for the new container. if the host is Centos, then it will defaultto the host's release.
668 --fqdn fully qualified domain name (FQDN) for DNS and system naming
3a6ef65a 669 --repo repository to use (url)
08754f30 670 -a,--arch Define what arch the container will be [i686,x86_64]
164105f6
MW
671 -h,--help print this help
672EOF
673 return 0
674}
675
3a6ef65a 676options=$(getopt -o a:hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,repo:,arch:,fqdn: -- "$@")
164105f6
MW
677if [ $? -ne 0 ]; then
678 usage $(basename $0)
679 exit 1
680fi
164105f6 681
08754f30
MW
682arch=$(arch)
683eval set -- "$options"
164105f6
MW
684while true
685do
686 case "$1" in
687 -h|--help) usage $0 && exit 0;;
688 -p|--path) path=$2; shift 2;;
689 --rootfs) rootfs=$2; shift 2;;
690 -n|--name) name=$2; shift 2;;
691 -c|--clean) clean=$2; shift 2;;
692 -R|--release) release=$2; shift 2;;
3a6ef65a 693 --repo) repo="$2"; shift 2;;
08754f30 694 -a|--arch) newarch=$2; shift 2;;
164105f6
MW
695 --fqdn) utsname=$2; shift 2;;
696 --) shift 1; break ;;
697 *) break ;;
698 esac
699done
700
701if [ ! -z "$clean" -a -z "$path" ]; then
702 clean || exit 1
703 exit 0
704fi
705
08754f30
MW
706basearch=${arch}
707# Map a few architectures to their generic CentOS repository archs.
708# The two ARM archs are a bit of a guesstimate for the v5 and v6
709# archs. V6 should have hardware floating point (Rasberry Pi).
710# The "arm" arch is safer (no hardware floating point). So
711# there may be cases where we "get it wrong" for some v6 other
712# than RPi.
713case "$arch" in
714i686) basearch=i386 ;;
715armv3l|armv4l|armv5l) basearch=arm ;;
716armv6l|armv7l|armv8l) basearch=armhfp ;;
717*) ;;
718esac
719
720# Somebody wants to specify an arch. This is very limited case.
721# i386/i586/i686 on i386/x86_64
722# - or -
723# x86_64 on x86_64
724if [ "${newarch}" != "" -a "${newarch}" != "${arch}" ]
725then
726 case "${newarch}" in
727 i386|i586|i686)
728 if [ "${basearch}" = "i386" -o "${basearch}" = "x86_64" ]
729 then
730 # Make the arch a generic x86 32 bit...
731 arch=${newarch}
732 basearch=i386
733 else
734 basearch=bad
735 fi
736 ;;
737 *)
738 basearch=bad
739 ;;
740 esac
741
742 if [ "${basearch}" = "bad" ]
743 then
744 echo "You cannot build a ${newarch} CentOS container on a ${arch} host. Sorry!"
745 exit 1
746 fi
747fi
748
749cache_base=@LOCALSTATEDIR@/cache/lxc/centos/$basearch
750
b4f7af7a
MW
751# Let's do something better for the initial root password.
752# It's not perfect but it will defeat common scanning brute force
753# attacks in the case where ssh is exposed. It will also be set to
754# expired, forcing the user to change it at first login.
755if [ "${root_password}" = "" ]
756then
757 root_password=Root-${name}-${RANDOM}
758else
759 # If it's got a ding in it, try and expand it!
760 if [ $(expr "${root_password}" : '.*$.') != 0 ]
761 then
762 root_password=$(eval echo "${root_password}")
763 fi
764
765 # If it has more than 3 consequtive X's in it, feed it
766 # through mktemp as a template.
767 if [ $(expr "${root_password}" : '.*XXXX') != 0 ]
768 then
769 root_password=$(mktemp -u ${root_password})
770 fi
771fi
772
164105f6
MW
773if [ -z "${utsname}" ]; then
774 utsname=${name}
775fi
776
777# This follows a standard "resolver" convention that an FQDN must have
778# at least two dots or it is considered a local relative host name.
779# If it doesn't, append the dns domain name of the host system.
780#
781# This changes one significant behavior when running
782# "lxc_create -n Container_Name" without using the
783# --fqdn option.
784#
785# Old behavior:
786# utsname and hostname = Container_Name
787# New behavior:
788# utsname and hostname = Container_Name.Domain_Name
789
790if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then
b4f7af7a 791 if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then
164105f6
MW
792 utsname=${utsname}.$(dnsdomainname)
793 fi
794fi
795
796type yum >/dev/null 2>&1
797if [ $? -ne 0 ]; then
798 echo "'yum' command is missing"
799 exit 1
800fi
801
802if [ -z "$path" ]; then
803 path=$default_path/$name
804fi
805
806if [ -z "$release" ]; then
807 if [ "$is_centos" -a "$centos_host_ver" ]; then
808 release=$centos_host_ver
c6df5ca4
MW
809 elif [ "$is_redhat" -a "$redhat_host_ver" ]; then
810 # This is needed to clean out bullshit like 6workstation and 6server.
811 release=$(expr $redhat_host_ver : '\([0-9.]*\)')
164105f6 812 else
c6df5ca4 813 echo "This is not a CentOS or Redhat host and release is missing, defaulting to 6 use -R|--release to specify release"
164105f6
MW
814 release=6
815 fi
816fi
817
818# CentOS 7 and above should run systemd. We need autodev enabled to keep
819# systemd from causing problems.
c6df5ca4
MW
820#
821# There is some ambiguity here due to the differnce between versioning
822# of point specific releases such as 6.5 and the rolling release 6. We
823# only want the major number here if it's a point release...
824
825mrelease=$(expr $release : '\([0-9]*\)')
826if [ $mrelease -gt 6 ]; then
164105f6
MW
827 auto_dev="1"
828else
829 auto_dev="0"
830fi
831
832if [ "$(id -u)" != "0" ]; then
833 echo "This script should be run as 'root'"
834 exit 1
835fi
836
837
838if [ -z "$rootfs_path" ]; then
839 rootfs_path=$path/rootfs
840 # check for 'lxc.rootfs' passed in through default config by lxc-create
841 if grep -q '^lxc.rootfs' $path/config 2>/dev/null ; then
08754f30
MW
842 rootfs_path=$(sed -e '/^lxc.rootfs\s*=/!d' -e 's/\s*#.*//' \
843 -e 's/^lxc.rootfs\s*=\s*//' -e q $path/config)
164105f6
MW
844 fi
845fi
08754f30 846config_path=$path
164105f6
MW
847cache=$cache_base/$release
848
849revert()
850{
851 echo "Interrupted, so cleaning up"
852 lxc-destroy -n $name
853 # maybe was interrupted before copy config
854 rm -rf $path
164105f6
MW
855 echo "exiting..."
856 exit 1
857}
858
859trap revert SIGHUP SIGINT SIGTERM
860
861copy_configuration
862if [ $? -ne 0 ]; then
863 echo "failed write configuration file"
864 exit 1
865fi
866
867install_centos
868if [ $? -ne 0 ]; then
869 echo "failed to install centos"
870 exit 1
871fi
872
873configure_centos
874if [ $? -ne 0 ]; then
875 echo "failed to configure centos for a container"
876 exit 1
877fi
878
879configure_centos_init
880
881if [ ! -z $clean ]; then
882 clean || exit 1
883 exit 0
884fi
b4f7af7a
MW
885echo "
886Container rootfs and config have been created.
887Edit the config file to check/enable networking setup.
888"
889
890if [ ${root_display_password} = "yes" ]
891then
892 echo "The temporary password for root is: '$root_password'
893
894You may want to note that password down before starting the container.
895"
896fi
897
898if [ ${root_store_password} = "yes" ]
899then
900 echo "The temporary root password is stored in:
901
902 '${config_path}/tmp_root_pass'
903"
904fi
905
906if [ ${root_prompt_password} = "yes" ]
907then
908 echo "Invoking the passwd command in the container to set the root password.
909
910 chroot ${rootfs_path} passwd
911"
912 chroot ${rootfs_path} passwd
913else
826cde7c
MW
914 if [ ${root_expire_password} = "yes" ]
915 then
916 echo "
b4f7af7a
MW
917The root password is set up as "expired" and will require it to be changed
918at first login, which you should do as soon as possible. If you lose the
919root password or wish to change it without starting the container, you
920can change it from the host by running the following command (which will
921also reset the expired flag):
922
923 chroot ${rootfs_path} passwd
924"
826cde7c 925 fi
b4f7af7a 926fi