remote checkfs.sh from squeeze
[sysadmin-cookbook] / recepies / lxc / lxc-debian
1 #!/bin/bash
2
3 #
4 # lxc: linux Container library
5
6 # Authors:
7 # Daniel Lezcano <daniel.lezcano@free.fr>
8
9 # This library is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU Lesser General Public
11 # License as published by the Free Software Foundation; either
12 # version 2.1 of the License, or (at your option) any later version.
13
14 # This library is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 # Lesser General Public License for more details.
18
19 # You should have received a copy of the GNU Lesser General Public
20 # License along with this library; if not, write to the Free Software
21 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 configure_debian()
24 {
25     rootfs=$1
26     hostname=$2
27
28     # configure the inittab
29     cat <<EOF > $rootfs/etc/inittab
30 id:3:initdefault:
31 si::sysinit:/etc/init.d/rcS
32 l0:0:wait:/etc/init.d/rc 0
33 l1:1:wait:/etc/init.d/rc 1
34 l2:2:wait:/etc/init.d/rc 2
35 l3:3:wait:/etc/init.d/rc 3
36 l4:4:wait:/etc/init.d/rc 4
37 l5:5:wait:/etc/init.d/rc 5
38 l6:6:wait:/etc/init.d/rc 6
39 # Normally not reached, but fallthrough in case of emergency.
40 z6:6:respawn:/sbin/sulogin
41 1:2345:respawn:/sbin/getty 38400 console
42 c1:12345:respawn:/sbin/getty 38400 tty1 linux
43 c2:12345:respawn:/sbin/getty 38400 tty2 linux
44 c3:12345:respawn:/sbin/getty 38400 tty3 linux
45 c4:12345:respawn:/sbin/getty 38400 tty4 linux
46 EOF
47
48     # disable selinux in debian
49     mkdir -p $rootfs/selinux
50     echo 0 > $rootfs/selinux/enforce
51
52     # by default setup root password with no password
53     cat <<EOF > $rootfs/etc/ssh/sshd_config
54 Port 22
55 Protocol 2
56 HostKey /etc/ssh/ssh_host_rsa_key
57 HostKey /etc/ssh/ssh_host_dsa_key
58 UsePrivilegeSeparation yes
59 KeyRegenerationInterval 3600
60 ServerKeyBits 768
61 SyslogFacility AUTH
62 LogLevel INFO
63 LoginGraceTime 120
64 PermitRootLogin yes
65 StrictModes yes
66 RSAAuthentication yes
67 PubkeyAuthentication yes
68 IgnoreRhosts yes
69 RhostsRSAAuthentication no
70 HostbasedAuthentication no
71 PermitEmptyPasswords yes
72 ChallengeResponseAuthentication no
73 EOF
74
75     # configure the network using the dhcp
76     cat <<EOF > $rootfs/etc/network/interfaces
77 auto lo
78 iface lo inet loopback
79
80 auto eth0
81 iface eth0 inet dhcp
82 EOF
83
84     # set the hostname
85     cat <<EOF > $rootfs/etc/hostname
86 $hostname
87 EOF
88
89     # reconfigure some services
90     chroot $rootfs /usr/sbin/dpkg-reconfigure locales
91
92     # remove pointless services in a container
93     chroot $rootfs /usr/sbin/update-rc.d -f umountfs remove
94     chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh remove
95     chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh remove
96 }
97
98 arch=$(arch)
99
100 download_debian()
101 {
102     packages=\
103 ifupdown,\
104 locales,\
105 libui-dialog-perl,\
106 dialog,\
107 dhcp-client,\
108 netbase,\
109 net-tools,\
110 iproute,\
111 openssh-server
112
113     cache=$1
114
115     # check the mini debian was not already downloaded
116     mkdir -p "$cache/partial-$arch"
117     if [ $? -ne 0 ]; then
118         echo "Failed to create '$cache/partial-$arch' directory"
119         return 1
120     fi
121
122     # download a mini debian into a cache
123     echo "Downloading debian minimal ..."
124     debootstrap --verbose --variant=minbase --arch=$arch \
125         --include $packages \
126         lenny $cache/partial-$arch http://ftp.debian.org/debian
127     if [ $? -ne 0 ]; then
128         echo "Failed to download the rootfs, aborting."
129         return 1
130     fi
131
132     mv "$1/partial-$arch" "$1/rootfs-$arch"
133     echo "Download complete."
134
135     return 0
136 }
137
138 copy_debian()
139 {
140     cache=$1
141     rootfs=$3
142
143     # make a local copy of the minidebian
144     echo -n "Copying rootfs to $rootfs..."
145     cp -a $cache/rootfs-$arch $rootfs || return 1
146     return 0
147 }
148
149 install_debian()
150 {
151     cache="/var/cache/lxc/debian"
152     rootfs=$1
153     mkdir -p /var/lock/subsys/
154     (
155         flock -n -x 200
156         if [ $? -ne 0 ]; then
157             echo "Cache repository is busy."
158             return 1
159         fi
160
161         if [ "$arch" == "x86_64" ]; then
162             arch=amd64
163         fi
164
165         if [ "$arch" == "i686" ]; then
166             arch=i386
167         fi
168
169         echo "Checking cache download in $cache/rootfs-$arch ... "
170         if [ ! -e "$cache/rootfs-$arch" ]; then
171             download_debian $cache $arch
172             if [ $? -ne 0 ]; then
173                 echo "Failed to download 'debian base'"
174                 return 1
175             fi
176         fi
177
178         copy_debian $cache $arch $rootfs
179         if [ $? -ne 0 ]; then
180             echo "Failed to copy rootfs"
181             return 1
182         fi
183
184         return 0
185
186         ) 200>/var/lock/subsys/lxc
187
188     return $?
189 }
190
191 copy_configuration()
192 {
193     path=$1
194     rootfs=$2
195     name=$3
196
197     cat <<EOF >> $path/config
198 lxc.tty = 4
199 lxc.pts = 1024
200 lxc.rootfs = $rootfs
201 lxc.cgroup.devices.deny = a
202 # /dev/null and zero
203 lxc.cgroup.devices.allow = c 1:3 rwm
204 lxc.cgroup.devices.allow = c 1:5 rwm
205 # consoles
206 lxc.cgroup.devices.allow = c 5:1 rwm
207 lxc.cgroup.devices.allow = c 5:0 rwm
208 lxc.cgroup.devices.allow = c 4:0 rwm
209 lxc.cgroup.devices.allow = c 4:1 rwm
210 # /dev/{,u}random
211 lxc.cgroup.devices.allow = c 1:9 rwm
212 lxc.cgroup.devices.allow = c 1:8 rwm
213 lxc.cgroup.devices.allow = c 136:* rwm
214 lxc.cgroup.devices.allow = c 5:2 rwm
215 # rtc
216 lxc.cgroup.devices.allow = c 254:0 rwm
217 EOF
218
219     if [ $? -ne 0 ]; then
220         echo "Failed to add configuration"
221         return 1
222     fi
223
224     return 0
225 }
226
227 clean()
228 {
229     cache="/var/cache/lxc/debian"
230
231     if [ ! -e $cache ]; then
232         exit 0
233     fi
234
235     # lock, so we won't purge while someone is creating a repository
236     (
237         flock -n -x 200 
238         if [ $? != 0 ]; then
239             echo "Cache repository is busy."
240             exit 1
241         fi
242
243         echo -n "Purging the download cache..."
244         rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
245         exit 0
246
247     ) 200>/var/lock/subsys/lxc
248 }
249
250 usage()
251 {
252     cat <<EOF
253 $1 -h|--help -p|--path=<path> -a|--arch=stable --clean
254 EOF
255     return 0
256 }
257
258 options=$(getopt -o hp:n:ca: -l help,path:,name:,clean,arch: -- "$@")
259 if [ $? -ne 0 ]; then
260         usage $(basename $0)
261         exit 1
262 fi
263 eval set -- "$options"
264
265 while true
266 do
267     case "$1" in
268         -h|--help)      usage $0 && exit 0;;
269         -p|--path)      path=$2; shift 2;;
270                 -n|--name)      name=$2; shift 2;;
271                 -c|--clean)     clean=$2; shift 2;;
272                 -a|--arch)              arch=$2; shift 2;;
273         --)             shift 1; break ;;
274         *)              break ;;
275     esac
276 done
277
278 if [ ! -z "$clean" -a -z "$path" ]; then
279     clean || exit 1
280     exit 0
281 fi
282
283 type debootstrap
284 if [ $? -ne 0 ]; then
285     echo "'debootstrap' command is missing"
286     exit 1
287 fi
288
289 if [ -z "$path" ]; then
290     echo "'path' parameter is required"
291     exit 1
292 fi
293
294 if [ "$(id -u)" != "0" ]; then
295     echo "This script should be run as 'root'"
296     exit 1
297 fi 
298
299 rootfs=$path/rootfs
300
301 install_debian $rootfs
302 if [ $? -ne 0 ]; then
303     echo "failed to install debian"
304     exit 1
305 fi
306
307 configure_debian $rootfs $name
308 if [ $? -ne 0 ]; then
309     echo "failed to configure debian for a container"
310     exit 1
311 fi
312
313 copy_configuration $path $rootfs
314 if [ $? -ne 0 ]; then
315     echo "failed write configuration file"
316     exit 1
317 fi
318
319 if [ ! -z $clean ]; then
320     clean || exit 1
321     exit 0
322 fi