]>
Commit | Line | Data |
---|---|---|
bad69158 | 1 | #!/bin/bash |
7afc269d | 2 | |
fb7460fe DL |
3 | # |
4 | # lxc: linux Container library | |
06388011 | 5 | |
fb7460fe DL |
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 | |
14d9c0f0 | 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
fb7460fe | 17 | # Lesser General Public License for more details. |
06388011 | 18 | |
fb7460fe DL |
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 | |
250b1eec | 21 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
06388011 | 22 | |
49a630b8 | 23 | MIRROR=${MIRROR:-http://cdn.debian.net/debian} |
2a7c16dc | 24 | |
fb7460fe DL |
25 | configure_debian() |
26 | { | |
27 | rootfs=$1 | |
28 | hostname=$2 | |
29 | ||
4e0eb765 DB |
30 | # squeeze only has /dev/tty and /dev/tty0 by default, |
31 | # therefore creating missing device nodes for tty1-4. | |
32 | for tty in $(seq 1 4); do | |
14d9c0f0 SG |
33 | if [ ! -e $rootfs/dev/tty$tty ]; then |
34 | mknod $rootfs/dev/tty$tty c 4 $tty | |
35 | fi | |
4e0eb765 DB |
36 | done |
37 | ||
fb7460fe DL |
38 | # configure the inittab |
39 | cat <<EOF > $rootfs/etc/inittab | |
06388011 | 40 | id:3:initdefault: |
41 | si::sysinit:/etc/init.d/rcS | |
42 | l0:0:wait:/etc/init.d/rc 0 | |
43 | l1:1:wait:/etc/init.d/rc 1 | |
44 | l2:2:wait:/etc/init.d/rc 2 | |
45 | l3:3:wait:/etc/init.d/rc 3 | |
46 | l4:4:wait:/etc/init.d/rc 4 | |
47 | l5:5:wait:/etc/init.d/rc 5 | |
48 | l6:6:wait:/etc/init.d/rc 6 | |
49 | # Normally not reached, but fallthrough in case of emergency. | |
50 | z6:6:respawn:/sbin/sulogin | |
51 | 1:2345:respawn:/sbin/getty 38400 console | |
b0a33c1e | 52 | c1:12345:respawn:/sbin/getty 38400 tty1 linux |
53 | c2:12345:respawn:/sbin/getty 38400 tty2 linux | |
54 | c3:12345:respawn:/sbin/getty 38400 tty3 linux | |
55 | c4:12345:respawn:/sbin/getty 38400 tty4 linux | |
f79d43bb | 56 | p6::ctrlaltdel:/sbin/init 6 |
6bf8daf9 | 57 | p0::powerfail:/sbin/init 0 |
06388011 | 58 | EOF |
06388011 | 59 | |
fb7460fe DL |
60 | # disable selinux in debian |
61 | mkdir -p $rootfs/selinux | |
62 | echo 0 > $rootfs/selinux/enforce | |
06388011 | 63 | |
fb7460fe DL |
64 | # configure the network using the dhcp |
65 | cat <<EOF > $rootfs/etc/network/interfaces | |
66 | auto lo | |
67 | iface lo inet loopback | |
06388011 | 68 | |
fb7460fe DL |
69 | auto eth0 |
70 | iface eth0 inet dhcp | |
06388011 | 71 | EOF |
1846e71a | 72 | |
fb7460fe DL |
73 | # set the hostname |
74 | cat <<EOF > $rootfs/etc/hostname | |
75 | $hostname | |
76 | EOF | |
06388011 | 77 | |
fb7460fe | 78 | # reconfigure some services |
f1fa1a08 | 79 | if [ -z "$LANG" ]; then |
14d9c0f0 SG |
80 | chroot $rootfs locale-gen en_US.UTF-8 UTF-8 |
81 | chroot $rootfs update-locale LANG=en_US.UTF-8 | |
f1fa1a08 | 82 | else |
14d9c0f0 SG |
83 | chroot $rootfs locale-gen $LANG $(echo $LANG | cut -d. -f2) |
84 | chroot $rootfs update-locale LANG=$LANG | |
f1fa1a08 | 85 | fi |
06388011 | 86 | |
fb7460fe | 87 | # remove pointless services in a container |
7593bdfb | 88 | chroot $rootfs /usr/sbin/update-rc.d -f checkroot.sh remove |
fb7460fe DL |
89 | chroot $rootfs /usr/sbin/update-rc.d -f umountfs remove |
90 | chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh remove | |
91 | chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh remove | |
19d618b1 DL |
92 | |
93 | echo "root:root" | chroot $rootfs chpasswd | |
94 | echo "Root password is 'root', please change !" | |
95 | ||
96 | return 0 | |
06388011 | 97 | } |
98 | ||
f1ccde27 SH |
99 | cleanup() |
100 | { | |
b269b8ad LV |
101 | rm -rf $cache/partial-$release-$arch |
102 | rm -rf $cache/rootfs-$release-$arch | |
f1ccde27 SH |
103 | } |
104 | ||
fb7460fe DL |
105 | download_debian() |
106 | { | |
107 | packages=\ | |
108 | ifupdown,\ | |
109 | locales,\ | |
110 | libui-dialog-perl,\ | |
111 | dialog,\ | |
06a1e1db | 112 | isc-dhcp-client,\ |
fb7460fe DL |
113 | netbase,\ |
114 | net-tools,\ | |
115 | iproute,\ | |
116 | openssh-server | |
117 | ||
118 | cache=$1 | |
119 | arch=$2 | |
b269b8ad | 120 | release=$3 |
fb7460fe | 121 | |
f1ccde27 | 122 | trap cleanup EXIT SIGHUP SIGINT SIGTERM |
fb7460fe | 123 | # check the mini debian was not already downloaded |
b269b8ad | 124 | mkdir -p "$cache/partial-$release-$arch" |
fb7460fe | 125 | if [ $? -ne 0 ]; then |
b269b8ad | 126 | echo "Failed to create '$cache/partial-$release-$arch' directory" |
14d9c0f0 | 127 | return 1 |
81f6a40a RT |
128 | fi |
129 | ||
fb7460fe DL |
130 | # download a mini debian into a cache |
131 | echo "Downloading debian minimal ..." | |
132 | debootstrap --verbose --variant=minbase --arch=$arch \ | |
14d9c0f0 | 133 | --include=$packages \ |
b269b8ad | 134 | "$release" "$cache/partial-$release-$arch" $MIRROR |
fb7460fe | 135 | if [ $? -ne 0 ]; then |
14d9c0f0 SG |
136 | echo "Failed to download the rootfs, aborting." |
137 | return 1 | |
c952d1b9 | 138 | fi |
cd830f33 | 139 | |
b269b8ad | 140 | mv "$1/partial-$release-$arch" "$1/rootfs-$release-$arch" |
fb7460fe | 141 | echo "Download complete." |
f1ccde27 SH |
142 | trap EXIT |
143 | trap SIGINT | |
144 | trap SIGTERM | |
145 | trap SIGHUP | |
cd830f33 | 146 | |
fb7460fe | 147 | return 0 |
c952d1b9 | 148 | } |
bad69158 | 149 | |
fb7460fe | 150 | copy_debian() |
c952d1b9 | 151 | { |
fb7460fe DL |
152 | cache=$1 |
153 | arch=$2 | |
154 | rootfs=$3 | |
b269b8ad | 155 | release=$4 |
bad69158 | 156 | |
fb7460fe DL |
157 | # make a local copy of the minidebian |
158 | echo -n "Copying rootfs to $rootfs..." | |
6d8ac56b | 159 | mkdir -p $rootfs |
b269b8ad | 160 | rsync -Ha "$cache/rootfs-$release-$arch"/ $rootfs/ || return 1 |
fb7460fe | 161 | return 0 |
c952d1b9 | 162 | } |
163 | ||
fb7460fe DL |
164 | install_debian() |
165 | { | |
166 | cache="@LOCALSTATEDIR@/cache/lxc/debian" | |
167 | rootfs=$1 | |
b269b8ad | 168 | release=$2 |
fb7460fe DL |
169 | mkdir -p @LOCALSTATEDIR@/lock/subsys/ |
170 | ( | |
14d9c0f0 SG |
171 | flock -x 200 |
172 | if [ $? -ne 0 ]; then | |
173 | echo "Cache repository is busy." | |
174 | return 1 | |
175 | fi | |
7afc269d | 176 | |
6efdcb6a DE |
177 | if which dpkg >/dev/null 2>&1 ; then |
178 | arch=$(dpkg --print-architecture) | |
179 | else | |
ed4616b1 | 180 | arch=$(uname -m) |
6efdcb6a DE |
181 | if [ "$arch" = "i686" ]; then |
182 | arch="i386" | |
183 | elif [ "$arch" = "x86_64" ]; then | |
184 | arch="amd64" | |
185 | elif [ "$arch" = "armv7l" ]; then | |
186 | arch="armhf" | |
187 | fi | |
188 | fi | |
bad69158 | 189 | |
b269b8ad LV |
190 | echo "Checking cache download in $cache/rootfs-$release-$arch ... " |
191 | if [ ! -e "$cache/rootfs-$release-$arch" ]; then | |
192 | download_debian $cache $arch $release | |
14d9c0f0 SG |
193 | if [ $? -ne 0 ]; then |
194 | echo "Failed to download 'debian base'" | |
195 | return 1 | |
196 | fi | |
197 | fi | |
c952d1b9 | 198 | |
b269b8ad | 199 | copy_debian $cache $arch $rootfs $release |
14d9c0f0 SG |
200 | if [ $? -ne 0 ]; then |
201 | echo "Failed to copy rootfs" | |
202 | return 1 | |
203 | fi | |
c952d1b9 | 204 | |
14d9c0f0 | 205 | return 0 |
c952d1b9 | 206 | |
fe253caa | 207 | ) 200>@LOCALSTATEDIR@/lock/subsys/lxc-debian |
85cbaa06 | 208 | |
fb7460fe | 209 | return $? |
bad69158 | 210 | } |
211 | ||
fb7460fe DL |
212 | copy_configuration() |
213 | { | |
214 | path=$1 | |
215 | rootfs=$2 | |
16501521 | 216 | hostname=$3 |
bad69158 | 217 | |
1881820a | 218 | grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config |
fb7460fe DL |
219 | cat <<EOF >> $path/config |
220 | lxc.tty = 4 | |
221 | lxc.pts = 1024 | |
16501521 | 222 | lxc.utsname = $hostname |
eee3ba81 | 223 | lxc.cap.drop = sys_module mac_admin mac_override sys_time |
f02ce27d SG |
224 | |
225 | # When using LXC with apparmor, uncomment the next line to run unconfined: | |
226 | #lxc.aa_profile = unconfined | |
227 | ||
fb7460fe DL |
228 | lxc.cgroup.devices.deny = a |
229 | # /dev/null and zero | |
230 | lxc.cgroup.devices.allow = c 1:3 rwm | |
231 | lxc.cgroup.devices.allow = c 1:5 rwm | |
232 | # consoles | |
233 | lxc.cgroup.devices.allow = c 5:1 rwm | |
234 | lxc.cgroup.devices.allow = c 5:0 rwm | |
235 | lxc.cgroup.devices.allow = c 4:0 rwm | |
236 | lxc.cgroup.devices.allow = c 4:1 rwm | |
237 | # /dev/{,u}random | |
238 | lxc.cgroup.devices.allow = c 1:9 rwm | |
239 | lxc.cgroup.devices.allow = c 1:8 rwm | |
240 | lxc.cgroup.devices.allow = c 136:* rwm | |
241 | lxc.cgroup.devices.allow = c 5:2 rwm | |
242 | # rtc | |
eee3ba81 | 243 | lxc.cgroup.devices.allow = c 254:0 rm |
a7dff834 DL |
244 | |
245 | # mounts point | |
eba7df9e SG |
246 | lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 |
247 | lxc.mount.entry = sysfs sys sysfs defaults 0 0 | |
fb7460fe | 248 | EOF |
bad69158 | 249 | |
fb7460fe | 250 | if [ $? -ne 0 ]; then |
14d9c0f0 SG |
251 | echo "Failed to add configuration" |
252 | return 1 | |
bad69158 | 253 | fi |
254 | ||
255 | return 0 | |
256 | } | |
257 | ||
fb7460fe DL |
258 | clean() |
259 | { | |
260 | cache="@LOCALSTATEDIR@/cache/lxc/debian" | |
bad69158 | 261 | |
fb7460fe | 262 | if [ ! -e $cache ]; then |
14d9c0f0 | 263 | exit 0 |
bad69158 | 264 | fi |
265 | ||
266 | # lock, so we won't purge while someone is creating a repository | |
267 | ( | |
14d9c0f0 SG |
268 | flock -x 200 |
269 | if [ $? != 0 ]; then | |
270 | echo "Cache repository is busy." | |
271 | exit 1 | |
272 | fi | |
bad69158 | 273 | |
14d9c0f0 SG |
274 | echo -n "Purging the download cache..." |
275 | rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 | |
276 | exit 0 | |
bad69158 | 277 | |
fe253caa | 278 | ) 200>@LOCALSTATEDIR@/lock/subsys/lxc-debian |
bad69158 | 279 | } |
280 | ||
fb7460fe DL |
281 | usage() |
282 | { | |
283 | cat <<EOF | |
b269b8ad | 284 | $1 -h|--help -p|--path=<path> -r|--release=<suite> --clean |
fb7460fe DL |
285 | EOF |
286 | return 0 | |
287 | } | |
288 | ||
b269b8ad | 289 | options=$(getopt -o hp:n:r:c -l help,rootfs:,path:,name:,release:,clean -- "$@") |
fb7460fe DL |
290 | if [ $? -ne 0 ]; then |
291 | usage $(basename $0) | |
14d9c0f0 | 292 | exit 1 |
fb7460fe DL |
293 | fi |
294 | eval set -- "$options" | |
295 | ||
296 | while true | |
297 | do | |
298 | case "$1" in | |
b269b8ad | 299 | -h|--help) usage $0 && exit 1;; |
fb7460fe | 300 | -p|--path) path=$2; shift 2;; |
1897e3bc | 301 | --rootfs) rootfs=$2; shift 2;; |
b269b8ad | 302 | -r|--release) release=$2; shift 2;; |
14d9c0f0 SG |
303 | -n|--name) name=$2; shift 2;; |
304 | -c|--clean) clean=$2; shift 2;; | |
fb7460fe DL |
305 | --) shift 1; break ;; |
306 | *) break ;; | |
307 | esac | |
308 | done | |
309 | ||
310 | if [ ! -z "$clean" -a -z "$path" ]; then | |
311 | clean || exit 1 | |
312 | exit 0 | |
313 | fi | |
314 | ||
315 | type debootstrap | |
316 | if [ $? -ne 0 ]; then | |
317 | echo "'debootstrap' command is missing" | |
318 | exit 1 | |
319 | fi | |
320 | ||
321 | if [ -z "$path" ]; then | |
322 | echo "'path' parameter is required" | |
323 | exit 1 | |
324 | fi | |
325 | ||
326 | if [ "$(id -u)" != "0" ]; then | |
327 | echo "This script should be run as 'root'" | |
328 | exit 1 | |
c01d62f2 | 329 | fi |
bad69158 | 330 | |
b269b8ad LV |
331 | current_release=`wget ${MIRROR}/dists/stable/Release -O - 2>/dev/null |\ |
332 | head |awk '/^Codename: (.*)$/ { print $2; }'` | |
333 | release=${release:-${current_release}} | |
334 | valid_releases=('squeeze' 'wheezy' 'jessie' 'sid') | |
335 | if [[ ! "${valid_releases[*]}" =~ (^|[^[:alpha:]])$release([^[:alpha:]]|$) ]] | |
336 | then | |
337 | echo "Invalid release ${release}, valid ones are: ${valid_releases[*]}" | |
338 | exit 1 | |
339 | fi | |
340 | ||
1881820a SH |
341 | # detect rootfs |
342 | config="$path/config" | |
1897e3bc SH |
343 | if [ -z "$rootfs" ]; then |
344 | if grep -q '^lxc.rootfs' $config 2>/dev/null ; then | |
345 | rootfs=`grep 'lxc.rootfs =' $config | awk -F= '{ print $2 }'` | |
346 | else | |
347 | rootfs=$path/rootfs | |
348 | fi | |
1881820a SH |
349 | fi |
350 | ||
fb7460fe | 351 | |
b269b8ad | 352 | install_debian $rootfs $release |
fb7460fe DL |
353 | if [ $? -ne 0 ]; then |
354 | echo "failed to install debian" | |
355 | exit 1 | |
356 | fi | |
357 | ||
358 | configure_debian $rootfs $name | |
359 | if [ $? -ne 0 ]; then | |
360 | echo "failed to configure debian for a container" | |
361 | exit 1 | |
362 | fi | |
363 | ||
16501521 | 364 | copy_configuration $path $rootfs $name |
fb7460fe DL |
365 | if [ $? -ne 0 ]; then |
366 | echo "failed write configuration file" | |
367 | exit 1 | |
368 | fi | |
369 | ||
370 | if [ ! -z $clean ]; then | |
371 | clean || exit 1 | |
372 | exit 0 | |
373 | fi |