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