4 # template script for generating centos container for LXC
8 # lxc: linux Container library
11 # Daniel Lezcano <daniel.lezcano@free.fr>
13 # This library is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU Lesser General Public
15 # License as published by the Free Software Foundation; either
16 # version 2.1 of the License, or (at your option) any later version.
18 # This library is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 # Lesser General Public License for more details.
23 # You should have received a copy of the GNU Lesser General Public
24 # License along with this library; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
35 # disable selinux in centos
36 mkdir -p $rootfs/selinux
37 echo 0 > $rootfs/selinux/enforce
40 if ! grep -q "^127.0.0.1" $rootfs/etc/hosts
42 cat <<EOF >> $rootfs/etc/hosts
43 # Do not remove the following line, or various programs
44 # that require network functionality will fail.
45 127.0.0.1 localhost.localdomain localhost
46 ::1 localhost6.localdomain6 localhost6
49 if ! grep -q "^::1" $rootfs/etc/hosts
51 cat <<EOF >> $rootfs/etc/hosts
52 ::1 localhost6.localdomain6 localhost6
56 if grep -q ^lxc.network.ipv4 $path/config
58 # configure static network
59 lxc_network_ipv4=`grep ^lxc.network.ipv4 $path/config | cut -d= -f2`
60 address=`echo $lxc_network_ipv4 | cut -d/ -f1`
61 netmask=`netmask -s $lxc_network_ipv4 | cut -d/ -f2`
62 if [ -e $rootfs/etc/sysconfig/network-scripts ]
64 cat <<EOF > $rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
74 cat <<EOF > $rootfs/etc/sysconfig/network
81 cat <<EOF >> $rootfs/etc/hosts
84 echo "Network configured with static ip"
90 # configure the network using the dhcp
91 if [ -e $rootfs/etc/sysconfig/network-scripts ]
93 cat <<EOF > $rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
99 cat <<EOF > $rootfs/etc/sysconfig/network
105 cat <<EOF >> $rootfs/etc/hosts
108 echo "Network configured with dhcp"
112 # When domain is not local, avahi completed by send hostname
113 hostnamebase=`echo $hostname | cut -d. -f1`
114 if [ "$hostnamebase.local" != "$hostname" ]
116 cat <<EOF > $rootfs/etc/dhclient.conf
117 send host-name "$hostnamebase";
122 # provide the lxc service
123 # cat <<EOF > $rootfs/etc/init/lxc.conf
124 ## fake some events needed for correct startup other services
126 #description "Container Upstart"
131 # rm -rf /var/run/*.pid
132 # rm -rf /var/run/network/*
133 # /sbin/initctl emit stopped JOB=udevtrigger --no-wait
134 # /sbin/initctl emit started JOB=udev --no-wait
138 cat <<EOF > $rootfs/etc/init/console.conf
141 # This service maintains a console on tty1 from the point the system is
142 # started until it is shut down again.
144 start on stopped rc RUNLEVEL=[2345]
145 stop on runlevel [!2345]
148 #exec /sbin/getty -8 38400 /dev/console
149 exec /sbin/mingetty console
153 #CB#cat <<EOF >> $rootfs/etc/inittab
154 #CB#0:2345:respawn:/sbin/mingetty console
157 # cat <<EOF > $rootfs/lib/init/fstab
158 ## /lib/init/fstab: lxc system fstab
159 #none /spu spufs gid=spu,optional 0 0
160 #none /tmp none defaults 0 0
161 #none /var/lock tmpfs nodev,noexec,nosuid,showthrough 0 0
162 #none /lib/init/rw tmpfs mode=0755,nosuid,optional 0 0
164 cat <<EOF > $rootfs/etc/fstab
165 #none /proc proc nodev,noexec,nosuid 0 0
166 none /dev/pts devpts defaults 0 0
167 #none /sys sysfs defaults 0 0
168 #none /dev/shm tmpfs defaults 0 0
171 # suppress log level output for udev
172 # sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf
174 # reconfigure some services
175 # if [ -z "$LANG" ]; then
176 # chroot $rootfs locale-gen en_US.UTF-8
177 # chroot $rootfs update-locale LANG=en_US.UTF-8
179 # chroot $rootfs locale-gen $LANG
180 # chroot $rootfs update-locale LANG=$LANG
183 # remove pointless services in a container
184 # chroot $rootfs /usr/sbin/update-rc.d -f ondemand remove
186 [ ! -f $rootfs/etc/init/kexec-disable.conf ] || mv $rootfs/etc/init/kexec-disable.conf $rootfs/etc/init/kexec-disable.conf.orig
187 # chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls u*.conf); do mv $f $f.orig; done'
188 # chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls tty[2-9].conf); do mv $f $f.orig; done'
189 # chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls plymouth*.conf); do mv $f $f.orig; done'
190 # chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls hwclock*.conf); do mv $f $f.orig; done'
191 # chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls module*.conf); do mv $f $f.orig; done'
193 echo "Please change root-password !"
194 echo "root:root" | chroot $rootfs chpasswd
196 sed -i -e 's:/sbin/start_udev:#/sbin/start_udev:' $rootfs/etc/rc.d/rc.sysinit
197 #CB#chroot $rootfs chkconfig udev-post off
198 #chroot $rootfs chkconfig network on
202 if [ -f $rootfs/etc/init.d/avahi-daemon ]
205 sed -i -e "s!-D!-D --no-rlimits!" $rootfs/etc/init.d/avahi-daemon
208 #CB#mv $rootfs/dev $rootfs/dev.old
209 #CB#mkdir $rootfs/dev
210 #CB#test -e $rootfs/dev/null || mknod -m 666 $rootfs/dev/null c 1 3
211 #CB#test -e $rootfs/dev/zero || mknod -m 666 $rootfs/dev/zero c 1 5
212 test -e $rootfs/dev/random || mknod -m 666 $rootfs/dev/random c 1 8
213 test -e $rootfs/dev/urandom || mknod -m 666 $rootfs/dev/urandom c 1 9
214 test -e $rootfs/dev/pts || mkdir -m 755 $rootfs/dev/pts
215 #test -e $rootfs/dev/shm || mkdir -m 1777 $rootfs/dev/shm
216 test -e $rootfs/dev/tty || mknod -m 666 $rootfs/dev/tty c 5 0
217 test -e $rootfs/dev/tty0 || mknod -m 666 $rootfs/dev/tty0 c 4 0
218 test -e $rootfs/dev/tty1 || mknod -m 666 $rootfs/dev/tty1 c 4 1
219 test -e $rootfs/dev/tty2 || mknod -m 666 $rootfs/dev/tty2 c 4 2
220 test -e $rootfs/dev/tty3 || mknod -m 666 $rootfs/dev/tty3 c 4 3
221 test -e $rootfs/dev/tty4 || mknod -m 666 $rootfs/dev/tty4 c 4 4
222 test -e $rootfs/dev/tty5 || mknod -m 666 $rootfs/dev/tty5 c 4 5
223 test -e $rootfs/dev/tty6 || mknod -m 666 $rootfs/dev/tty6 c 4 6
224 test -e $rootfs/dev/console || mknod -m 600 $rootfs/dev/console c 5 1
225 test -e $rootfs/dev/full || mknod -m 666 $rootfs/dev/full c 1 7
226 test -e $rootfs/dev/initctl || mknod -m 600 $rootfs/dev/initctl p
227 #CB#test -e $rootfs/dev/ptmx || mknod -m 666 $rootfs/dev/ptmx c 5 2
236 if grep -q ^\#lxc.pubkey $path/config
238 pubkey=`grep ^\#lxc.pubkey $path/config | cut -d= -f2`
240 if [ ! -e $rootfs/root/.ssh ]
242 mkdir $rootfs/root/.ssh
244 if [ ! -z "$pubkey" ]
246 echo "Copying $pubkey -> $rootfs/root/.ssh/authorized_keys"
247 cp $pubkey $rootfs/root/.ssh/authorized_keys
251 configure_hostkeydir(){
259 [ -d $rootfs/etc/ssh ] || mkdir -p $rootfs/etc/ssh
260 if [ -e $hostkeydir ]
262 if [ ! -d $hostkeydir/$name ]
264 mkdir $hostkeydir/$name
265 echo "Creating SSH2 RSA key; this may take some time ..."
266 ssh-keygen -q -f $hostkeydir/$name/ssh_host_rsa_key -N '' -t rsa
267 echo "Creating SSH2 DSA key; this may take some time ..."
268 ssh-keygen -q -f $hostkeydir/$name/ssh_host_dsa_key -N '' -t dsa
270 cp $hostkeydir/$name/ssh_host_* $rootfs/etc/ssh/
280 # check the mini centos was not already downloaded
281 mkdir -p "$cache/partial-$arch"
282 if [ $? -ne 0 ]; then
283 echo "Failed to create '$cache/partial-$arch' directory"
287 # download a mini centos into a cache
288 echo "Downloading centos minimal ..."
289 #febootstrap $DISTRO $cache/partial-$arch
290 rinsearch=`dpkg-architecture -qDEB_BUILD_ARCH`
291 pkglist="plymouth policycoreutils openssh-server man zsh bind-utils openssh-clients php wget rsync avahi php-pear php-dom java-1.6.0-openjdk xorg-x11-xauth firefox make rpm-build createrepo"
293 cat <<EOF > /var/cache/rinse/$DISTRO-$arch.before_post_install
294 echo "Rinse defines mirror=\$mirror in config"
295 server=\`echo \$mirror | cut -d/ -f3\`
296 echo "Disable mirrorlists"
297 sed -i -e "s/^mirrorlist=/#mirrorlist=/" $cache/partial-$arch/etc/yum.repos.d/CentOS-Base.repo
298 echo "Setup baseurl on server \$server"
299 sed -i -e "s!#baseurl=http://mirror.centos.org!baseurl=http://\$server!" $cache/partial-$arch/etc/yum.repos.d/CentOS-Base.repo
300 rm -f $cache/partial-$arch/etc/mtab
301 ln -s /proc/mounts $cache/partial-$arch/etc/mtab
303 chmod 755 /var/cache/rinse/$DISTRO-$arch.before_post_install
305 cat <<EOF > /var/cache/rinse/$DISTRO-$arch.after_post_install
308 chroot $cache/partial-$arch /bin/mount proc /proc -t proc
310 echo "Install $pkglist"
311 chroot $cache/partial-$arch /usr/bin/yum -y install $pkglist
314 if grep -q ^http_proxy /etc/wgetrc
316 PROXY=`grep ^http_proxy /etc/wgetrc | tail -1 | sed -e 's!.*http://!!' -e 's!/!!'`
319 cat <<EOF >> /var/cache/rinse/$DISTRO-$arch.after_post_install
320 # PROXY CONF FROM WGET
321 echo "Set up proxy $PROXY for pear"
322 chroot $cache/partial-$arch /usr/bin/pear config-set http_proxy $PROXY
326 cat <<EOF >> /var/cache/rinse/$DISTRO-$arch.after_post_install
328 # phpunit install, requires: php-pear php-dom
329 echo "Updating pear.php.net pear channel"
330 chroot $cache/partial-$arch /usr/bin/pear channel-update pear.php.net
331 #optional?# chroot $cache/partial-$arch /usr/bin/pear channel-discover components.ez.no
332 echo "Discovering pear.phpunit.de pear channel"
333 chroot $cache/partial-$arch /usr/bin/pear channel-discover pear.phpunit.de
334 echo "Discovering pear.symfony-project.com pear channel"
335 chroot $cache/partial-$arch /usr/bin/pear channel-discover pear.symfony-project.com
336 echo "Upgrading pear"
337 chroot $cache/partial-$arch /usr/bin/pear upgrade-all
338 chroot $cache/partial-$arch /usr/bin/pear upgrade --force PEAR
339 echo "Installing phpunit/PHPUnit"
340 chroot $cache/partial-$arch /usr/bin/pear install --alldeps phpunit/PHPUnit
343 chroot $cache/partial-$arch /bin/umount /proc
345 chmod 755 /var/cache/rinse/$DISTRO-$arch.after_post_install
347 rinse --config /etc/rinse/rinse.conf \
349 --distribution $DISTRO \
350 --before-post-install /var/cache/rinse/$DISTRO-$arch.before_post_install \
351 --after-post-install /var/cache/rinse/$DISTRO-$arch.after_post_install \
352 --directory $cache/partial-$arch
354 if [ $? -ne 0 ]; then
355 echo "Failed to download the rootfs, aborting."
359 mv "$1/partial-$arch" "$1/rootfs-$arch"
360 echo "Download complete."
371 # make a local copy of the minicentos
372 echo -n "Copying rootfs to $rootfs ..."
373 cp -a $cache/rootfs-$arch $rootfs || return 1
379 cache="/var/cache/lxc/$DISTRO"
381 mkdir -p /var/lock/subsys/
384 if [ $? -ne 0 ]; then
385 echo "Cache repository is busy."
391 echo "Checking cache download in $cache/rootfs-$arch ... "
392 if [ ! -e "$cache/rootfs-$arch" ]; then
393 download_centos $cache $arch
394 if [ $? -ne 0 ]; then
395 echo "Failed to download 'centos base'"
400 echo "Copy $cache/rootfs-$arch to $rootfs ... "
401 copy_centos $cache $arch $rootfs
402 if [ $? -ne 0 ]; then
403 echo "Failed to copy rootfs"
409 ) 200>/var/lock/subsys/lxc
416 dd if=/dev/urandom bs=1 count=3 2>/dev/null | od -tx1 | head -1 | cut -d' ' -f2- | awk '{ print "00:16:3e:"$1":"$2":"$3 }'
426 if [ ! -e "$macdir/$name" ]
428 gen_mac > $macdir/$name
430 macaddr=`cat $macdir/$name`
432 cat <<EOF >> $path/config
433 lxc.network.hwaddr = $macaddr
434 # lxc.utsname = $name
439 # lxc.mount = $path/fstab
441 # lxc.console = /dev/console
443 lxc.cgroup.devices.deny = a
445 lxc.cgroup.devices.allow = c 1:3 rwm
446 lxc.cgroup.devices.allow = c 1:5 rwm
448 lxc.cgroup.devices.allow = c 1:7 rwm
450 lxc.cgroup.devices.allow = c 5:1 rwm
451 lxc.cgroup.devices.allow = c 5:0 rwm
452 lxc.cgroup.devices.allow = c 4:0 rwm
453 lxc.cgroup.devices.allow = c 4:1 rwm
454 lxc.cgroup.devices.allow = c 4:2 rwm
455 lxc.cgroup.devices.allow = c 4:3 rwm
456 lxc.cgroup.devices.allow = c 4:4 rwm
457 lxc.cgroup.devices.allow = c 4:5 rwm
458 lxc.cgroup.devices.allow = c 4:6 rwm
460 lxc.cgroup.devices.allow = c 1:9 rwm
461 lxc.cgroup.devices.allow = c 1:8 rwm
462 lxc.cgroup.devices.allow = c 136:* rwm
463 lxc.cgroup.devices.allow = c 5:2 rwm
465 lxc.cgroup.devices.allow = c 254:0 rwm
468 #CB#lxc.mount.entry=proc $rootfs/proc proc nodev,noexec,nosuid 0 0
469 #CB#lxc.mount.entry=devpts $rootfs/dev/pts devpts defaults 0 0
470 #CB#lxc.mount.entry=sysfs $rootfs/sys sysfs defaults 0 0
473 # cat <<EOF > $path/fstab
474 #proc $rootfs/proc proc nodev,noexec,nosuid 0 0
475 #devpts $rootfs/dev/pts devpts defaults 0 0
476 ##sysfs $rootfs/sys sysfs defaults 0 0
477 #tmpfs $rootfs/dev/shm tmpfs defaults 0 0
480 if [ $? -ne 0 ]; then
481 echo "Failed to add configuration"
490 cache="/var/cache/lxc/$DISTRO"
492 if [ ! -e $cache ]; then
496 # lock, so we won't purge while someone is creating a repository
500 echo "Cache repository is busy."
504 echo -n "Purging the download cache..."
505 rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
508 ) 200>/var/lock/subsys/lxc
514 $1 -h|--help -p|--path=<path> --clean
519 options=$(getopt -o hp:n:c -l help,path:,name:,clean -- "$@")
520 if [ $? -ne 0 ]; then
524 eval set -- "$options"
529 -h|--help) usage $0 && exit 0;;
530 -p|--path) path=$2; shift 2;;
531 -n|--name) name=$2; shift 2;;
532 -c|--clean) clean=$2; shift 2;;
533 --) shift 1; break ;;
538 if [ ! -z "$clean" -a -z "$path" ]; then
544 if [ $? -ne 0 ]; then
545 echo "'netmask' command is missing"
550 if [ $? -ne 0 ]; then
551 echo "'rinse' command is missing"
555 if [ -z "$path" ]; then
556 echo "'path' parameter is required"
560 if [ "$(id -u)" != "0" ]; then
561 echo "This script should be run as 'root'"
566 oldhostkeydir=/var/lib/lxc/ssh
567 hostkeydir=/var/cache/lxc/ssh
568 macdir=/var/cache/lxc/mac
569 if [ -e $oldhostkeydir ]
571 if [ ! -e $hostkeydir ]
573 mv $oldhostkeydir $hostkeydir
576 if [ ! -e $hostkeydir ]
585 install_centos $rootfs
586 if [ $? -ne 0 ]; then
587 echo "failed to install centos"
591 configure_centos $path $rootfs $name
592 if [ $? -ne 0 ]; then
593 echo "failed to configure centos for a container"
597 copy_configuration $path $rootfs $name $macdir
598 if [ $? -ne 0 ]; then
599 echo "failed write configuration file"
603 configure_pubkey $path $rootfs
604 if [ $? -ne 0 ]; then
605 echo "failed to configure pubkey"
609 configure_hostkeydir $rootfs $hostkeydir $name
610 if [ $? -ne 0 ]; then
611 echo "failed to configure hostkeydir"
615 if [ ! -z $clean ]; then