4 # template script for generating centos container for LXC
7 # lxc: linux Container library
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>
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.
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.
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
30 default_path
=@LXCPATH@
32 # Some combinations of the tuning knobs below do not exactly make sense.
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.
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 contains more than 3 consecutive X's, pass it as
42 # a template to mktemp and take the result.
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.
51 # These are conditional assignments... The can be overridden from the
52 # preexisting environment variables...
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'}
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'}
66 # Expire root password? Default to yes, but can be overridden from
67 # the environment variable
68 : ${root_expire_password='yes'}
70 # These are only going into comments in the resulting config...
72 lxc_network_link
=lxcbr0
75 # Alow for weird remixes like the Raspberry Pi
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.
81 # Detect use under userns (unsupported)
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
91 # Make sure the usual locations are in PATH
92 export PATH
=$PATH:/usr
/sbin
:/usr
/bin
:/sbin
:/bin
94 if [ -e /etc
/os-release
]
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
99 echo "Host CPE ID from /etc/os-release: ${CPE_NAME}"
102 if [ "${CPE_NAME}" = "" -a -e /etc
/system-release-cpe
]
104 CPE_NAME
=$
(head -n1 /etc
/system-release-cpe
)
105 CPE_URI
=$
(expr ${CPE_NAME} : '\([^:]*:[^:]*\)')
106 if [ "${CPE_URI}" != "cpe:/o" ]
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.
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
118 # cpe:/o:centos:centos:6.5
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" ]
127 # Instead we got this: cpe:/o:centos:linux:6
128 ID
=$
(expr ${CPE_NAME} : '[^:]*:[^:]*:\([^:]*\)')
131 VERSION_ID
=$
(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\)')
132 echo "Host CPE ID from /etc/system-release-cpe: ${CPE_NAME}"
136 if [ "${CPE_NAME}" != "" -a "${ID}" = "centos" -a "${VERSION_ID}" != "" ]
138 centos_host_ver
=${VERSION_ID}
140 elif [ "${CPE_NAME}" != "" -a "${ID}" = "redhat" -a "${VERSION_ID}" != "" ]
142 redhat_host_ver
=${VERSION_ID}
144 elif [ -e /etc
/centos-release
]
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" != "" ]
156 # delete a device node if exists, and create a new one
157 rm -f $2 && mknod
-m $1 $2 $3 $4 $5
163 # disable selinux in centos
164 mkdir
-p $rootfs_path/selinux
165 echo 0 > $rootfs_path/selinux
/enforce
167 # Also kill it in the /etc/selinux/config file if it's there...
168 if [ -f $rootfs_path/etc
/selinux
/config
]
170 sed -i '/^SELINUX=/s/.*/SELINUX=disabled/' $rootfs_path/etc
/selinux
/config
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
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
186 if [ -f ${rootfs_path}/etc
/pam.d
/crond
]
188 sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc
/pam.d
/crond
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.
195 # Catch either or both 32 and 64 bit archs.
196 if [ -f ${rootfs_path}/lib
/security
/pam_loginuid.so
]
198 ( cd ${rootfs_path}/lib
/security
/
199 mv pam_loginuid.so pam_loginuid.so.disabled
200 ln -s pam_permit.so pam_loginuid.so
204 if [ -f ${rootfs_path}/lib64
/security
/pam_loginuid.so
]
206 ( cd ${rootfs_path}/lib64
/security
/
207 mv pam_loginuid.so pam_loginuid.so.disabled
208 ln -s pam_permit.so pam_loginuid.so
212 # Set default localtime to the host localtime if not set...
213 if [ -e /etc
/localtime
-a ! -e ${rootfs_path}/etc
/localtime
]
215 # if /etc/localtime is a symlink, this should preserve it.
216 cp -a /etc
/localtime
${rootfs_path}/etc
/localtime
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.
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
]
231 sed -e '/hwclock/,$d' \
232 < ${rootfs_path}/etc
/init.d
/halt \
233 > ${rootfs_path}/etc
/init.d
/lxc-halt
235 echo '$command -f' >> ${rootfs_path}/etc
/init.d
/lxc-halt
236 chmod 755 ${rootfs_path}/etc
/init.d
/lxc-halt
238 # Link them into the rc directories...
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
247 # configure the network using the dhcp
248 cat <<EOF > ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0
260 cat <<EOF > ${rootfs_path}/etc/sysconfig/network
266 cat <<EOF > $rootfs_path/etc/hosts
267 127.0.0.1 localhost $name
271 cat <<EOF > $rootfs_path/etc/fstab
272 /dev/root / rootfs defaults 0 0
275 # create lxc compatibility init script
276 if [ "$release" = "6" ]; then
277 cat <<EOF > $rootfs_path/etc/init/lxc-sysinit.conf
282 if [ "x\$container" != "xlxc" -a "x\$container" != "xlibvirt" ]; then
286 rm -f /var/lock/subsys/*
288 [ -e /etc/mtab ] || ln -s /proc/mounts /etc/mtab
290 mount -t tmpfs -o nosuid,nodev tmpfs /dev/shm
292 initctl start tty TTY=console
297 elif [ "$release" = "5" ]; then
298 cat <<EOF > $rootfs_path/etc/rc.d/lxc.sysinit
300 rm -f /etc/mtab /var/run/*.{pid,lock} /var/lock/subsys/*
301 rm -rf {/,/var}/tmp/*
302 echo "/dev/root / rootfs defaults 0 0" > /etc/mtab
305 chmod 755 $rootfs_path/etc
/rc.d
/lxc.sysinit
306 sed -i 's|si::sysinit:/etc/rc.d/rc.sysinit|si::bootwait:/etc/rc.d/lxc.sysinit|' $rootfs_path/etc
/inittab
307 # prevent mingetty from calling vhangup(2) since it fails with userns.
308 # Same issue as oracle template: prevent mingetty from calling vhangup(2)
309 # commit 2e83f7201c5d402478b9849f0a85c62d5b9f1589.
310 sed -i 's|^1:|co:2345:respawn:/sbin/mingetty --nohangup console\n1:|' $rootfs_path/etc
/inittab
311 sed -i 's|^\([56]:\)|#\1|' $rootfs_path/etc
/inittab
314 dev_path
="${rootfs_path}/dev"
317 mknod
-m 666 ${dev_path}/null c
1 3
318 mknod
-m 666 ${dev_path}/zero c
1 5
319 mknod
-m 666 ${dev_path}/random c
1 8
320 mknod
-m 666 ${dev_path}/urandom c
1 9
321 mkdir
-m 755 ${dev_path}/pts
322 mkdir
-m 1777 ${dev_path}/shm
323 mknod
-m 666 ${dev_path}/tty c
5 0
324 mknod
-m 666 ${dev_path}/tty0 c
4 0
325 mknod
-m 666 ${dev_path}/tty1 c
4 1
326 mknod
-m 666 ${dev_path}/tty2 c
4 2
327 mknod
-m 666 ${dev_path}/tty3 c
4 3
328 mknod
-m 666 ${dev_path}/tty4 c
4 4
329 mknod
-m 600 ${dev_path}/console c
5 1
330 mknod
-m 666 ${dev_path}/full c
1 7
331 mknod
-m 600 ${dev_path}/initctl p
332 mknod
-m 666 ${dev_path}/ptmx c
5 2
334 # setup console and tty[1-4] for login. note that /dev/console and
335 # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and
336 # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks.
337 # lxc will maintain these links and bind mount ptys over /dev/lxc/*
338 # since lxc.devttydir is specified in the config.
340 # allow root login on console, tty[1-4], and pts/0 for libvirt
341 echo "# LXC (Linux Containers)" >>${rootfs_path}/etc
/securetty
342 echo "lxc/console" >>${rootfs_path}/etc
/securetty
343 echo "lxc/tty1" >>${rootfs_path}/etc
/securetty
344 echo "lxc/tty2" >>${rootfs_path}/etc
/securetty
345 echo "lxc/tty3" >>${rootfs_path}/etc
/securetty
346 echo "lxc/tty4" >>${rootfs_path}/etc
/securetty
347 echo "# For libvirt/Virtual Machine Monitor" >>${rootfs_path}/etc
/securetty
348 echo "pts/0" >>${rootfs_path}/etc
/securetty
350 # prevent mingetty from calling vhangup(2) since it fails with userns.
351 # Same issue as oracle template: prevent mingetty from calling vhangup(2)
352 # commit 2e83f7201c5d402478b9849f0a85c62d5b9f1589.
353 sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc
/init
/tty.conf
355 if [ ${root_display_password} = "yes" ]
357 echo "Setting root password to '$root_password'"
359 if [ ${root_store_password} = "yes" ]
361 touch ${config_path}/tmp_root_pass
362 chmod 600 ${config_path}/tmp_root_pass
363 echo ${root_password} > ${config_path}/tmp_root_pass
364 echo "Storing root password in '${config_path}/tmp_root_pass'"
367 echo "root:$root_password" | chroot
$rootfs_path chpasswd
369 if [ ${root_expire_password} = "yes" ]
371 # Also set this password as expired to force the user to change it!
372 chroot
$rootfs_path passwd
-e root
375 # This will need to be enhanced for CentOS 7 when systemd
376 # comes into play... /\/\|=mhw=|\/\/
381 configure_centos_init
()
383 sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc
/rc.sysinit
384 sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc
/rc.d
/rc.sysinit
385 if [ "$release" = "6" ]; then
386 chroot
${rootfs_path} chkconfig udev-post off
388 chroot
${rootfs_path} chkconfig network on
390 if [ -d ${rootfs_path}/etc
/init
]
392 # This is to make upstart honor SIGPWR
393 cat <<EOF >${rootfs_path}/etc/init/power-status-changed.conf
394 # power-status-changed - shutdown on SIGPWR
396 start on power-status-changed
398 exec /sbin/shutdown -h now "SIGPWR received"
406 # check the mini centos was not already downloaded
407 INSTALL_ROOT
=$cache/partial
408 mkdir
-p $INSTALL_ROOT
409 if [ $?
-ne 0 ]; then
410 echo "Failed to create '$INSTALL_ROOT' directory"
414 # download a mini centos into a cache
415 echo "Downloading centos minimal ..."
416 if [ $release -le 5 ];then
417 YUM
="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
419 YUM
="yum --installroot $INSTALL_ROOT -y --nogpgcheck --releasever=$release"
421 PKG_LIST
="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils"
423 # use temporary repository definition
424 REPO_FILE
=$INSTALL_ROOT/etc
/yum.repos.d
/lxc-centos-temp.repo
425 mkdir
-p $
(dirname $REPO_FILE)
426 if [ -n "$repo" ]; then
427 cat <<EOF > $REPO_FILE
429 name=local repository
433 cat <<EOF > $REPO_FILE
435 name=CentOS-$release - Base
436 mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=os
439 name=CentOS-$release - Updates
440 mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=updates
444 # create minimal device nodes, needed for "yum install" and "yum update" process
445 mkdir
-p $INSTALL_ROOT/dev
446 force_mknod
666 $INSTALL_ROOT/dev
/null c
1 3
447 force_mknod
666 $INSTALL_ROOT/dev
/urandom c
1 9
449 $YUM install $PKG_LIST
451 if [ $?
-ne 0 ]; then
452 echo "Failed to download the rootfs, aborting."
456 # use same nameservers as hosts, needed for "yum update later"
457 cp /etc
/resolv.conf
$INSTALL_ROOT/etc
/
459 # check whether rpmdb is under $HOME
460 if [ ! -e $INSTALL_ROOT/var
/lib
/rpm
/Packages
-a -e $INSTALL_ROOT/$HOME/.rpmdb
/Packages
]; then
461 echo "Fixing rpmdb location ..."
462 mv $INSTALL_ROOT/$HOME/.rpmdb
/[A-Z
]* $INSTALL_ROOT/var
/lib
/rpm
/
463 rm -rf $INSTALL_ROOT/$HOME/.rpmdb
464 chroot
$INSTALL_ROOT rpm
--rebuilddb 2>/dev
/null
467 # check whether rpmdb version is correct
468 chroot
$INSTALL_ROOT rpm
--quiet -q yum
2>/dev
/null
471 # if "rpm -q" doesn't work due to rpmdb version difference,
472 # then we need to redo the process using the newly-installed yum
473 if [ $ret -gt 0 ]; then
474 echo "Reinstalling packages ..."
475 mv $REPO_FILE $REPO_FILE.tmp
476 mkdir
$INSTALL_ROOT/etc
/yum.repos.disabled
477 mv $INSTALL_ROOT/etc
/yum.repos.d
/*.repo
$INSTALL_ROOT/etc
/yum.repos.disabled
/
478 mv $REPO_FILE.tmp
$REPO_FILE
479 mkdir
-p $INSTALL_ROOT/$INSTALL_ROOT/etc
480 cp /etc
/resolv.conf
$INSTALL_ROOT/$INSTALL_ROOT/etc
/
481 mkdir
-p $INSTALL_ROOT/$INSTALL_ROOT/dev
482 mknod
-m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev
/null c
1 3
483 mknod
-m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev
/urandom c
1 9
484 mkdir
-p $INSTALL_ROOT/$INSTALL_ROOT/var
/cache
/yum
485 cp -al $INSTALL_ROOT/var
/cache
/yum
/* $INSTALL_ROOT/$INSTALL_ROOT/var
/cache
/yum
/
486 chroot
$INSTALL_ROOT $YUM install $PKG_LIST
487 if [ $?
-ne 0 ]; then
488 echo "Failed to download the rootfs, aborting."
491 mv $INSTALL_ROOT/$INSTALL_ROOT $INSTALL_ROOT.tmp
493 mv $INSTALL_ROOT.tmp
$INSTALL_ROOT
497 rm -rf $INSTALL_ROOT/var
/cache
/yum
/*
499 mv "$INSTALL_ROOT" "$cache/rootfs"
500 echo "Download complete."
508 # make a local copy of the mini centos
509 echo -n "Copying rootfs to $rootfs_path ..."
510 #cp -a $cache/rootfs-$arch $rootfs_path || return 1
511 # i prefer rsync (no reason really)
512 mkdir
-p $rootfs_path
513 rsync
-a $cache/rootfs
/ $rootfs_path/
520 YUM
="chroot $cache/rootfs yum -y --nogpgcheck"
522 if [ $?
-ne 0 ]; then
530 mkdir
-p /var
/lock
/subsys
/
533 if [ $?
-ne 0 ]; then
534 echo "Cache repository is busy."
538 echo "Checking cache download in $cache/rootfs ... "
539 if [ ! -e "$cache/rootfs" ]; then
541 if [ $?
-ne 0 ]; then
542 echo "Failed to download 'centos base'"
546 echo "Cache found. Updating..."
548 if [ $?
-ne 0 ]; then
549 echo "Failed to update 'centos base', continuing with last known good cache"
551 echo "Update finished"
555 echo "Copy $cache/rootfs to $rootfs_path ... "
557 if [ $?
-ne 0 ]; then
558 echo "Failed to copy rootfs"
564 ) 9>/var
/lock
/subsys
/lxc-centos
571 openssl rand
-hex 5 |
sed -e 's/\(..\)/:\1/g; s/^/fe/'
576 mkdir
-p $config_path
578 grep -q "^lxc.rootfs" $config_path/config
2>/dev
/null ||
echo "
579 lxc.rootfs = $rootfs_path
580 " >> $config_path/config
582 # The following code is to create static MAC addresses for each
583 # interface in the container. This code will work for multiple
584 # interfaces in the default config.
585 mv $config_path/config
$config_path/config.def
588 # This should catch variable expansions from the default config...
589 if expr "${LINE}" : '.*\$' > /dev
/null
2>&1
591 LINE
=$
(eval "echo \"${LINE}\"")
594 # There is a tab and a space in the regex bracket below!
595 # Seems that \s doesn't work in brackets.
596 KEY
=$
(expr "${LINE}" : '\s*\([^ ]*\)\s*=')
598 if [[ "${KEY}" != "lxc.network.hwaddr" ]]
600 echo ${LINE} >> $config_path/config
602 if [[ "${KEY}" == "lxc.network.link" ]]
604 echo "lxc.network.hwaddr = $(create_hwaddr)" >> $config_path/config
607 done < $config_path/config.def
609 rm -f $config_path/config.def
611 if [ -e "@LXCTEMPLATECONFIG@/centos.common.conf" ]; then
613 # Include common configuration
614 lxc.include = @LXCTEMPLATECONFIG@/centos.common.conf
615 " >> $config_path/config
618 # Append things which require expansion here...
619 cat <<EOF >> $config_path/config
621 lxc.utsname = $utsname
623 # When using LXC with apparmor, uncomment the next line to run unconfined:
624 #lxc.aa_profile = unconfined
626 # example simple networking setup, uncomment to enable
627 #lxc.network.type = $lxc_network_type
628 #lxc.network.flags = up
629 #lxc.network.link = $lxc_network_link
630 #lxc.network.name = eth0
631 # Additional example for veth network type
632 # static MAC address,
633 #lxc.network.hwaddr = 00:16:3e:77:52:20
634 # persistent veth device name on host side
635 # Note: This may potentially collide with other containers of same name!
636 #lxc.network.veth.pair = v-$name-e0
640 if [ $?
-ne 0 ]; then
641 echo "Failed to add configuration"
651 if [ ! -e $cache ]; then
655 # lock, so we won't purge while someone is creating a repository
659 echo "Cache repository is busy."
663 echo -n "Purging the download cache for centos-$release..."
664 rm --preserve-root --one-file-system -rf $cache && echo "Done." ||
exit 1
667 ) 9>@LOCALSTATEDIR@
/lock
/subsys
/lxc-centos
674 $1 -n|--name=<container_name>
675 [-p|--path=<path>] [-c|--clean] [-R|--release=<CentOS_release>] [-a|--arch=<arch of the container>]
678 -n,--name container name, used to as an identifier for that container from now on
680 -p,--path path to where the container rootfs will be created, defaults to /var/lib/lxc/name.
681 -c,--clean clean the cache
682 -R,--release Centos release for the new container. if the host is Centos, then it will defaultto the host's release.
683 --fqdn fully qualified domain name (FQDN) for DNS and system naming
684 --repo repository to use (url)
685 -a,--arch Define what arch the container will be [i686,x86_64]
686 -h,--help print this help
691 options
=$
(getopt
-o a
:hp
:n
:cR
: -l help,path
:,rootfs
:,name
:,clean
,release
:,repo
:,arch
:,fqdn
: -- "$@")
692 if [ $?
-ne 0 ]; then
698 eval set -- "$options"
702 -h|
--help) usage
$0 && exit 0;;
703 -p|
--path) path
=$2; shift 2;;
704 --rootfs) rootfs_path
=$2; shift 2;;
705 -n|
--name) name
=$2; shift 2;;
706 -c|
--clean) clean
=1; shift 1;;
707 -R|
--release) release
=$2; shift 2;;
708 --repo) repo
="$2"; shift 2;;
709 -a|
--arch) newarch
=$2; shift 2;;
710 --fqdn) utsname
=$2; shift 2;;
711 --) shift 1; break ;;
716 if [ ! -z "$clean" -a -z "$path" ]; then
722 # Map a few architectures to their generic CentOS repository archs.
723 # The two ARM archs are a bit of a guesstimate for the v5 and v6
724 # archs. V6 should have hardware floating point (Rasberry Pi).
725 # The "arm" arch is safer (no hardware floating point). So
726 # there may be cases where we "get it wrong" for some v6 other
729 i686
) basearch
=i386
;;
730 armv3l|armv4l|armv5l
) basearch
=arm
;;
731 armv6l|armv7l|armv8l
) basearch
=armhfp
;;
735 # Somebody wants to specify an arch. This is very limited case.
736 # i386/i586/i686 on i386/x86_64
739 if [ "${newarch}" != "" -a "${newarch}" != "${arch}" ]
743 if [ "${basearch}" = "i386" -o "${basearch}" = "x86_64" ]
745 # Make the arch a generic x86 32 bit...
757 if [ "${basearch}" = "bad" ]
759 echo "You cannot build a ${newarch} CentOS container on a ${arch} host. Sorry!"
764 cache_base
=@LOCALSTATEDIR@
/cache
/lxc
/centos
/$basearch
766 # Let's do something better for the initial root password.
767 # It's not perfect but it will defeat common scanning brute force
768 # attacks in the case where ssh is exposed. It will also be set to
769 # expired, forcing the user to change it at first login.
770 if [ "${root_password}" = "" ]
772 root_password
=Root-
${name}-${RANDOM}
774 # If it's got a ding in it, try and expand it!
775 if [ $
(expr "${root_password}" : '.*$.') != 0 ]
777 root_password
=$
(eval echo "${root_password}")
780 # If it has more than 3 consecutive X's in it, feed it
781 # through mktemp as a template.
782 if [ $
(expr "${root_password}" : '.*XXXX') != 0 ]
784 root_password
=$
(mktemp
-u ${root_password})
788 if [ -z "${utsname}" ]; then
792 # This follows a standard "resolver" convention that an FQDN must have
793 # at least two dots or it is considered a local relative host name.
794 # If it doesn't, append the dns domain name of the host system.
796 # This changes one significant behavior when running
797 # "lxc_create -n Container_Name" without using the
801 # utsname and hostname = Container_Name
803 # utsname and hostname = Container_Name.Domain_Name
805 if [ $
(expr "$utsname" : '.*\..*\.') = 0 ]; then
806 if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then
807 utsname
=${utsname}.$
(dnsdomainname
)
811 type yum
>/dev
/null
2>&1
812 if [ $?
-ne 0 ]; then
813 echo "'yum' command is missing"
817 if [ -z "$path" ]; then
818 path
=$default_path/$name
821 if [ -z "$release" ]; then
822 if [ "$is_centos" -a "$centos_host_ver" ]; then
823 release
=$centos_host_ver
824 elif [ "$is_redhat" -a "$redhat_host_ver" ]; then
825 # This is needed to clean out bullshit like 6workstation and 6server.
826 release
=$
(expr $redhat_host_ver : '\([0-9.]*\)')
828 echo "This is not a CentOS or Redhat host and release is missing, defaulting to 6 use -R|--release to specify release"
833 if [ "$(id -u)" != "0" ]; then
834 echo "This script should be run as 'root'"
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
)
847 cache
=$cache_base/$release
851 echo "Interrupted, so cleaning up"
853 # maybe was interrupted before copy config
859 trap revert SIGHUP SIGINT SIGTERM
862 if [ $?
-ne 0 ]; then
863 echo "failed write configuration file"
868 if [ $?
-ne 0 ]; then
869 echo "failed to install centos"
874 if [ $?
-ne 0 ]; then
875 echo "failed to configure centos for a container"
879 configure_centos_init
881 if [ ! -z "$clean" ]; then
886 Container rootfs and config have been created.
887 Edit the config file to check/enable networking setup.
890 if [ ${root_display_password} = "yes" ]
892 echo "The temporary password for root is: '$root_password'
894 You may want to note that password down before starting the container.
898 if [ ${root_store_password} = "yes" ]
900 echo "The temporary root password is stored in:
902 '${config_path}/tmp_root_pass'
906 if [ ${root_prompt_password} = "yes" ]
908 echo "Invoking the passwd command in the container to set the root password.
910 chroot ${rootfs_path} passwd
912 chroot
${rootfs_path} passwd
914 if [ ${root_expire_password} = "yes" ]
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):
923 chroot ${rootfs_path} passwd