]> git.proxmox.com Git - mirror_lxc.git/blob - templates/lxc-centos.in
Added lxc.arch to configuration files for CentOS and Fedora
[mirror_lxc.git] / templates / lxc-centos.in
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
30 default_path=@LXCPATH@
31
32 # Some combinations of the tuning 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 # If root_expire_password = yes, you will be prompted to change the root
49 # password at the first login.
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 # Expire root password? Default to yes, but can be overridden from
67 # the environment variable
68 : ${root_expire_password='yes'}
69
70 # These are only going into comments in the resulting config...
71 lxc_network_type=veth
72 lxc_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
81 # Detect use under userns (unsupported)
82 for arg in "$@"; do
83 [ "$arg" = "--" ] && break
84 if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
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
89 done
90
91 # Make sure the usual locations are in PATH
92 export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
93
94 if [ -e /etc/os-release ]
95 then
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}"
100 fi
101
102 if [ "${CPE_NAME}" = "" -a -e /etc/system-release-cpe ]
103 then
104 CPE_NAME=$(head -n1 /etc/system-release-cpe)
105 CPE_URI=$(expr ${CPE_NAME} : '\([^:]*:[^:]*\)')
106 if [ "${CPE_URI}" != "cpe:/o" ]
107 then
108 CPE_NAME=
109 else
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.
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 #
120 ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:\([^:]*\)')
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
131 VERSION_ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\)')
132 echo "Host CPE ID from /etc/system-release-cpe: ${CPE_NAME}"
133 fi
134 fi
135
136 if [ "${CPE_NAME}" != "" -a "${ID}" = "centos" -a "${VERSION_ID}" != "" ]
137 then
138 centos_host_ver=${VERSION_ID}
139 is_centos=true
140 elif [ "${CPE_NAME}" != "" -a "${ID}" = "redhat" -a "${VERSION_ID}" != "" ]
141 then
142 redhat_host_ver=${VERSION_ID}
143 is_redhat=true
144 elif [ -e /etc/centos-release ]
145 then
146 # Only if all other methods fail, try to parse the redhat-release file.
147 centos_host_ver=$( sed -e '/^CentOS /!d' -e 's/CentOS.*\srelease\s*\([0-9][0-9.]*\)\s.*/\1/' < /etc/centos-release )
148 if [ "$centos_host_ver" != "" ]
149 then
150 is_centos=true
151 fi
152 fi
153
154 force_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
160 configure_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...
168 if [ -f $rootfs_path/etc/selinux/config ]
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
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
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
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
248 cat <<EOF > ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0
249 DEVICE=eth0
250 BOOTPROTO=dhcp
251 ONBOOT=yes
252 HOSTNAME=${UTSNAME}
253 NM_CONTROLLED=no
254 TYPE=Ethernet
255 MTU=${MTU}
256 EOF
257
258 # set the hostname
259 cat <<EOF > ${rootfs_path}/etc/sysconfig/network
260 NETWORKING=yes
261 HOSTNAME=${UTSNAME}
262 EOF
263
264 # set minimal hosts
265 cat <<EOF > $rootfs_path/etc/hosts
266 127.0.0.1 localhost $name
267 EOF
268
269 # set minimal fstab
270 cat <<EOF > $rootfs_path/etc/fstab
271 /dev/root / rootfs defaults 0 0
272 none /dev/shm tmpfs nosuid,nodev 0 0
273 EOF
274
275 # create lxc compatibility init script
276 if [ "$release" = "6" ]; then
277 cat <<EOF > $rootfs_path/etc/init/lxc-sysinit.conf
278 start on startup
279 env container
280
281 pre-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;
290 end script
291 EOF
292 elif [ "$release" = "5" ]; then
293 cat <<EOF > $rootfs_path/etc/rc.d/lxc.sysinit
294 #! /bin/bash
295 rm -f /etc/mtab /var/run/*.{pid,lock} /var/lock/subsys/*
296 rm -rf {/,/var}/tmp/*
297 echo "/dev/root / rootfs defaults 0 0" > /etc/mtab
298 exit 0
299 EOF
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
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
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
354 echo "root:$root_password" | chroot $rootfs_path chpasswd
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
361
362 # This will need to be enhanced for CentOS 7 when systemd
363 # comes into play... /\/\|=mhw=|\/\/
364
365 return 0
366 }
367
368 configure_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
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 #
383 start on power-status-changed
384
385 exec /sbin/shutdown -h now "SIGPWR received"
386 EOF
387 fi
388 }
389
390 download_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)
409 if [ -n "$repo" ]; then
410 cat <<EOF > $REPO_FILE
411 [base]
412 name=local repository
413 baseurl="$repo"
414 EOF
415 else
416 cat <<EOF > $REPO_FILE
417 [base]
418 name=CentOS-$release - Base
419 mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=os
420
421 [updates]
422 name=CentOS-$release - Updates
423 mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=updates
424 EOF
425 fi
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
488 copy_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/
497 echo
498 return 0
499 }
500
501 update_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
511 install_centos()
512 {
513 mkdir -p /var/lock/subsys/
514 (
515 flock -x 9
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
547 ) 9>/var/lock/subsys/lxc-centos
548
549 return $?
550 }
551
552 create_hwaddr()
553 {
554 openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/'
555 }
556
557 copy_configuration()
558 {
559 mkdir -p $config_path
560
561 grep -q "^lxc.rootfs" $config_path/config 2>/dev/null || echo "
562 lxc.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
594 if [ -e "@LXCTEMPLATECONFIG@/centos.common.conf" ]; then
595 echo "
596 # Include common configuration
597 lxc.include = @LXCTEMPLATECONFIG@/centos.common.conf
598 " >> $config_path/config
599 fi
600
601 # Append things which require expansion here...
602 cat <<EOF >> $config_path/config
603 lxc.arch = $arch
604 lxc.utsname = $utsname
605
606 lxc.autodev = $auto_dev
607
608 # When using LXC with apparmor, uncomment the next line to run unconfined:
609 #lxc.aa_profile = unconfined
610
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
616 # Additional example for veth network type
617 # static MAC address,
618 #lxc.network.hwaddr = 00:16:3e:77:52:20
619 # persistent veth device name on host side
620 # Note: This may potentially collide with other containers of same name!
621 #lxc.network.veth.pair = v-$name-e0
622
623 EOF
624
625 if [ $? -ne 0 ]; then
626 echo "Failed to add configuration"
627 return 1
628 fi
629
630 return 0
631 }
632
633 clean()
634 {
635
636 if [ ! -e $cache ]; then
637 exit 0
638 fi
639
640 # lock, so we won't purge while someone is creating a repository
641 (
642 flock -x 9
643 if [ $? != 0 ]; then
644 echo "Cache repository is busy."
645 exit 1
646 fi
647
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
651
652 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-centos
653 }
654
655 usage()
656 {
657 cat <<EOF
658 usage:
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]
662 Mandatory args:
663 -n,--name container name, used to as an identifier for that container from now on
664 Optional args:
665 -p,--path path to where the container rootfs will be created, defaults to /var/lib/lxc/name.
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
669 --repo repository to use (url)
670 -a,--arch Define what arch the container will be [i686,x86_64]
671 -h,--help print this help
672 EOF
673 return 0
674 }
675
676 options=$(getopt -o a:hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,repo:,arch:,fqdn: -- "$@")
677 if [ $? -ne 0 ]; then
678 usage $(basename $0)
679 exit 1
680 fi
681
682 arch=$(arch)
683 eval set -- "$options"
684 while true
685 do
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;;
693 --repo) repo="$2"; shift 2;;
694 -a|--arch) newarch=$2; shift 2;;
695 --fqdn) utsname=$2; shift 2;;
696 --) shift 1; break ;;
697 *) break ;;
698 esac
699 done
700
701 if [ ! -z "$clean" -a -z "$path" ]; then
702 clean || exit 1
703 exit 0
704 fi
705
706 basearch=${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.
713 case "$arch" in
714 i686) basearch=i386 ;;
715 armv3l|armv4l|armv5l) basearch=arm ;;
716 armv6l|armv7l|armv8l) basearch=armhfp ;;
717 *) ;;
718 esac
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
724 if [ "${newarch}" != "" -a "${newarch}" != "${arch}" ]
725 then
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
747 fi
748
749 cache_base=@LOCALSTATEDIR@/cache/lxc/centos/$basearch
750
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.
755 if [ "${root_password}" = "" ]
756 then
757 root_password=Root-${name}-${RANDOM}
758 else
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
771 fi
772
773 if [ -z "${utsname}" ]; then
774 utsname=${name}
775 fi
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
790 if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then
791 if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then
792 utsname=${utsname}.$(dnsdomainname)
793 fi
794 fi
795
796 type yum >/dev/null 2>&1
797 if [ $? -ne 0 ]; then
798 echo "'yum' command is missing"
799 exit 1
800 fi
801
802 if [ -z "$path" ]; then
803 path=$default_path/$name
804 fi
805
806 if [ -z "$release" ]; then
807 if [ "$is_centos" -a "$centos_host_ver" ]; then
808 release=$centos_host_ver
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.]*\)')
812 else
813 echo "This is not a CentOS or Redhat host and release is missing, defaulting to 6 use -R|--release to specify release"
814 release=6
815 fi
816 fi
817
818 # CentOS 7 and above should run systemd. We need autodev enabled to keep
819 # systemd from causing problems.
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
825 mrelease=$(expr $release : '\([0-9]*\)')
826 if [ $mrelease -gt 6 ]; then
827 auto_dev="1"
828 else
829 auto_dev="0"
830 fi
831
832 if [ "$(id -u)" != "0" ]; then
833 echo "This script should be run as 'root'"
834 exit 1
835 fi
836
837
838 if [ -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
842 rootfs_path=$(sed -e '/^lxc.rootfs\s*=/!d' -e 's/\s*#.*//' \
843 -e 's/^lxc.rootfs\s*=\s*//' -e q $path/config)
844 fi
845 fi
846 config_path=$path
847 cache=$cache_base/$release
848
849 revert()
850 {
851 echo "Interrupted, so cleaning up"
852 lxc-destroy -n $name
853 # maybe was interrupted before copy config
854 rm -rf $path
855 echo "exiting..."
856 exit 1
857 }
858
859 trap revert SIGHUP SIGINT SIGTERM
860
861 copy_configuration
862 if [ $? -ne 0 ]; then
863 echo "failed write configuration file"
864 exit 1
865 fi
866
867 install_centos
868 if [ $? -ne 0 ]; then
869 echo "failed to install centos"
870 exit 1
871 fi
872
873 configure_centos
874 if [ $? -ne 0 ]; then
875 echo "failed to configure centos for a container"
876 exit 1
877 fi
878
879 configure_centos_init
880
881 if [ ! -z $clean ]; then
882 clean || exit 1
883 exit 0
884 fi
885 echo "
886 Container rootfs and config have been created.
887 Edit the config file to check/enable networking setup.
888 "
889
890 if [ ${root_display_password} = "yes" ]
891 then
892 echo "The temporary password for root is: '$root_password'
893
894 You may want to note that password down before starting the container.
895 "
896 fi
897
898 if [ ${root_store_password} = "yes" ]
899 then
900 echo "The temporary root password is stored in:
901
902 '${config_path}/tmp_root_pass'
903 "
904 fi
905
906 if [ ${root_prompt_password} = "yes" ]
907 then
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
913 else
914 if [ ${root_expire_password} = "yes" ]
915 then
916 echo "
917 The root password is set up as "expired" and will require it to be changed
918 at first login, which you should do as soon as possible. If you lose the
919 root password or wish to change it without starting the container, you
920 can change it from the host by running the following command (which will
921 also reset the expired flag):
922
923 chroot ${rootfs_path} passwd
924 "
925 fi
926 fi