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