4 # template script for generating centos container for LXC
8 # lxc: linux Container library
11 # Daniel Lezcano <daniel.lezcano@free.fr>
12 # Christian Bayle <bayle@debian.org>
14 # This library is free software; you can redistribute it and/or
15 # modify it under the terms of the GNU Lesser General Public
16 # License as published by the Free Software Foundation; either
17 # version 2.1 of the License, or (at your option) any later version.
19 # This library is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 # Lesser General Public License for more details.
24 # You should have received a copy of the GNU Lesser General Public
25 # License along with this library; if not, write to the Free Software
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
36 # disable selinux in centos
37 mkdir -p $rootfs/selinux
38 echo 0 > $rootfs/selinux/enforce
41 if ! grep -q "^127.0.0.1" $rootfs/etc/hosts
43 cat <<EOF >> $rootfs/etc/hosts
44 # Do not remove the following line, or various programs
45 # that require network functionality will fail.
46 127.0.0.1 localhost.localdomain localhost
47 ::1 localhost6.localdomain6 localhost6
50 if ! grep -q "^::1" $rootfs/etc/hosts
52 cat <<EOF >> $rootfs/etc/hosts
53 ::1 localhost6.localdomain6 localhost6
57 if grep -q ^lxc.network.ipv4 $path/config
59 # configure static network
60 lxc_network_ipv4=`grep ^lxc.network.ipv4 $path/config | cut -d= -f2`
61 address=`echo $lxc_network_ipv4 | cut -d/ -f1`
62 netmask=`netmask -s $lxc_network_ipv4 | cut -d/ -f2`
63 if [ -e $rootfs/etc/sysconfig/network-scripts ]
65 cat <<EOF > $rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
75 cat <<EOF > $rootfs/etc/sysconfig/network
82 cat <<EOF >> $rootfs/etc/hosts
85 echo "Network configured with static ip"
91 # configure the network using the dhcp
92 if [ -e $rootfs/etc/sysconfig/network-scripts ]
94 cat <<EOF > $rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
100 cat <<EOF > $rootfs/etc/sysconfig/network
106 cat <<EOF >> $rootfs/etc/hosts
109 echo "Network configured with dhcp"
113 # When domain is not local, avahi completed by send hostname
114 hostnamebase=`echo $hostname | cut -d. -f1`
115 if [ "$hostnamebase.local" != "$hostname" ]
117 cat <<EOF > $rootfs/etc/dhclient.conf
118 send host-name "$hostnamebase";
123 cat <<EOF > $rootfs/etc/init/console.conf
126 # This service maintains a console on tty1 from the point the system is
127 # started until it is shut down again.
129 start on stopped rc RUNLEVEL=[2345]
130 stop on runlevel [!2345]
132 initctl start tty TTY=console
135 cat <<EOF > $rootfs/etc/fstab
136 # NOT MOUNTING IN LXC
137 #none /dev/pts devpts defaults 0 0
138 #none /proc proc nodev,noexec,nosuid 0 0
139 #none /sys sysfs defaults 0 0
140 #none /dev/shm tmpfs defaults 0 0
143 [ ! -f $rootfs/etc/init/kexec-disable.conf ] || mv $rootfs/etc/init/kexec-disable.conf $rootfs/etc/init/kexec-disable.conf.orig
145 echo "Please change root-password !"
146 echo "root:root" | chroot $rootfs chpasswd
148 sed -i -e 's:/sbin/start_udev:#/sbin/start_udev:' $rootfs/etc/rc.d/rc.sysinit
149 #CB# remove lines acting on /dev/pts
150 sed -i -e 's:\(.*/dev/pts.*\):#\1:' $rootfs/etc/rc.d/rc.sysinit
151 #CB# remove lines acting on /dev/shm
152 sed -i -e 's:\(.*/dev/shm*\):#\1:' $rootfs/etc/rc.d/rc.sysinit
153 #CB# remove / proc and sys mounts
154 sed -i -e 's:\(.*mount -f /.*\):#\1:' $rootfs/etc/rc.d/rc.sysinit
155 sed -i -e 's:\(.*mount -f /proc.*\):#\1:' $rootfs/etc/rc.d/rc.sysinit
156 sed -i -e 's:\(.*mount -f /sys*\):#\1:' $rootfs/etc/rc.d/rc.sysinit
159 if [ -f $rootfs/etc/init.d/avahi-daemon ]
162 sed -i -e "s!-D!-D --no-rlimits!" $rootfs/etc/init.d/avahi-daemon
165 mv $rootfs/dev $rootfs/dev.old
167 test -e $rootfs/dev/null || mknod -m 666 $rootfs/dev/null c 1 3
168 test -e $rootfs/dev/zero || mknod -m 666 $rootfs/dev/zero c 1 5
169 test -e $rootfs/dev/random || mknod -m 666 $rootfs/dev/random c 1 8
170 test -e $rootfs/dev/urandom || mknod -m 666 $rootfs/dev/urandom c 1 9
171 test -e $rootfs/dev/pts || mkdir -m 755 $rootfs/dev/pts
172 test -e $rootfs/dev/shm || mkdir -m 1777 $rootfs/dev/shm
173 test -e $rootfs/dev/tty || mknod -m 666 $rootfs/dev/tty c 5 0
174 test -e $rootfs/dev/console || mknod -m 600 $rootfs/dev/console c 5 1
175 test -e $rootfs/dev/tty0 || mknod -m 666 $rootfs/dev/tty0 c 4 0
176 test -e $rootfs/dev/full || mknod -m 666 $rootfs/dev/full c 1 7
177 test -e $rootfs/dev/initctl || mknod -m 600 $rootfs/dev/initctl p
178 test -e $rootfs/dev/ptmx || mknod -m 666 $rootfs/dev/ptmx c 5 2
180 test -e $rootfs/dev/tty1 || mknod -m 666 $rootfs/dev/tty1 c 4 1
181 test -e $rootfs/dev/tty2 || mknod -m 666 $rootfs/dev/tty2 c 4 2
182 test -e $rootfs/dev/tty3 || mknod -m 666 $rootfs/dev/tty3 c 4 3
183 test -e $rootfs/dev/tty4 || mknod -m 666 $rootfs/dev/tty4 c 4 4
184 test -e $rootfs/dev/tty5 || mknod -m 666 $rootfs/dev/tty5 c 4 5
185 test -e $rootfs/dev/tty6 || mknod -m 666 $rootfs/dev/tty6 c 4 6
193 if grep -q ^\#lxc.pubkey $path/config
195 pubkey=`grep ^\#lxc.pubkey $path/config | cut -d= -f2`
197 if [ ! -e $rootfs/root/.ssh ]
199 mkdir $rootfs/root/.ssh
201 if [ ! -z "$pubkey" ]
203 echo "Copying $pubkey -> $rootfs/root/.ssh/authorized_keys"
204 cp $pubkey $rootfs/root/.ssh/authorized_keys
208 configure_hostkeydir(){
216 [ -d $rootfs/etc/ssh ] || mkdir -p $rootfs/etc/ssh
217 if [ -e $hostkeydir ]
219 if [ ! -d $hostkeydir/$name ]
221 mkdir $hostkeydir/$name
222 echo "Creating SSH2 RSA key; this may take some time ..."
223 ssh-keygen -q -f $hostkeydir/$name/ssh_host_rsa_key -N '' -t rsa
224 echo "Creating SSH2 DSA key; this may take some time ..."
225 ssh-keygen -q -f $hostkeydir/$name/ssh_host_dsa_key -N '' -t dsa
227 cp $hostkeydir/$name/ssh_host_* $rootfs/etc/ssh/
237 # check the mini centos was not already downloaded
238 mkdir -p "$cache/partial-$arch"
239 if [ $? -ne 0 ]; then
240 echo "Failed to create '$cache/partial-$arch' directory"
244 # download a mini centos into a cache
245 echo "Downloading centos minimal ..."
246 #febootstrap $DISTRO $cache/partial-$arch
247 rinsearch=`dpkg-architecture -qDEB_BUILD_ARCH`
248 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 tigervnc-server crypto-utils"
250 cat <<EOF > /var/cache/rinse/$DISTRO-$arch.before_post_install
251 echo "Rinse defines mirror=\$mirror in config"
252 server=\`echo \$mirror | cut -d/ -f3\`
253 echo "Disable mirrorlists"
254 sed -i -e "s/^mirrorlist=/#mirrorlist=/" $cache/partial-$arch/etc/yum.repos.d/CentOS-Base.repo
255 echo "Setup baseurl on server \$server"
256 sed -i -e "s!#baseurl=http://mirror.centos.org!baseurl=http://\$server!" $cache/partial-$arch/etc/yum.repos.d/CentOS-Base.repo
257 rm -f $cache/partial-$arch/etc/mtab
258 ln -s /proc/mounts $cache/partial-$arch/etc/mtab
260 mkdir -p $cache/partial-$arch/dev
261 test -e $cache/partial-$arch/dev/null || mknod -m 666 $cache/partial-$arch/dev/null c 1 3
262 test -e $cache/partial-$arch/dev/zero || mknod -m 666 $cache/partial-$arch/dev/zero c 1 5
263 test -e $cache/partial-$arch/dev/random || mknod -m 666 $cache/partial-$arch/dev/random c 1 8
264 test -e $cache/partial-$arch/dev/urandom || mknod -m 666 $cache/partial-$arch/dev/urandom c 1 9
265 test -e $cache/partial-$arch/dev/pts || mkdir -m 755 $cache/partial-$arch/dev/pts
266 test -e $cache/partial-$arch/dev/shm || mkdir -m 1777 $cache/partial-$arch/dev/shm
267 test -e $cache/partial-$arch/dev/tty || mknod -m 666 $cache/partial-$arch/dev/tty c 5 0
268 test -e $cache/partial-$arch/dev/console || mknod -m 600 $cache/partial-$arch/dev/console c 5 1
269 test -e $cache/partial-$arch/dev/tty0 || mknod -m 666 $cache/partial-$arch/dev/tty0 c 4 0
270 test -e $cache/partial-$arch/dev/full || mknod -m 666 $cache/partial-$arch/dev/full c 1 7
271 test -e $cache/partial-$arch/dev/initctl || mknod -m 600 $cache/partial-$arch/dev/initctl p
272 test -e $cache/partial-$arch/dev/ptmx || mknod -m 666 $cache/partial-$arch/dev/ptmx c 5 2
274 test -e $cache/partial-$arch/dev/tty1 || mknod -m 666 $cache/partial-$arch/dev/tty1 c 4 1
275 test -e $cache/partial-$arch/dev/tty2 || mknod -m 666 $cache/partial-$arch/dev/tty2 c 4 2
276 test -e $cache/partial-$arch/dev/tty3 || mknod -m 666 $cache/partial-$arch/dev/tty3 c 4 3
277 test -e $cache/partial-$arch/dev/tty4 || mknod -m 666 $cache/partial-$arch/dev/tty4 c 4 4
278 test -e $cache/partial-$arch/dev/tty5 || mknod -m 666 $cache/partial-$arch/dev/tty5 c 4 5
279 test -e $cache/partial-$arch/dev/tty6 || mknod -m 666 $cache/partial-$arch/dev/tty6 c 4 6
281 chmod 755 /var/cache/rinse/$DISTRO-$arch.before_post_install
283 cat <<EOF > /var/cache/rinse/$DISTRO-$arch.after_post_install
284 # CREATE FSTAB IF NOT EXISTS
288 chroot $cache/partial-$arch /bin/mount proc /proc -t proc
290 echo "Install $pkglist"
291 chroot $cache/partial-$arch /usr/bin/yum -y install $pkglist
294 cat <<EOF >> /var/cache/rinse/$DISTRO-$arch.after_post_install
297 chroot $cache/partial-$arch /bin/umount /proc
299 chmod 755 /var/cache/rinse/$DISTRO-$arch.after_post_install
301 rinse --config /etc/rinse/rinse.conf \
303 --distribution $DISTRO \
304 --before-post-install /var/cache/rinse/$DISTRO-$arch.before_post_install \
305 --after-post-install /var/cache/rinse/$DISTRO-$arch.after_post_install \
306 --directory $cache/partial-$arch
308 if [ $? -ne 0 ]; then
309 echo "Failed to download the rootfs, aborting."
313 mv "$1/partial-$arch" "$1/rootfs-$arch"
314 echo "Download complete."
325 # make a local copy of the minicentos
326 echo -n "Copying rootfs to $rootfs ..."
327 cp --reflink=auto -a $cache/rootfs-$arch $rootfs || return 1
333 cache="/var/cache/lxc/$DISTRO"
335 mkdir -p /var/lock/subsys/
338 if [ $? -ne 0 ]; then
339 echo "Cache repository is busy."
345 echo "Checking cache download in $cache/rootfs-$arch ... "
346 if [ ! -e "$cache/rootfs-$arch" ]; then
347 download_centos $cache $arch
348 if [ $? -ne 0 ]; then
349 echo "Failed to download 'centos base'"
354 echo "Copy $cache/rootfs-$arch to $rootfs ... "
355 copy_centos $cache $arch $rootfs
356 if [ $? -ne 0 ]; then
357 echo "Failed to copy rootfs"
363 ) 200>/var/lock/subsys/lxc
370 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 }'
380 if [ ! -e "$macdir/$name" ]
382 gen_mac > $macdir/$name
384 macaddr=`cat $macdir/$name`
386 cat <<EOF >> $path/config
387 lxc.network.hwaddr = $macaddr
388 # lxc.utsname = $name
393 lxc.cgroup.devices.deny = a
395 lxc.cgroup.devices.allow = c 1:3 rwm
396 lxc.cgroup.devices.allow = c 1:5 rwm
398 lxc.cgroup.devices.allow = c 1:7 rwm
400 lxc.cgroup.devices.allow = c 5:1 rwm
401 lxc.cgroup.devices.allow = c 5:0 rwm
402 lxc.cgroup.devices.allow = c 4:0 rwm
403 lxc.cgroup.devices.allow = c 4:1 rwm
404 lxc.cgroup.devices.allow = c 4:2 rwm
405 lxc.cgroup.devices.allow = c 4:3 rwm
406 lxc.cgroup.devices.allow = c 4:4 rwm
407 lxc.cgroup.devices.allow = c 4:5 rwm
408 lxc.cgroup.devices.allow = c 4:6 rwm
410 lxc.cgroup.devices.allow = c 1:9 rwm
411 lxc.cgroup.devices.allow = c 1:8 rwm
412 lxc.cgroup.devices.allow = c 136:* rwm
413 lxc.cgroup.devices.allow = c 5:2 rwm
415 lxc.cgroup.devices.allow = c 254:0 rwm
418 lxc.mount.entry=proc $rootfs/proc proc nodev,noexec,nosuid 0 0
419 lxc.mount.entry=devpts $rootfs/dev/pts devpts defaults 0 0
420 lxc.mount.entry=sysfs $rootfs/sys sysfs defaults 0 0
423 cat <<EOF > $path/fstab
424 #proc $rootfs/proc proc nodev,noexec,nosuid 0 0
425 #devpts $rootfs/dev/pts devpts defaults 0 0
426 #sysfs $rootfs/sys sysfs defaults 0 0
427 #tmpfs $rootfs/dev/shm tmpfs defaults 0 0
430 if [ $? -ne 0 ]; then
431 echo "Failed to add configuration"
440 cache="/var/cache/lxc/$DISTRO"
442 if [ ! -e $cache ]; then
446 # lock, so we won't purge while someone is creating a repository
450 echo "Cache repository is busy."
454 echo -n "Purging the download cache..."
455 rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
458 ) 200>/var/lock/subsys/lxc
464 $1 -h|--help -p|--path=<path> --clean
469 options=$(getopt -o hp:n:c -l help,path:,name:,clean -- "$@")
470 if [ $? -ne 0 ]; then
474 eval set -- "$options"
479 -h|--help) usage $0 && exit 0;;
480 -p|--path) path=$2; shift 2;;
481 -n|--name) name=$2; shift 2;;
482 -c|--clean) clean=$2; shift 2;;
483 --) shift 1; break ;;
488 if [ ! -z "$clean" -a -z "$path" ]; then
494 if [ $? -ne 0 ]; then
495 echo "'netmask' command is missing"
500 if [ $? -ne 0 ]; then
501 echo "'rinse' command is missing"
505 if [ -z "$path" ]; then
506 echo "'path' parameter is required"
510 if [ "$(id -u)" != "0" ]; then
511 echo "This script should be run as 'root'"
516 oldhostkeydir=/var/lib/lxc/ssh
517 hostkeydir=/var/cache/lxc/ssh
518 macdir=/var/cache/lxc/mac
519 if [ -e $oldhostkeydir ]
521 if [ ! -e $hostkeydir ]
523 mv $oldhostkeydir $hostkeydir
526 if [ ! -e $hostkeydir ]
535 install_centos $rootfs
536 if [ $? -ne 0 ]; then
537 echo "failed to install centos"
541 configure_centos $path $rootfs $name
542 if [ $? -ne 0 ]; then
543 echo "failed to configure centos for a container"
547 copy_configuration $path $rootfs $name $macdir
548 if [ $? -ne 0 ]; then
549 echo "failed write configuration file"
553 configure_pubkey $path $rootfs
554 if [ $? -ne 0 ]; then
555 echo "failed to configure pubkey"
559 configure_hostkeydir $rootfs $hostkeydir $name
560 if [ $? -ne 0 ]; then
561 echo "failed to configure hostkeydir"
565 if [ ! -z $clean ]; then