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 |