1 |
dpavlin |
174 |
#!/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 |
|
|
download_debian() |
99 |
|
|
{ |
100 |
|
|
packages=\ |
101 |
|
|
ifupdown,\ |
102 |
|
|
locales,\ |
103 |
|
|
libui-dialog-perl,\ |
104 |
|
|
dialog,\ |
105 |
|
|
dhcp-client,\ |
106 |
|
|
netbase,\ |
107 |
|
|
net-tools,\ |
108 |
|
|
iproute,\ |
109 |
|
|
openssh-server |
110 |
|
|
|
111 |
|
|
cache=$1 |
112 |
|
|
arch=$2 |
113 |
|
|
|
114 |
|
|
# check the mini debian was not already downloaded |
115 |
|
|
mkdir -p "$cache/partial-$arch" |
116 |
|
|
if [ $? -ne 0 ]; then |
117 |
|
|
echo "Failed to create '$cache/partial-$arch' directory" |
118 |
|
|
return 1 |
119 |
|
|
fi |
120 |
|
|
|
121 |
|
|
# download a mini debian into a cache |
122 |
|
|
echo "Downloading debian minimal ..." |
123 |
|
|
debootstrap --verbose --variant=minbase --arch=$arch \ |
124 |
|
|
--include $packages \ |
125 |
|
|
lenny $cache/partial-$arch http://ftp.debian.org/debian |
126 |
|
|
if [ $? -ne 0 ]; then |
127 |
|
|
echo "Failed to download the rootfs, aborting." |
128 |
|
|
return 1 |
129 |
|
|
fi |
130 |
|
|
|
131 |
|
|
mv "$1/partial-$arch" "$1/rootfs-$arch" |
132 |
|
|
echo "Download complete." |
133 |
|
|
|
134 |
|
|
return 0 |
135 |
|
|
} |
136 |
|
|
|
137 |
|
|
copy_debian() |
138 |
|
|
{ |
139 |
|
|
cache=$1 |
140 |
|
|
arch=$2 |
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 |
|
|
arch=$(arch) |
162 |
|
|
if [ "$arch" == "x86_64" ]; then |
163 |
|
|
arch=amd64 |
164 |
|
|
fi |
165 |
|
|
|
166 |
|
|
if [ "$arch" == "i686" ]; then |
167 |
|
|
arch=i386 |
168 |
|
|
fi |
169 |
|
|
|
170 |
|
|
echo "Checking cache download in $cache/rootfs-$arch ... " |
171 |
|
|
if [ ! -e "$cache/rootfs-$arch" ]; then |
172 |
|
|
download_debian $cache $arch |
173 |
|
|
if [ $? -ne 0 ]; then |
174 |
|
|
echo "Failed to download 'debian base'" |
175 |
|
|
return 1 |
176 |
|
|
fi |
177 |
|
|
fi |
178 |
|
|
|
179 |
|
|
copy_debian $cache $arch $rootfs |
180 |
|
|
if [ $? -ne 0 ]; then |
181 |
|
|
echo "Failed to copy rootfs" |
182 |
|
|
return 1 |
183 |
|
|
fi |
184 |
|
|
|
185 |
|
|
return 0 |
186 |
|
|
|
187 |
|
|
) 200>/var/lock/subsys/lxc |
188 |
|
|
|
189 |
|
|
return $? |
190 |
|
|
} |
191 |
|
|
|
192 |
|
|
copy_configuration() |
193 |
|
|
{ |
194 |
|
|
path=$1 |
195 |
|
|
rootfs=$2 |
196 |
|
|
name=$3 |
197 |
|
|
|
198 |
|
|
cat <<EOF >> $path/config |
199 |
|
|
lxc.tty = 4 |
200 |
|
|
lxc.pts = 1024 |
201 |
|
|
lxc.rootfs = $rootfs |
202 |
|
|
lxc.cgroup.devices.deny = a |
203 |
|
|
# /dev/null and zero |
204 |
|
|
lxc.cgroup.devices.allow = c 1:3 rwm |
205 |
|
|
lxc.cgroup.devices.allow = c 1:5 rwm |
206 |
|
|
# consoles |
207 |
|
|
lxc.cgroup.devices.allow = c 5:1 rwm |
208 |
|
|
lxc.cgroup.devices.allow = c 5:0 rwm |
209 |
|
|
lxc.cgroup.devices.allow = c 4:0 rwm |
210 |
|
|
lxc.cgroup.devices.allow = c 4:1 rwm |
211 |
|
|
# /dev/{,u}random |
212 |
|
|
lxc.cgroup.devices.allow = c 1:9 rwm |
213 |
|
|
lxc.cgroup.devices.allow = c 1:8 rwm |
214 |
|
|
lxc.cgroup.devices.allow = c 136:* rwm |
215 |
|
|
lxc.cgroup.devices.allow = c 5:2 rwm |
216 |
|
|
# rtc |
217 |
|
|
lxc.cgroup.devices.allow = c 254:0 rwm |
218 |
|
|
EOF |
219 |
|
|
|
220 |
|
|
if [ $? -ne 0 ]; then |
221 |
|
|
echo "Failed to add configuration" |
222 |
|
|
return 1 |
223 |
|
|
fi |
224 |
|
|
|
225 |
|
|
return 0 |
226 |
|
|
} |
227 |
|
|
|
228 |
|
|
clean() |
229 |
|
|
{ |
230 |
|
|
cache="/var/cache/lxc/debian" |
231 |
|
|
|
232 |
|
|
if [ ! -e $cache ]; then |
233 |
|
|
exit 0 |
234 |
|
|
fi |
235 |
|
|
|
236 |
|
|
# lock, so we won't purge while someone is creating a repository |
237 |
|
|
( |
238 |
|
|
flock -n -x 200 |
239 |
|
|
if [ $? != 0 ]; then |
240 |
|
|
echo "Cache repository is busy." |
241 |
|
|
exit 1 |
242 |
|
|
fi |
243 |
|
|
|
244 |
|
|
echo -n "Purging the download cache..." |
245 |
|
|
rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 |
246 |
|
|
exit 0 |
247 |
|
|
|
248 |
|
|
) 200>/var/lock/subsys/lxc |
249 |
|
|
} |
250 |
|
|
|
251 |
|
|
usage() |
252 |
|
|
{ |
253 |
|
|
cat <<EOF |
254 |
|
|
$1 -h|--help -p|--path=<path> --clean |
255 |
|
|
EOF |
256 |
|
|
return 0 |
257 |
|
|
} |
258 |
|
|
|
259 |
|
|
options=$(getopt -o hp:n:c -l help,path:,name:,clean -- "$@") |
260 |
|
|
if [ $? -ne 0 ]; then |
261 |
|
|
usage $(basename $0) |
262 |
|
|
exit 1 |
263 |
|
|
fi |
264 |
|
|
eval set -- "$options" |
265 |
|
|
|
266 |
|
|
while true |
267 |
|
|
do |
268 |
|
|
case "$1" in |
269 |
|
|
-h|--help) usage $0 && exit 0;; |
270 |
|
|
-p|--path) path=$2; shift 2;; |
271 |
|
|
-n|--name) name=$2; shift 2;; |
272 |
|
|
-c|--clean) clean=$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 |