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" -o "${ID}" = "rhel" -a "${VERSION_ID}" != "" ]
142 # RHEL 7+ /etc/os-release ID = 'rhel', which doesn't enter this elif without the added OR statement
143 redhat_host_ver
=${VERSION_ID}
145 elif [ -e /etc
/centos-release
]
147 # Only if all other methods fail, try to parse the redhat-release file.
148 centos_host_ver
=$
( sed -e '/^CentOS /!d' -e 's/CentOS.*\srelease\s*\([0-9][0-9.]*\)\s.*/\1/' < /etc
/centos-release
)
149 if [ "$centos_host_ver" != "" ]
157 # delete a device node if exists, and create a new one
158 rm -f $2 && mknod
-m $1 $2 $3 $4 $5
164 # disable selinux in CentOS
165 mkdir
-p $rootfs_path/selinux
166 echo 0 > $rootfs_path/selinux
/enforce
168 # Also kill it in the /etc/selinux/config file if it's there...
169 if [ -f $rootfs_path/etc
/selinux
/config
]
171 sed -i '/^SELINUX=/s/.*/SELINUX=disabled/' $rootfs_path/etc
/selinux
/config
174 # Nice catch from Dwight Engen in the Oracle template.
175 # Wantonly plagerized here with much appreciation.
176 if [ -f $rootfs_path/usr
/sbin
/selinuxenabled
]; then
177 mv $rootfs_path/usr
/sbin
/selinuxenabled
$rootfs_path/usr
/sbin
/selinuxenabled.lxcorig
178 ln -s /bin
/false
$rootfs_path/usr
/sbin
/selinuxenabled
181 # This is a known problem and documented in RedHat bugzilla as relating
182 # to a problem with auditing enabled. This prevents an error in
183 # the container "Cannot make/remove an entry for the specified session"
184 sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc
/pam.d
/login
185 sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc
/pam.d
/sshd
187 if [ -f ${rootfs_path}/etc
/pam.d
/crond
]
189 sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc
/pam.d
/crond
192 # In addition to disabling pam_loginuid in the above config files
193 # we'll also disable it by linking it to pam_permit to catch any
194 # we missed or any that get installed after the container is built.
196 # Catch either or both 32 and 64 bit archs.
197 if [ -f ${rootfs_path}/lib
/security
/pam_loginuid.so
]
199 ( cd ${rootfs_path}/lib
/security
/
200 mv pam_loginuid.so pam_loginuid.so.disabled
201 ln -s pam_permit.so pam_loginuid.so
205 if [ -f ${rootfs_path}/lib64
/security
/pam_loginuid.so
]
207 ( cd ${rootfs_path}/lib64
/security
/
208 mv pam_loginuid.so pam_loginuid.so.disabled
209 ln -s pam_permit.so pam_loginuid.so
213 # Set default localtime to the host localtime if not set...
214 if [ -e /etc
/localtime
-a ! -e ${rootfs_path}/etc
/localtime
]
216 # if /etc/localtime is a symlink, this should preserve it.
217 cp -a /etc
/localtime
${rootfs_path}/etc
/localtime
220 # Deal with some dain bramage in the /etc/init.d/halt script.
221 # Trim it and make it our own and link it in before the default
222 # halt script so we can intercept it. This also preventions package
223 # updates from interferring with our interferring with it.
225 # There's generally not much in the halt script that useful but what's
226 # in there from resetting the hardware clock down is generally very bad.
227 # So we just eliminate the whole bottom half of that script in making
228 # ourselves a copy. That way a major update to the init scripts won't
229 # trash what we've set up.
230 if [ -f ${rootfs_path}/etc
/init.d
/halt
]
232 sed -e '/hwclock/,$d' \
233 < ${rootfs_path}/etc
/init.d
/halt \
234 > ${rootfs_path}/etc
/init.d
/lxc-halt
236 echo '$command -f' >> ${rootfs_path}/etc
/init.d
/lxc-halt
237 chmod 755 ${rootfs_path}/etc
/init.d
/lxc-halt
239 # Link them into the rc directories...
241 cd ${rootfs_path}/etc
/rc.d
/rc0.d
242 ln -s ..
/init.d
/lxc-halt S00lxc-halt
243 cd ${rootfs_path}/etc
/rc.d
/rc6.d
244 ln -s ..
/init.d
/lxc-halt S00lxc-reboot
248 # configure the network using the dhcp
249 cat <<EOF > ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0
257 DHCP_HOSTNAME=\`hostname\`
261 cat <<EOF > ${rootfs_path}/etc/sysconfig/network
267 cat <<EOF > $rootfs_path/etc/hosts
268 127.0.0.1 localhost $name
272 cat <<EOF > $rootfs_path/etc/fstab
273 /dev/root / rootfs defaults 0 0
276 # create lxc compatibility init script
277 if [ "$release" = "6" ]; then
278 cat <<EOF > $rootfs_path/etc/init/lxc-sysinit.conf
283 if [ "x\$container" != "xlxc" -a "x\$container" != "xlibvirt" ]; then
287 rm -f /var/lock/subsys/*
289 [ -e /etc/mtab ] || ln -s /proc/mounts /etc/mtab
291 mount -t tmpfs -o nosuid,nodev tmpfs /dev/shm
293 initctl start tty TTY=console
298 elif [ "$release" = "5" ]; then
299 cat <<EOF > $rootfs_path/etc/rc.d/lxc.sysinit
301 rm -f /etc/mtab /var/run/*.{pid,lock} /var/lock/subsys/*
302 rm -rf {/,/var}/tmp/*
303 echo "/dev/root / rootfs defaults 0 0" > /etc/mtab
306 chmod 755 $rootfs_path/etc
/rc.d
/lxc.sysinit
307 sed -i 's|si::sysinit:/etc/rc.d/rc.sysinit|si::bootwait:/etc/rc.d/lxc.sysinit|' $rootfs_path/etc
/inittab
308 # prevent mingetty from calling vhangup(2) since it fails with userns.
309 # Same issue as oracle template: prevent mingetty from calling vhangup(2)
310 # commit 2e83f7201c5d402478b9849f0a85c62d5b9f1589.
311 sed -i 's|^1:|co:2345:respawn:/sbin/mingetty --nohangup console\n1:|' $rootfs_path/etc
/inittab
312 sed -i 's|^\([56]:\)|#\1|' $rootfs_path/etc
/inittab
315 dev_path
="${rootfs_path}/dev"
318 mknod
-m 666 ${dev_path}/null c
1 3
319 mknod
-m 666 ${dev_path}/zero c
1 5
320 mknod
-m 666 ${dev_path}/random c
1 8
321 mknod
-m 666 ${dev_path}/urandom c
1 9
322 mkdir
-m 755 ${dev_path}/pts
323 mkdir
-m 1777 ${dev_path}/shm
324 mknod
-m 666 ${dev_path}/tty c
5 0
325 mknod
-m 666 ${dev_path}/tty0 c
4 0
326 mknod
-m 666 ${dev_path}/tty1 c
4 1
327 mknod
-m 666 ${dev_path}/tty2 c
4 2
328 mknod
-m 666 ${dev_path}/tty3 c
4 3
329 mknod
-m 666 ${dev_path}/tty4 c
4 4
330 mknod
-m 600 ${dev_path}/console c
5 1
331 mknod
-m 666 ${dev_path}/full c
1 7
332 mknod
-m 600 ${dev_path}/initctl p
333 mknod
-m 666 ${dev_path}/ptmx c
5 2
335 # setup console and tty[1-4] for login. note that /dev/console and
336 # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and
337 # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks.
338 # lxc will maintain these links and bind mount ptys over /dev/lxc/*
339 # since lxc.tty.dir is specified in the config.
341 # allow root login on console, tty[1-4], and pts/0 for libvirt
342 echo "# LXC (Linux Containers)" >>${rootfs_path}/etc
/securetty
343 echo "lxc/console" >>${rootfs_path}/etc
/securetty
344 echo "lxc/tty1" >>${rootfs_path}/etc
/securetty
345 echo "lxc/tty2" >>${rootfs_path}/etc
/securetty
346 echo "lxc/tty3" >>${rootfs_path}/etc
/securetty
347 echo "lxc/tty4" >>${rootfs_path}/etc
/securetty
348 echo "# For libvirt/Virtual Machine Monitor" >>${rootfs_path}/etc
/securetty
349 echo "pts/0" >>${rootfs_path}/etc
/securetty
351 # prevent mingetty from calling vhangup(2) since it fails with userns.
352 # Same issue as oracle template: prevent mingetty from calling vhangup(2)
353 # commit 2e83f7201c5d402478b9849f0a85c62d5b9f1589.
354 sed -i 's|mingetty|mingetty --nohangup|' $rootfs_path/etc
/init
/tty.conf
356 if [ ${root_display_password} = "yes" ]
358 echo "Setting root password to '$root_password'"
360 if [ ${root_store_password} = "yes" ]
362 touch ${config_path}/tmp_root_pass
363 chmod 600 ${config_path}/tmp_root_pass
364 echo ${root_password} > ${config_path}/tmp_root_pass
365 echo "Storing root password in '${config_path}/tmp_root_pass'"
368 echo "root:$root_password" | chroot
$rootfs_path chpasswd
370 if [ ${root_expire_password} = "yes" ]
372 # Also set this password as expired to force the user to change it!
373 chroot
$rootfs_path passwd
-e root
376 # This will need to be enhanced for CentOS 7 when systemd
377 # comes into play... /\/\|=mhw=|\/\/
382 configure_centos_init
()
384 sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc
/rc.sysinit
385 sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc
/rc.d
/rc.sysinit
386 if [ "$release" = "6" ]; then
387 chroot
${rootfs_path} chkconfig udev-post off
389 chroot
${rootfs_path} chkconfig network on
391 if [ -d ${rootfs_path}/etc
/init
]
393 # This is to make upstart honor SIGPWR
394 cat <<EOF >${rootfs_path}/etc/init/power-status-changed.conf
395 # power-status-changed - shutdown on SIGPWR
397 start on power-status-changed
399 exec /sbin/shutdown -h now "SIGPWR received"
407 # check the mini CentOS was not already downloaded
408 INSTALL_ROOT
=$cache/partial
409 mkdir
-p $INSTALL_ROOT
410 if [ $?
-ne 0 ]; then
411 echo "Failed to create '$INSTALL_ROOT' directory"
415 # download a mini CentOS into a cache
416 echo "Downloading CentOS minimal ..."
417 YUM0
="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
419 if yum
-h |
grep -q 'releasever=RELEASEVER'; then
420 YUM
="$YUM0 --releasever=$release"
424 PKG_LIST
="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils cronie"
426 # use temporary repository definition
427 # always prefer the repo given by the user
428 # if no repo given, use mirrorlist.centos.org for i386 and x86_64
429 # and http://mirror.centos.org/altarch/ otherwise
430 REPO_FILE
=$INSTALL_ROOT/etc
/yum.repos.d
/lxc-centos-temp.repo
431 mkdir
-p $
(dirname $REPO_FILE)
432 if [ -n "$repo" ]; then
433 cat <<EOF > $REPO_FILE
435 name=local repository
438 elif [ ${basearch} = 'i386' ] ||
[ ${basearch} = 'x86_64' ]; then
439 cat <<EOF > $REPO_FILE
441 name=CentOS-$release - Base
442 mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=os
445 name=CentOS-$release - Updates
446 mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=updates
449 cat <<EOF > $REPO_FILE
451 name=CentOS-$release - Base
452 baseurl=http://mirror.centos.org/altarch/7/os/$basearch/
455 name=CentOS-$release - Updates
456 baseurl=http://mirror.centos.org/altarch/7/updates/$basearch/
460 # create minimal device nodes, needed for "yum install" and "yum update" process
461 mkdir
-p $INSTALL_ROOT/dev
462 force_mknod
666 $INSTALL_ROOT/dev
/null c
1 3
463 force_mknod
666 $INSTALL_ROOT/dev
/urandom c
1 9
465 $YUM install $PKG_LIST
467 # create symlink for /var/run -> ../run
468 if [ "$release" = "7" ]; then
469 mv $INSTALL_ROOT/var
/run
/* $INSTALL_ROOT/run
/
470 rmdir $INSTALL_ROOT/var
/run
471 ln -sf ..
/run
$INSTALL_ROOT/var
/run
474 if [ $?
-ne 0 ]; then
475 echo "Failed to download the rootfs, aborting."
479 # use same nameservers as hosts, needed for "yum update later"
480 cp /etc
/resolv.conf
$INSTALL_ROOT/etc
/
482 # check whether rpmdb is under $HOME
483 if [ ! -e $INSTALL_ROOT/var
/lib
/rpm
/Packages
-a -e $INSTALL_ROOT/$HOME/.rpmdb
/Packages
]; then
484 echo "Fixing rpmdb location ..."
485 mv $INSTALL_ROOT/$HOME/.rpmdb
/[A-Z
]* $INSTALL_ROOT/var
/lib
/rpm
/
486 rm -rf $INSTALL_ROOT/$HOME/.rpmdb
487 chroot
$INSTALL_ROOT rpm
--rebuilddb 2>/dev
/null
490 # check whether rpmdb version is correct
491 chroot
$INSTALL_ROOT rpm
--quiet -q yum
2>/dev
/null
494 # if "rpm -q" doesn't work due to rpmdb version difference,
495 # then we need to redo the process using the newly-installed yum
496 if [ $ret -gt 0 ]; then
497 echo "Reinstalling packages ..."
498 mv $REPO_FILE $REPO_FILE.tmp
499 mkdir
$INSTALL_ROOT/etc
/yum.repos.disabled
500 mv $INSTALL_ROOT/etc
/yum.repos.d
/*.repo
$INSTALL_ROOT/etc
/yum.repos.disabled
/
501 mv $REPO_FILE.tmp
$REPO_FILE
502 mkdir
-p $INSTALL_ROOT/$INSTALL_ROOT/etc
503 cp /etc
/resolv.conf
$INSTALL_ROOT/$INSTALL_ROOT/etc
/
504 mkdir
-p $INSTALL_ROOT/$INSTALL_ROOT/dev
505 mknod
-m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev
/null c
1 3
506 mknod
-m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev
/urandom c
1 9
507 mkdir
-p $INSTALL_ROOT/$INSTALL_ROOT/var
/cache
/yum
508 cp -al $INSTALL_ROOT/var
/cache
/yum
/* $INSTALL_ROOT/$INSTALL_ROOT/var
/cache
/yum
/
509 chroot
$INSTALL_ROOT $YUM0 install $PKG_LIST
510 if [ $?
-ne 0 ]; then
511 echo "Failed to download the rootfs, aborting."
514 mv $INSTALL_ROOT/$INSTALL_ROOT $INSTALL_ROOT.tmp
516 mv $INSTALL_ROOT.tmp
$INSTALL_ROOT
520 rm -rf $INSTALL_ROOT/var
/cache
/yum
/*
522 mv "$INSTALL_ROOT" "$cache/rootfs"
523 echo "Download complete."
531 # make a local copy of the mini CentOS
532 echo -n "Copying rootfs to $rootfs_path ..."
533 #cp -a $cache/rootfs-$arch $rootfs_path || return 1
534 # i prefer rsync (no reason really)
535 mkdir
-p $rootfs_path
536 rsync
-a $cache/rootfs
/ $rootfs_path/
543 YUM
="chroot $cache/rootfs yum -y --nogpgcheck"
545 if [ $?
-ne 0 ]; then
553 mkdir
-p /var
/lock
/subsys
/
556 if [ $?
-ne 0 ]; then
557 echo "Cache repository is busy."
561 echo "Checking cache download in $cache/rootfs ... "
562 if [ ! -e "$cache/rootfs" ]; then
564 if [ $?
-ne 0 ]; then
565 echo "Failed to download 'CentOS base'"
569 echo "Cache found. Updating..."
571 if [ $?
-ne 0 ]; then
572 echo "Failed to update 'CentOS base', continuing with last known good cache"
574 echo "Update finished"
578 echo "Copy $cache/rootfs to $rootfs_path ... "
580 if [ $?
-ne 0 ]; then
581 echo "Failed to copy rootfs"
587 ) 9>/var
/lock
/subsys
/lxc-centos
594 openssl rand
-hex 5 |
sed -e 's/\(..\)/:\1/g; s/^/fe/'
599 mkdir
-p $config_path
601 grep -q "^lxc.rootfs.path" $config_path/config
2>/dev
/null ||
echo "
602 lxc.rootfs.path = $rootfs_path
603 " >> $config_path/config
605 # The following code is to create static MAC addresses for each
606 # interface in the container. This code will work for multiple
607 # interfaces in the default config.
608 mv $config_path/config
$config_path/config.def
611 # This should catch variable expansions from the default config...
612 if expr "${LINE}" : '.*\$' > /dev
/null
2>&1
614 LINE
=$
(eval "echo \"${LINE}\"")
617 # There is a tab and a space in the regex bracket below!
618 # Seems that \s doesn't work in brackets.
619 KEY
=$
(expr "${LINE}" : '\s*\([^ ]*\)\s*=')
621 if [[ "${KEY}" != "lxc.net.0.hwaddr" ]]
623 echo ${LINE} >> $config_path/config
625 if [[ "${KEY}" == "lxc.net.0.link" ]]
627 echo "lxc.net.0.hwaddr = $(create_hwaddr)" >> $config_path/config
630 done < $config_path/config.def
632 rm -f $config_path/config.def
634 if [ -e "@LXCTEMPLATECONFIG@/centos.common.conf" ]; then
636 # Include common configuration
637 lxc.include = @LXCTEMPLATECONFIG@/centos.common.conf
638 " >> $config_path/config
641 # Append things which require expansion here...
642 cat <<EOF >> $config_path/config
644 lxc.uts.name = $utsname
646 # When using LXC with apparmor, uncomment the next line to run unconfined:
647 #lxc.apparmor.profile = unconfined
649 # example simple networking setup, uncomment to enable
650 #lxc.net.0.type = $lxc_network_type
651 #lxc.net.0.flags = up
652 #lxc.net.0.link = $lxc_network_link
653 #lxc.net.0.name = eth0
654 # Additional example for veth network type
655 # static MAC address,
656 #lxc.net.0.hwaddr = 00:16:3e:77:52:20
657 # persistent veth device name on host side
658 # Note: This may potentially collide with other containers of same name!
659 #lxc.net.0.veth.pair = v-$name-e0
663 if [ $?
-ne 0 ]; then
664 echo "Failed to add configuration"
674 if [ ! -e $cache ]; then
678 # lock, so we won't purge while someone is creating a repository
682 echo "Cache repository is busy."
686 echo -n "Purging the download cache for CentOS-$release..."
687 rm --preserve-root --one-file-system -rf $cache && echo "Done." ||
exit 1
690 ) 9>@LOCALSTATEDIR@
/lock
/subsys
/lxc-centos
697 $1 -n|--name=<container_name>
698 [-p|--path=<path>] [-c|--clean] [-R|--release=<CentOS_release>] [-a|--arch=<arch of the container>]
701 -n,--name container name, used to as an identifier for that container from now on
703 -p,--path path to where the container rootfs will be created, defaults to /var/lib/lxc/name.
704 -c,--clean clean the cache
705 -R,--release CentOS release for the new container. If the host is CentOS, then it will default to the host's release.
706 --fqdn fully qualified domain name (FQDN) for DNS and system naming
707 --repo repository to use (url)
708 -a,--arch Define what arch the container will be [i686,x86_64]
709 -h,--help print this help
714 options
=$
(getopt
-o a
:hp
:n
:cR
: -l help,path
:,rootfs
:,name
:,clean
,release
:,repo
:,arch
:,fqdn
: -- "$@")
715 if [ $?
-ne 0 ]; then
721 eval set -- "$options"
725 -h|
--help) usage
$0 && exit 0;;
726 -p|
--path) path
=$2; shift 2;;
727 --rootfs) rootfs_path
=$2; shift 2;;
728 -n|
--name) name
=$2; shift 2;;
729 -c|
--clean) clean
=1; shift 1;;
730 -R|
--release) release
=$2; shift 2;;
731 --repo) repo
="$2"; shift 2;;
732 -a|
--arch) newarch
=$2; shift 2;;
733 --fqdn) utsname
=$2; shift 2;;
734 --) shift 1; break ;;
739 if [ ! -z "$clean" -a -z "$path" ]; then
745 # Map a few architectures to their generic CentOS repository archs.
746 # The two ARM archs are a bit of a guesstimate for the v5 and v6
747 # archs. V6 should have hardware floating point (Rasberry Pi).
748 # The "arm" arch is safer (no hardware floating point). So
749 # there may be cases where we "get it wrong" for some v6 other
752 i686
) basearch
=i386
;;
753 armv3l|armv4l|armv5l
) basearch
=arm
;;
754 armv6l|armv7l|armv8l
) basearch
=armhfp
;;
758 # Somebody wants to specify an arch. This is very limited case.
759 # i386/i586/i686 on i386/x86_64
762 if [ "${newarch}" != "" -a "${newarch}" != "${arch}" ]
766 if [ "${basearch}" = "i386" -o "${basearch}" = "x86_64" ]
768 # Make the arch a generic x86 32 bit...
780 if [ "${basearch}" = "bad" ]
782 echo "You cannot build a ${newarch} CentOS container on a ${arch} host. Sorry!"
787 # Allow the cache base to be set by environment variable
788 cache_base
=${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc"}/centos
/$basearch
790 # Let's do something better for the initial root password.
791 # It's not perfect but it will defeat common scanning brute force
792 # attacks in the case where ssh is exposed. It will also be set to
793 # expired, forcing the user to change it at first login.
794 if [ "${root_password}" = "" ]
796 root_password
=Root-
${name}-${RANDOM}
798 # If it's got a ding in it, try and expand it!
799 if [ $
(expr "${root_password}" : '.*$.') != 0 ]
801 root_password
=$
(eval echo "${root_password}")
804 # If it has more than 3 consecutive X's in it, feed it
805 # through mktemp as a template.
806 if [ $
(expr "${root_password}" : '.*XXXX') != 0 ]
808 root_password
=$
(mktemp
-u ${root_password})
812 if [ -z "${utsname}" ]; then
816 # This follows a standard "resolver" convention that an FQDN must have
817 # at least two dots or it is considered a local relative host name.
818 # If it doesn't, append the dns domain name of the host system.
820 # This changes one significant behavior when running
821 # "lxc_create -n Container_Name" without using the
825 # utsname and hostname = Container_Name
827 # utsname and hostname = Container_Name.Domain_Name
829 if [ $
(expr "$utsname" : '.*\..*\.') = 0 ]; then
830 if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then
831 utsname
=${utsname}.$
(dnsdomainname
)
835 type yum
>/dev
/null
2>&1
836 if [ $?
-ne 0 ]; then
837 echo "'yum' command is missing"
841 if [ -z "$path" ]; then
842 path
=$default_path/$name
845 if [ -z "$release" ]; then
846 if [ "$is_centos" -a "$centos_host_ver" ]; then
847 release
=$centos_host_ver
848 elif [ "$is_redhat" -a "$redhat_host_ver" ]; then
849 # This is needed to clean out bullshit like 6workstation and 6server.
850 release
=$
(expr $redhat_host_ver : '\([0-9.]*\)')
852 echo "This is not a CentOS or Red Hat host and release is missing, defaulting to 7, use -R|--release to specify release"
857 if [ "$(id -u)" != "0" ]; then
858 echo "This script should be run as 'root'"
862 if [ -z "$rootfs_path" ]; then
863 rootfs_path
=$path/rootfs
864 # check for 'lxc.rootfs.path' passed in through default config by lxc-create
865 if grep -q '^lxc.rootfs.path' $path/config
2>/dev
/null
; then
866 rootfs_path
=$
(sed -e '/^lxc.rootfs.path\s*=/!d' -e 's/\s*#.*//' \
867 -e 's/^lxc.rootfs.path\s*=\s*//' -e q
$path/config
)
871 cache
=$cache_base/$release
875 echo "Interrupted, so cleaning up"
877 # maybe was interrupted before copy config
883 trap revert SIGHUP SIGINT SIGTERM
886 if [ $?
-ne 0 ]; then
887 echo "failed write configuration file"
892 if [ $?
-ne 0 ]; then
893 echo "failed to install CentOS"
898 if [ $?
-ne 0 ]; then
899 echo "failed to configure CentOS for a container"
903 configure_centos_init
905 if [ ! -z "$clean" ]; then
910 Container rootfs and config have been created.
911 Edit the config file to check/enable networking setup.
914 if [ ${root_display_password} = "yes" ]
916 echo "The temporary password for root is: '$root_password'
918 You may want to note that password down before starting the container.
922 if [ ${root_store_password} = "yes" ]
924 echo "The temporary root password is stored in:
926 '${config_path}/tmp_root_pass'
930 if [ ${root_prompt_password} = "yes" ]
932 echo "Invoking the passwd command in the container to set the root password.
934 chroot ${rootfs_path} passwd
936 chroot
${rootfs_path} passwd
938 if [ ${root_expire_password} = "yes" ]
940 if ( mountpoint
-q -- "${rootfs_path}" )
942 echo "To reset the root password, you can do:
945 lxc-attach -n ${name} -- passwd
950 The root password is set up as "expired
" and will require it to be changed
951 at first login, which you should do as soon as possible. If you lose the
952 root password or wish to change it without starting the container, you
953 can change it from the host by running the following command (which will
954 also reset the expired flag):
956 chroot ${rootfs_path} passwd