]> git.proxmox.com Git - mirror_lxc.git/blame - templates/lxc-centos.in
Do not allow snapshots of LVM backed containers
[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
7edae51e
CAR
302 # prevent mingetty from calling vhangup(2) since it fails with userns.
303 # Same issue as oracle template: prevent mingetty from calling vhangup(2)
304 # commit 2e83f7201c5d402478b9849f0a85c62d5b9f1589.
305 sed -i 's|^1:|co:2345:respawn:/sbin/mingetty --nohangup console\n1:|' $rootfs_path/etc/inittab
164105f6
MW
306 sed -i 's|^\([56]:\)|#\1|' $rootfs_path/etc/inittab
307 fi
308
309 dev_path="${rootfs_path}/dev"
310 rm -rf $dev_path
311 mkdir -p $dev_path
312 mknod -m 666 ${dev_path}/null c 1 3
313 mknod -m 666 ${dev_path}/zero c 1 5
314 mknod -m 666 ${dev_path}/random c 1 8
315 mknod -m 666 ${dev_path}/urandom c 1 9
316 mkdir -m 755 ${dev_path}/pts
317 mkdir -m 1777 ${dev_path}/shm
318 mknod -m 666 ${dev_path}/tty c 5 0
319 mknod -m 666 ${dev_path}/tty0 c 4 0
320 mknod -m 666 ${dev_path}/tty1 c 4 1
321 mknod -m 666 ${dev_path}/tty2 c 4 2
322 mknod -m 666 ${dev_path}/tty3 c 4 3
323 mknod -m 666 ${dev_path}/tty4 c 4 4
324 mknod -m 600 ${dev_path}/console c 5 1
325 mknod -m 666 ${dev_path}/full c 1 7
326 mknod -m 600 ${dev_path}/initctl p
327 mknod -m 666 ${dev_path}/ptmx c 5 2
328
1ecee40b
MW
329 # setup console and tty[1-4] for login. note that /dev/console and
330 # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and
331 # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks.
332 # lxc will maintain these links and bind mount ptys over /dev/lxc/*
333 # since lxc.devttydir is specified in the config.
334
335 # allow root login on console, tty[1-4], and pts/0 for libvirt
336 echo "# LXC (Linux Containers)" >>${rootfs_path}/etc/securetty
337 echo "lxc/console" >>${rootfs_path}/etc/securetty
338 echo "lxc/tty1" >>${rootfs_path}/etc/securetty
339 echo "lxc/tty2" >>${rootfs_path}/etc/securetty
340 echo "lxc/tty3" >>${rootfs_path}/etc/securetty
341 echo "lxc/tty4" >>${rootfs_path}/etc/securetty
342 echo "# For libvirt/Virtual Machine Monitor" >>${rootfs_path}/etc/securetty
343 echo "pts/0" >>${rootfs_path}/etc/securetty
344
7edae51e
CAR
345 # prevent mingetty from calling vhangup(2) since it fails with userns.
346 # Same issue as oracle template: prevent mingetty from calling vhangup(2)
347 # commit 2e83f7201c5d402478b9849f0a85c62d5b9f1589.
348 sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc/init/tty.conf
349
b4f7af7a
MW
350 if [ ${root_display_password} = "yes" ]
351 then
352 echo "Setting root password to '$root_password'"
353 fi
354 if [ ${root_store_password} = "yes" ]
355 then
356 touch ${config_path}/tmp_root_pass
357 chmod 600 ${config_path}/tmp_root_pass
358 echo ${root_password} > ${config_path}/tmp_root_pass
359 echo "Storing root password in '${config_path}/tmp_root_pass'"
360 fi
361
164105f6 362 echo "root:$root_password" | chroot $rootfs_path chpasswd
826cde7c
MW
363
364 if [ ${root_expire_password} = "yes" ]
365 then
366 # Also set this password as expired to force the user to change it!
367 chroot $rootfs_path passwd -e root
368 fi
164105f6
MW
369
370 # This will need to be enhanced for CentOS 7 when systemd
371 # comes into play... /\/\|=mhw=|\/\/
372
373 return 0
374}
375
376configure_centos_init()
377{
378 sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.sysinit
379 sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.d/rc.sysinit
380 if [ "$release" = "6" ]; then
381 chroot ${rootfs_path} chkconfig udev-post off
382 fi
383 chroot ${rootfs_path} chkconfig network on
779b47fd
MW
384
385 if [ -d ${rootfs_path}/etc/init ]
386 then
387 # This is to make upstart honor SIGPWR
388 cat <<EOF >${rootfs_path}/etc/init/power-status-changed.conf
389# power-status-changed - shutdown on SIGPWR
390#
391start on power-status-changed
392
393exec /sbin/shutdown -h now "SIGPWR received"
394EOF
395 fi
164105f6
MW
396}
397
398download_centos()
399{
400
401 # check the mini centos was not already downloaded
402 INSTALL_ROOT=$cache/partial
403 mkdir -p $INSTALL_ROOT
404 if [ $? -ne 0 ]; then
405 echo "Failed to create '$INSTALL_ROOT' directory"
406 return 1
407 fi
408
409 # download a mini centos into a cache
410 echo "Downloading centos minimal ..."
411 YUM="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
412 PKG_LIST="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils"
413
414 # use temporary repository definition
415 REPO_FILE=$INSTALL_ROOT/etc/yum.repos.d/lxc-centos-temp.repo
416 mkdir -p $(dirname $REPO_FILE)
3a6ef65a
HD
417 if [ -n "$repo" ]; then
418 cat <<EOF > $REPO_FILE
419[base]
420name=local repository
421baseurl="$repo"
422EOF
423else
424 cat <<EOF > $REPO_FILE
164105f6
MW
425[base]
426name=CentOS-$release - Base
08754f30 427mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=os
164105f6
MW
428
429[updates]
430name=CentOS-$release - Updates
08754f30 431mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=updates
164105f6 432EOF
3a6ef65a 433 fi
164105f6
MW
434
435 # create minimal device nodes, needed for "yum install" and "yum update" process
436 mkdir -p $INSTALL_ROOT/dev
437 force_mknod 666 $INSTALL_ROOT/dev/null c 1 3
438 force_mknod 666 $INSTALL_ROOT/dev/urandom c 1 9
439
440 $YUM install $PKG_LIST
441
442 if [ $? -ne 0 ]; then
443 echo "Failed to download the rootfs, aborting."
444 return 1
445 fi
446
447 # use same nameservers as hosts, needed for "yum update later"
448 cp /etc/resolv.conf $INSTALL_ROOT/etc/
449
450 # check whether rpmdb is under $HOME
451 if [ ! -e $INSTALL_ROOT/var/lib/rpm/Packages -a -e $INSTALL_ROOT/$HOME/.rpmdb/Packages ]; then
452 echo "Fixing rpmdb location ..."
453 mv $INSTALL_ROOT/$HOME/.rpmdb/[A-Z]* $INSTALL_ROOT/var/lib/rpm/
454 rm -rf $INSTALL_ROOT/$HOME/.rpmdb
455 chroot $INSTALL_ROOT rpm --rebuilddb 2>/dev/null
456 fi
457
458 # check whether rpmdb version is correct
459 chroot $INSTALL_ROOT rpm --quiet -q yum 2>/dev/null
460 ret=$?
461
462 # if "rpm -q" doesn't work due to rpmdb version difference,
463 # then we need to redo the process using the newly-installed yum
464 if [ $ret -gt 0 ]; then
465 echo "Reinstalling packages ..."
466 mv $REPO_FILE $REPO_FILE.tmp
467 mkdir $INSTALL_ROOT/etc/yum.repos.disabled
468 mv $INSTALL_ROOT/etc/yum.repos.d/*.repo $INSTALL_ROOT/etc/yum.repos.disabled/
469 mv $REPO_FILE.tmp $REPO_FILE
470 mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/etc
471 cp /etc/resolv.conf $INSTALL_ROOT/$INSTALL_ROOT/etc/
472 mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/dev
473 mknod -m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev/null c 1 3
474 mknod -m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev/urandom c 1 9
475 mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/var/cache/yum
476 cp -al $INSTALL_ROOT/var/cache/yum/* $INSTALL_ROOT/$INSTALL_ROOT/var/cache/yum/
477 chroot $INSTALL_ROOT $YUM install $PKG_LIST
478 if [ $? -ne 0 ]; then
479 echo "Failed to download the rootfs, aborting."
480 return 1
481 fi
482 mv $INSTALL_ROOT/$INSTALL_ROOT $INSTALL_ROOT.tmp
483 rm -rf $INSTALL_ROOT
484 mv $INSTALL_ROOT.tmp $INSTALL_ROOT
485 fi
486
487 rm -f $REPO_FILE
488 rm -rf $INSTALL_ROOT/var/cache/yum/*
489
490 mv "$INSTALL_ROOT" "$cache/rootfs"
491 echo "Download complete."
492
493 return 0
494}
495
496copy_centos()
497{
498
499 # make a local copy of the mini centos
500 echo -n "Copying rootfs to $rootfs_path ..."
501 #cp -a $cache/rootfs-$arch $rootfs_path || return 1
502 # i prefer rsync (no reason really)
503 mkdir -p $rootfs_path
504 rsync -a $cache/rootfs/ $rootfs_path/
b4f7af7a 505 echo
164105f6
MW
506 return 0
507}
508
509update_centos()
510{
511 YUM="chroot $cache/rootfs yum -y --nogpgcheck"
512 $YUM update
513 if [ $? -ne 0 ]; then
514 return 1
515 fi
516 $YUM clean packages
517}
518
519install_centos()
520{
521 mkdir -p /var/lock/subsys/
522 (
17abf278 523 flock -x 9
164105f6
MW
524 if [ $? -ne 0 ]; then
525 echo "Cache repository is busy."
526 return 1
527 fi
528
529 echo "Checking cache download in $cache/rootfs ... "
530 if [ ! -e "$cache/rootfs" ]; then
531 download_centos
532 if [ $? -ne 0 ]; then
533 echo "Failed to download 'centos base'"
534 return 1
535 fi
536 else
537 echo "Cache found. Updating..."
538 update_centos
539 if [ $? -ne 0 ]; then
540 echo "Failed to update 'centos base', continuing with last known good cache"
541 else
542 echo "Update finished"
543 fi
544 fi
545
546 echo "Copy $cache/rootfs to $rootfs_path ... "
547 copy_centos
548 if [ $? -ne 0 ]; then
549 echo "Failed to copy rootfs"
550 return 1
551 fi
552
553 return 0
554
17abf278 555 ) 9>/var/lock/subsys/lxc-centos
164105f6
MW
556
557 return $?
558}
559
b4f7af7a 560create_hwaddr()
164105f6 561{
08754f30 562 openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/'
b4f7af7a 563}
164105f6 564
b4f7af7a
MW
565copy_configuration()
566{
164105f6 567 mkdir -p $config_path
b4f7af7a
MW
568
569 grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo "
570lxc.rootfs = $rootfs_path
571" >> $config_path/config
572
573 # The following code is to create static MAC addresses for each
574 # interface in the container. This code will work for multiple
575 # interfaces in the default config.
576 mv $config_path/config $config_path/config.def
577 while read LINE
578 do
579 # This should catch variable expansions from the default config...
580 if expr "${LINE}" : '.*\$' > /dev/null 2>&1
581 then
582 LINE=$(eval "echo \"${LINE}\"")
583 fi
584
585 # There is a tab and a space in the regex bracket below!
586 # Seems that \s doesn't work in brackets.
587 KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=')
588
589 if [[ "${KEY}" != "lxc.network.hwaddr" ]]
590 then
591 echo ${LINE} >> $config_path/config
592
593 if [[ "${KEY}" == "lxc.network.link" ]]
594 then
595 echo "lxc.network.hwaddr = $(create_hwaddr)" >> $config_path/config
596 fi
597 fi
598 done < $config_path/config.def
599
600 rm -f $config_path/config.def
601
1ecee40b
MW
602 if [ -e "@LXCTEMPLATECONFIG@/centos.common.conf" ]; then
603 echo "
604# Include common configuration
605lxc.include = @LXCTEMPLATECONFIG@/centos.common.conf
606" >> $config_path/config
607 fi
608
609 # Append things which require expansion here...
164105f6 610 cat <<EOF >> $config_path/config
e13923c7 611lxc.arch = $arch
164105f6 612lxc.utsname = $utsname
164105f6
MW
613
614lxc.autodev = $auto_dev
615
b4f7af7a
MW
616# When using LXC with apparmor, uncomment the next line to run unconfined:
617#lxc.aa_profile = unconfined
618
164105f6
MW
619# example simple networking setup, uncomment to enable
620#lxc.network.type = $lxc_network_type
621#lxc.network.flags = up
622#lxc.network.link = $lxc_network_link
623#lxc.network.name = eth0
b4f7af7a
MW
624# Additional example for veth network type
625# static MAC address,
164105f6 626#lxc.network.hwaddr = 00:16:3e:77:52:20
b4f7af7a
MW
627# persistent veth device name on host side
628# Note: This may potentially collide with other containers of same name!
164105f6
MW
629#lxc.network.veth.pair = v-$name-e0
630
164105f6
MW
631EOF
632
633 if [ $? -ne 0 ]; then
b4f7af7a
MW
634 echo "Failed to add configuration"
635 return 1
164105f6
MW
636 fi
637
638 return 0
639}
640
641clean()
642{
643
644 if [ ! -e $cache ]; then
b4f7af7a 645 exit 0
164105f6
MW
646 fi
647
648 # lock, so we won't purge while someone is creating a repository
649 (
b4f7af7a
MW
650 flock -x 9
651 if [ $? != 0 ]; then
652 echo "Cache repository is busy."
653 exit 1
654 fi
164105f6 655
b4f7af7a
MW
656 echo -n "Purging the download cache for centos-$release..."
657 rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
658 exit 0
164105f6 659
b4f7af7a 660 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-centos
164105f6
MW
661}
662
663usage()
664{
665 cat <<EOF
666usage:
667 $1 -n|--name=<container_name>
668 [-p|--path=<path>] [-c|--clean] [-R|--release=<CentOS_release>] [-A|--arch=<arch of the container>]
669 [-h|--help]
670Mandatory args:
671 -n,--name container name, used to as an identifier for that container from now on
672Optional args:
08754f30 673 -p,--path path to where the container rootfs will be created, defaults to /var/lib/lxc/name.
164105f6
MW
674 -c,--clean clean the cache
675 -R,--release Centos release for the new container. if the host is Centos, then it will defaultto the host's release.
676 --fqdn fully qualified domain name (FQDN) for DNS and system naming
3a6ef65a 677 --repo repository to use (url)
08754f30 678 -a,--arch Define what arch the container will be [i686,x86_64]
164105f6
MW
679 -h,--help print this help
680EOF
681 return 0
682}
683
3a6ef65a 684options=$(getopt -o a:hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,repo:,arch:,fqdn: -- "$@")
164105f6
MW
685if [ $? -ne 0 ]; then
686 usage $(basename $0)
687 exit 1
688fi
164105f6 689
08754f30
MW
690arch=$(arch)
691eval set -- "$options"
164105f6
MW
692while true
693do
694 case "$1" in
695 -h|--help) usage $0 && exit 0;;
696 -p|--path) path=$2; shift 2;;
697 --rootfs) rootfs=$2; shift 2;;
698 -n|--name) name=$2; shift 2;;
699 -c|--clean) clean=$2; shift 2;;
700 -R|--release) release=$2; shift 2;;
3a6ef65a 701 --repo) repo="$2"; shift 2;;
08754f30 702 -a|--arch) newarch=$2; shift 2;;
164105f6
MW
703 --fqdn) utsname=$2; shift 2;;
704 --) shift 1; break ;;
705 *) break ;;
706 esac
707done
708
709if [ ! -z "$clean" -a -z "$path" ]; then
710 clean || exit 1
711 exit 0
712fi
713
08754f30
MW
714basearch=${arch}
715# Map a few architectures to their generic CentOS repository archs.
716# The two ARM archs are a bit of a guesstimate for the v5 and v6
717# archs. V6 should have hardware floating point (Rasberry Pi).
718# The "arm" arch is safer (no hardware floating point). So
719# there may be cases where we "get it wrong" for some v6 other
720# than RPi.
721case "$arch" in
722i686) basearch=i386 ;;
723armv3l|armv4l|armv5l) basearch=arm ;;
724armv6l|armv7l|armv8l) basearch=armhfp ;;
725*) ;;
726esac
727
728# Somebody wants to specify an arch. This is very limited case.
729# i386/i586/i686 on i386/x86_64
730# - or -
731# x86_64 on x86_64
732if [ "${newarch}" != "" -a "${newarch}" != "${arch}" ]
733then
734 case "${newarch}" in
735 i386|i586|i686)
736 if [ "${basearch}" = "i386" -o "${basearch}" = "x86_64" ]
737 then
738 # Make the arch a generic x86 32 bit...
739 arch=${newarch}
740 basearch=i386
741 else
742 basearch=bad
743 fi
744 ;;
745 *)
746 basearch=bad
747 ;;
748 esac
749
750 if [ "${basearch}" = "bad" ]
751 then
752 echo "You cannot build a ${newarch} CentOS container on a ${arch} host. Sorry!"
753 exit 1
754 fi
755fi
756
757cache_base=@LOCALSTATEDIR@/cache/lxc/centos/$basearch
758
b4f7af7a
MW
759# Let's do something better for the initial root password.
760# It's not perfect but it will defeat common scanning brute force
761# attacks in the case where ssh is exposed. It will also be set to
762# expired, forcing the user to change it at first login.
763if [ "${root_password}" = "" ]
764then
765 root_password=Root-${name}-${RANDOM}
766else
767 # If it's got a ding in it, try and expand it!
768 if [ $(expr "${root_password}" : '.*$.') != 0 ]
769 then
770 root_password=$(eval echo "${root_password}")
771 fi
772
773 # If it has more than 3 consequtive X's in it, feed it
774 # through mktemp as a template.
775 if [ $(expr "${root_password}" : '.*XXXX') != 0 ]
776 then
777 root_password=$(mktemp -u ${root_password})
778 fi
779fi
780
164105f6
MW
781if [ -z "${utsname}" ]; then
782 utsname=${name}
783fi
784
785# This follows a standard "resolver" convention that an FQDN must have
786# at least two dots or it is considered a local relative host name.
787# If it doesn't, append the dns domain name of the host system.
788#
789# This changes one significant behavior when running
790# "lxc_create -n Container_Name" without using the
791# --fqdn option.
792#
793# Old behavior:
794# utsname and hostname = Container_Name
795# New behavior:
796# utsname and hostname = Container_Name.Domain_Name
797
798if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then
b4f7af7a 799 if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then
164105f6
MW
800 utsname=${utsname}.$(dnsdomainname)
801 fi
802fi
803
804type yum >/dev/null 2>&1
805if [ $? -ne 0 ]; then
806 echo "'yum' command is missing"
807 exit 1
808fi
809
810if [ -z "$path" ]; then
811 path=$default_path/$name
812fi
813
814if [ -z "$release" ]; then
815 if [ "$is_centos" -a "$centos_host_ver" ]; then
816 release=$centos_host_ver
c6df5ca4
MW
817 elif [ "$is_redhat" -a "$redhat_host_ver" ]; then
818 # This is needed to clean out bullshit like 6workstation and 6server.
819 release=$(expr $redhat_host_ver : '\([0-9.]*\)')
164105f6 820 else
c6df5ca4 821 echo "This is not a CentOS or Redhat host and release is missing, defaulting to 6 use -R|--release to specify release"
164105f6
MW
822 release=6
823 fi
824fi
825
826# CentOS 7 and above should run systemd. We need autodev enabled to keep
827# systemd from causing problems.
c6df5ca4
MW
828#
829# There is some ambiguity here due to the differnce between versioning
830# of point specific releases such as 6.5 and the rolling release 6. We
831# only want the major number here if it's a point release...
832
833mrelease=$(expr $release : '\([0-9]*\)')
834if [ $mrelease -gt 6 ]; then
164105f6
MW
835 auto_dev="1"
836else
837 auto_dev="0"
838fi
839
840if [ "$(id -u)" != "0" ]; then
841 echo "This script should be run as 'root'"
842 exit 1
843fi
844
845
846if [ -z "$rootfs_path" ]; then
847 rootfs_path=$path/rootfs
848 # check for 'lxc.rootfs' passed in through default config by lxc-create
849 if grep -q '^lxc.rootfs' $path/config 2>/dev/null ; then
08754f30
MW
850 rootfs_path=$(sed -e '/^lxc.rootfs\s*=/!d' -e 's/\s*#.*//' \
851 -e 's/^lxc.rootfs\s*=\s*//' -e q $path/config)
164105f6
MW
852 fi
853fi
08754f30 854config_path=$path
164105f6
MW
855cache=$cache_base/$release
856
857revert()
858{
859 echo "Interrupted, so cleaning up"
860 lxc-destroy -n $name
861 # maybe was interrupted before copy config
862 rm -rf $path
164105f6
MW
863 echo "exiting..."
864 exit 1
865}
866
867trap revert SIGHUP SIGINT SIGTERM
868
869copy_configuration
870if [ $? -ne 0 ]; then
871 echo "failed write configuration file"
872 exit 1
873fi
874
875install_centos
876if [ $? -ne 0 ]; then
877 echo "failed to install centos"
878 exit 1
879fi
880
881configure_centos
882if [ $? -ne 0 ]; then
883 echo "failed to configure centos for a container"
884 exit 1
885fi
886
887configure_centos_init
888
889if [ ! -z $clean ]; then
890 clean || exit 1
891 exit 0
892fi
b4f7af7a
MW
893echo "
894Container rootfs and config have been created.
895Edit the config file to check/enable networking setup.
896"
897
898if [ ${root_display_password} = "yes" ]
899then
900 echo "The temporary password for root is: '$root_password'
901
902You may want to note that password down before starting the container.
903"
904fi
905
906if [ ${root_store_password} = "yes" ]
907then
908 echo "The temporary root password is stored in:
909
910 '${config_path}/tmp_root_pass'
911"
912fi
913
914if [ ${root_prompt_password} = "yes" ]
915then
916 echo "Invoking the passwd command in the container to set the root password.
917
918 chroot ${rootfs_path} passwd
919"
920 chroot ${rootfs_path} passwd
921else
826cde7c
MW
922 if [ ${root_expire_password} = "yes" ]
923 then
924 echo "
b4f7af7a
MW
925The root password is set up as "expired" and will require it to be changed
926at first login, which you should do as soon as possible. If you lose the
927root password or wish to change it without starting the container, you
928can change it from the host by running the following command (which will
929also reset the expired flag):
930
931 chroot ${rootfs_path} passwd
932"
826cde7c 933 fi
b4f7af7a 934fi