]>
Commit | Line | Data |
---|---|---|
9aad9d12 AK |
1 | #!/bin/bash |
2 | ||
3 | # | |
4 | # template script for generating openmandriva container for LXC | |
5 | # | |
6 | ||
7 | # | |
8 | # lxc: linux Container library | |
9 | ||
10 | # Authors: | |
11 | # Alexander Khryukin <alexander@mezon.ru> | |
12 | # Vokhmin Alexey V <avokhmin@gmail.com> | |
13 | ||
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. | |
18 | ||
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. | |
23 | ||
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 | |
27 | # | |
28 | ||
8ec981fc | 29 | # Detect use under userns (unsupported) |
c63c04fc | 30 | for arg in "$@"; do |
96283b54 SG |
31 | [ "$arg" = "--" ] && break |
32 | if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then | |
8ec981fc SG |
33 | echo "This template can't be used for unprivileged containers." 1>&2 |
34 | echo "You may want to try the \"download\" template instead." 1>&2 | |
35 | exit 1 | |
36 | fi | |
37 | done | |
38 | ||
207bf0e4 SG |
39 | # Make sure the usual locations are in PATH |
40 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin | |
41 | ||
9aad9d12 AK |
42 | #Configurations |
43 | #distro=cooker | |
44 | hostarch=$(uname -m) | |
6dc6f80b KC |
45 | # Allow the cache base to be set by environment variable |
46 | cache_base="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/openmandriva/$arch}" | |
9aad9d12 AK |
47 | default_path=@LXCPATH@ |
48 | default_profile=default | |
9aad9d12 AK |
49 | lxc_network_type=veth |
50 | lxc_network_link=br0 | |
51 | ||
52 | # is this openmandriva? | |
53 | [ -f /etc/mandriva-release ] && is_openmandriva=true | |
54 | ||
55 | configure_openmandriva() | |
56 | { | |
57 | mkdir -p ${rootfs_path}/etc/sysconfig/network-scripts/ | |
58 | ||
59 | # configure the network using the dhcp | |
60 | cat <<EOF > ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0 | |
61 | DEVICE=eth0 | |
62 | ONBOOT=yes | |
63 | BOOTPROTO=dhcp | |
64 | NM_CONTROLLED=no | |
65 | HOSTNAME=${utsname} | |
66 | EOF | |
67 | ||
68 | # set the hostname | |
69 | cat <<EOF > ${rootfs_path}/etc/sysconfig/network | |
70 | NETWORKING=yes | |
71 | HOSTNAME=${utsname} | |
72 | EOF | |
73 | ||
74 | echo "${utsname}" > ${rootfs_path}/etc/hostname | |
75 | ||
76 | # set minimal hosts | |
77 | cat <<EOF > $rootfs_path/etc/hosts | |
78 | 127.0.0.1 localhost.localdomain localhost $utsname | |
79 | ::1 localhost6.localdomain6 localhost6 | |
80 | EOF | |
81 | } | |
82 | ||
83 | populate_dev() | |
84 | { | |
edcf9b59 | 85 | echo -n "Create devices in /dev/" |
9aad9d12 AK |
86 | dev_path="${rootfs_path}/dev" |
87 | rm -rf $dev_path | |
88 | mkdir -p $dev_path | |
89 | mknod -m 666 ${dev_path}/null c 1 3 | |
90 | mknod -m 666 ${dev_path}/zero c 1 5 | |
91 | mknod -m 666 ${dev_path}/random c 1 8 | |
92 | mknod -m 666 ${dev_path}/urandom c 1 9 | |
93 | mkdir -m 755 ${dev_path}/pts | |
94 | mkdir -m 1777 ${dev_path}/shm | |
95 | mknod -m 666 ${dev_path}/tty c 5 0 | |
96 | mknod -m 666 ${dev_path}/tty0 c 4 0 | |
97 | mknod -m 666 ${dev_path}/tty1 c 4 1 | |
98 | mknod -m 666 ${dev_path}/tty2 c 4 2 | |
99 | mknod -m 666 ${dev_path}/tty3 c 4 3 | |
100 | mknod -m 666 ${dev_path}/tty4 c 4 4 | |
101 | mknod -m 600 ${dev_path}/console c 5 1 | |
102 | mknod -m 666 ${dev_path}/full c 1 7 | |
103 | mknod -m 600 ${dev_path}/initctl p | |
104 | mknod -m 666 ${dev_path}/ptmx c 5 2 | |
105 | mkdir -m 755 ${dev_path}/net | |
edcf9b59 | 106 | mknod -m 666 ${dev_path}/net/tun c 10 200 |
9aad9d12 AK |
107 | |
108 | } | |
109 | ||
110 | set_guest_root_password() | |
111 | { | |
17abf278 | 112 | [ -z "$root_password" ] && return # pass is empty, abort |
9aad9d12 | 113 | |
aa1c458c AK |
114 | echo " - setting guest root password.." |
115 | echo "root passwd is: $root_password" | |
9aad9d12 AK |
116 | echo "root:$root_password" | chroot "$rootfs_path" chpasswd |
117 | echo "done." | |
118 | } | |
119 | ||
120 | create_chroot_openmandriva() | |
121 | { | |
122 | # check the mini openmandriva was not already downloaded | |
123 | INSTALL_ROOT=$cache/cache | |
124 | mkdir -p $INSTALL_ROOT | |
125 | if [ $? -ne 0 ]; then | |
126 | echo "Failed to create '$INSTALL_ROOT' directory" | |
127 | return 1 | |
128 | fi | |
129 | # package list to install | |
edcf9b59 | 130 | PKG_LIST="basesystem-minimal locales locales-en initscripts urpmi cronie dhcp-client kbd" |
9aad9d12 AK |
131 | # download a mini openmandriva into a cache |
132 | echo "Downloading openmandriva minimal ..." | |
9aad9d12 AK |
133 | URPMI="/usr/sbin/urpmi.addmedia --urpmi-root $INSTALL_ROOT main http://abf.rosalinux.ru/downloads/$release/repository/$arch/main/release" |
134 | echo $URPMI | |
135 | URPMI_BASE="/usr/sbin/urpmi --no-suggests --no-verify-rpm --ignorearch --root $INSTALL_ROOT --urpmi-root $INSTALL_ROOT --auto $PKG_LIST" | |
136 | $URPMI | |
137 | $URPMI_BASE | |
138 | # We're splitting the old loop into two loops plus a directory retrival. | |
139 | # First loop... Try and retrive a mirror list with retries and a slight | |
140 | # delay between attempts... | |
141 | if [ $? -ne 0 ]; then | |
142 | echo "Failed to download the rootfs, aborting." | |
143 | return 1 | |
144 | fi | |
145 | ||
146 | mv "$INSTALL_ROOT" "$cache/rootfs" | |
147 | echo "Download complete." | |
148 | ||
149 | return 0 | |
150 | ||
151 | } | |
152 | ||
153 | copy_openmandriva() | |
154 | { | |
155 | ||
156 | echo -n "Copying rootfs to $rootfs_path ..." | |
157 | mkdir -p $rootfs_path | |
6273aef1 | 158 | rsync -SHaAX $cache/rootfs/ $rootfs_path/ |
9aad9d12 AK |
159 | return 0 |
160 | } | |
161 | ||
162 | update_openmandriva() | |
163 | { | |
164 | echo "automated update in progress..." | |
aa1c458c | 165 | urpmi --root $cache/rootfs --urpmi-root $cache/rootfs --auto --auto-update --ignorearch |
9aad9d12 AK |
166 | } |
167 | ||
edcf9b59 AK |
168 | configure_openmandriva_systemd() |
169 | { | |
170 | chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/proc-sys-fs-binfmt_misc.automount | |
171 | chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd.service | |
172 | chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd-control.socket | |
173 | chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd-kernel.socket | |
174 | # remove numlock service | |
175 | # KDGKBLED: Inappropriate ioctl for device | |
176 | rm -f ${rootfs_path}/etc/systemd/system/getty@.service.d/enable-numlock.conf | |
177 | ||
178 | unlink ${rootfs_path}/etc/systemd/system/default.target | |
179 | chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target | |
180 | sed -i 's!ConditionPathExists=/dev/tty0!ConditionPathExists=|/dev/tty0\nConditionVirtualization=|lxc!' \ | |
181 | ${rootfs_path}/lib/systemd/system/getty\@.service | |
182 | } | |
183 | ||
184 | ||
9aad9d12 AK |
185 | install_openmandriva() |
186 | { | |
187 | mkdir -p @LOCALSTATEDIR@/lock/subsys/ | |
188 | ( | |
17abf278 | 189 | flock -x 9 |
9aad9d12 AK |
190 | if [ $? -ne 0 ]; then |
191 | echo "Cache repository is busy." | |
192 | return 1 | |
193 | fi | |
194 | ||
195 | echo "Checking cache download in $cache/rootfs ... " | |
196 | if [ ! -e "$cache/rootfs" ]; then | |
c01c25fc | 197 | echo $cache/rootfs |
9aad9d12 AK |
198 | create_chroot_openmandriva |
199 | if [ $? -ne 0 ]; then | |
200 | echo "Failed to download 'openmandriva basesystem-minimal'" | |
201 | return 1 | |
202 | fi | |
203 | else | |
204 | echo "Cache found. Updating..." | |
205 | update_openmandriva | |
206 | if [ $? -ne 0 ]; then | |
207 | echo "Failed to update 'openmandriva base', continuing with last known good cache" | |
208 | else | |
209 | echo "Update finished" | |
210 | fi | |
211 | fi | |
212 | ||
213 | echo "Copy $cache/rootfs to $rootfs_path ... " | |
214 | copy_openmandriva | |
215 | if [ $? -ne 0 ]; then | |
216 | echo "Failed to copy rootfs" | |
217 | return 1 | |
218 | fi | |
219 | return 0 | |
17abf278 | 220 | ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-openmandriva |
9aad9d12 AK |
221 | |
222 | return $? | |
223 | } | |
224 | ||
225 | copy_configuration() | |
226 | { | |
227 | ||
228 | mkdir -p $config_path | |
7a96a068 | 229 | grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs_path" >> $config_path/config |
9aad9d12 | 230 | cat <<EOF >> $config_path/config |
b67771bc | 231 | lxc.uts.name = $name |
fe1c5887 | 232 | lxc.tty.max = 4 |
232763d6 | 233 | lxc.pty.max = 1024 |
9aad9d12 | 234 | lxc.cap.drop = sys_module mac_admin mac_override sys_time |
f24a52d5 | 235 | lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed |
9aad9d12 AK |
236 | |
237 | # When using LXC with apparmor, uncomment the next line to run unconfined: | |
a1d5fdfd | 238 | #lxc.apparmor.profile = unconfined |
9aad9d12 AK |
239 | |
240 | #networking | |
7fa3f2e9 | 241 | lxc.net.0.type = $lxc_network_type |
242 | lxc.net.0.flags = up | |
243 | lxc.net.0.link = $lxc_network_link | |
244 | lxc.net.0.name = eth0 | |
245 | lxc.net.0.mtu = 1500 | |
9aad9d12 AK |
246 | EOF |
247 | if [ ! -z ${ipv4} ]; then | |
248 | cat <<EOF >> $config_path/config | |
9ff60df2 | 249 | lxc.net.0.ipv4.address = $ipv4 |
9aad9d12 AK |
250 | EOF |
251 | fi | |
252 | if [ ! -z ${gw} ]; then | |
253 | cat <<EOF >> $config_path/config | |
7fa3f2e9 | 254 | lxc.net.0.ipv4.gateway = $gw |
9aad9d12 AK |
255 | EOF |
256 | fi | |
257 | if [ ! -z ${ipv6} ]; then | |
258 | cat <<EOF >> $config_path/config | |
2e44ae28 | 259 | lxc.net.0.ipv6.address = $ipv6 |
9aad9d12 AK |
260 | EOF |
261 | fi | |
262 | if [ ! -z ${gw6} ]; then | |
263 | cat <<EOF >> $config_path/config | |
7fa3f2e9 | 264 | lxc.net.0.ipv6.gateway = $gw6 |
9aad9d12 AK |
265 | EOF |
266 | fi | |
267 | cat <<EOF >> $config_path/config | |
268 | #cgroups | |
269 | lxc.cgroup.devices.deny = a | |
270 | # /dev/null and zero | |
271 | lxc.cgroup.devices.allow = c 1:3 rwm | |
272 | lxc.cgroup.devices.allow = c 1:5 rwm | |
273 | # consoles | |
274 | lxc.cgroup.devices.allow = c 5:1 rwm | |
275 | lxc.cgroup.devices.allow = c 5:0 rwm | |
276 | lxc.cgroup.devices.allow = c 4:0 rwm | |
277 | lxc.cgroup.devices.allow = c 4:1 rwm | |
278 | # /dev/{,u}random | |
279 | lxc.cgroup.devices.allow = c 1:9 rwm | |
280 | lxc.cgroup.devices.allow = c 1:8 rwm | |
281 | lxc.cgroup.devices.allow = c 136:* rwm | |
282 | lxc.cgroup.devices.allow = c 5:2 rwm | |
283 | # rtc | |
284 | lxc.cgroup.devices.allow = c 10:135 rwm | |
9aad9d12 AK |
285 | EOF |
286 | ||
287 | if [ $? -ne 0 ]; then | |
288 | echo "Failed to add configuration" | |
289 | return 1 | |
290 | fi | |
291 | ||
292 | return 0 | |
293 | } | |
294 | ||
295 | clean() | |
296 | { | |
297 | ||
298 | if [ ! -e $cache ]; then | |
299 | exit 0 | |
300 | fi | |
301 | ||
302 | # lock, so we won't purge while someone is creating a repository | |
303 | ( | |
17abf278 | 304 | flock -x 9 |
9aad9d12 AK |
305 | if [ $? != 0 ]; then |
306 | echo "Cache repository is busy." | |
307 | exit 1 | |
308 | fi | |
309 | ||
310 | echo -n "Purging the download cache for OpenMandriva-$release..." | |
311 | rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 | |
312 | exit 0 | |
17abf278 | 313 | ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-openmandriva |
9aad9d12 AK |
314 | } |
315 | ||
316 | usage() | |
317 | { | |
318 | cat <<EOF | |
319 | usage: | |
320 | $1 -n|--name=<container_name> | |
321 | [-p|--path=<path>] [-c|--clean] [-R|--release=<openmandriva2013.0/rosa2012.1/cooker/ release>] | |
322 | [-4|--ipv4=<ipv4 address>] [-6|--ipv6=<ipv6 address>] | |
323 | [-g|--gw=<gw address>] [-d|--dns=<dns address>] | |
324 | [-P|--profile=<name of the profile>] [--rootfs=<path>] | |
325 | [-A|--arch=<arch of the container>] | |
326 | [-h|--help] | |
327 | Mandatory args: | |
328 | -n,--name container name, used to as an identifier for that container from now on | |
329 | Optional args: | |
330 | -p,--path path to where the container rootfs will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case | |
331 | -c,--clean clean the cache | |
332 | -R,--release openmandriva2013.0/cooker/rosa2012.1 release for the new container. if the host is OpenMandriva, then it will default to the host's release. | |
333 | -4,--ipv4 specify the ipv4 address to assign to the virtualized interface, eg. 192.168.1.123/24 | |
334 | -6,--ipv6 specify the ipv6 address to assign to the virtualized interface, eg. 2003:db8:1:0:214:1234:fe0b:3596/64 | |
335 | -g,--gw specify the default gw, eg. 192.168.1.1 | |
336 | -G,--gw6 specify the default gw, eg. 2003:db8:1:0:214:1234:fe0b:3596 | |
337 | -d,--dns specify the DNS server, eg. 192.168.1.2 | |
338 | -P,--profile Profile name is the file name in /etc/lxc/profiles contained packages name for install to cache. | |
339 | -A,--arch Define what arch the container will be [i586,x86_64,armv7l,armv7hl] | |
340 | ---rootfs rootfs path | |
341 | -h,--help print this help | |
342 | EOF | |
343 | return 0 | |
344 | } | |
345 | ||
346 | options=$(getopt -o hp:n:P:cR:4:6:g:d:A -l help,rootfs:,path:,name:,profile:,clean:,release:,ipv4:,ipv6:,gw:,dns:,arch: -- "$@") | |
347 | if [ $? -ne 0 ]; then | |
348 | usage $(basename $0) | |
349 | exit 1 | |
350 | fi | |
351 | eval set -- "$options" | |
352 | ||
f7f1ba77 | 353 | release=${release:-"cooker"} |
9aad9d12 AK |
354 | if [ -f /etc/lsb-release ]; then |
355 | . /etc/lsb-release | |
356 | if [ "$DISTRIB_ID" = "OpenMandrivaLinux" ]; then | |
357 | release=openmandriva2013.0 | |
358 | elif [ "$DISTRIB_ID" = "RosaDesktop.Fresh" ]; then | |
c01c25fc | 359 | release=rosa2012.1 |
9aad9d12 | 360 | else |
c01c25fc | 361 | echo "This is not an OpenMandriva or ROSA release" |
9aad9d12 AK |
362 | exit 1 |
363 | fi | |
364 | fi | |
365 | ||
366 | while true | |
367 | do | |
368 | case "$1" in | |
369 | -h|--help) usage $0 && exit 0;; | |
370 | -p|--path) path=$2; shift 2;; | |
371 | --rootfs) rootfs_path=$2; shift 2;; | |
372 | -n|--name) name=$2; shift 2;; | |
373 | -P|--profile) profile=$2; shift 2;; | |
fe9d4df4 | 374 | -c|--clean) clean=1; shift 1;; |
9aad9d12 | 375 | -R|--release) release=$2; shift 2;; |
cd2738c4 | 376 | -A|--arch) arch=$2; shift 2;; |
9aad9d12 AK |
377 | -4|--ipv4) ipv4=$2; shift 2;; |
378 | -6|--ipv6) ipv6=$2; shift 2;; | |
379 | -g|--gw) gw=$2; shift 2;; | |
380 | -d|--dns) dns=$2; shift 2;; | |
381 | --) shift 1; break ;; | |
382 | *) break ;; | |
383 | esac | |
384 | done | |
385 | ||
386 | arch=${arch:-$hostarch} | |
387 | ||
388 | if [ ! -z "$clean" -a -z "$path" ]; then | |
389 | clean || exit 1 | |
390 | exit 0 | |
391 | fi | |
392 | ||
edcf9b59 AK |
393 | if [ -z "${utsname}" ]; then |
394 | utsname=${name} | |
395 | fi | |
396 | ||
9aad9d12 AK |
397 | type urpmi >/dev/null 2>&1 |
398 | if [ $? -ne 0 ]; then | |
399 | echo "'urpmi' command is missing" | |
400 | exit 1 | |
401 | fi | |
402 | ||
403 | if [ -z "$path" ]; then | |
404 | path=$default_path | |
405 | fi | |
406 | ||
407 | if [ -z "$profile" ]; then | |
408 | profile=$default_profile | |
409 | fi | |
410 | ||
411 | if [ $hostarch = "i586" -a $arch = "x86_64" ]; then | |
412 | echo "can't create x86_64 container on i586" | |
413 | exit 1 | |
414 | fi | |
415 | ||
416 | if [ -z "$ipv4" -a -z "$ipv6" ]; then | |
417 | BOOTPROTO="dhcp" | |
418 | else | |
419 | BOOTPROTO="static" | |
420 | fi | |
421 | ||
422 | if [ "$(id -u)" != "0" ]; then | |
423 | echo "This script should be run as 'root'" | |
424 | exit 1 | |
425 | fi | |
426 | ||
7a96a068 | 427 | # check for 'lxc.rootfs.path' passed in through default config by lxc-create |
9aad9d12 | 428 | if [ -z "$rootfs_path" ]; then |
7a96a068 CB |
429 | if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then |
430 | rootfs_path=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config) | |
9aad9d12 AK |
431 | else |
432 | rootfs_path=$path/$name/rootfs | |
433 | fi | |
434 | fi | |
435 | ||
436 | config_path=$default_path/$name | |
7d35d3a7 | 437 | cache=$cache_base/$release/$arch/$profile |
9aad9d12 AK |
438 | |
439 | if [ ! -f $config_path/config ]; then | |
440 | echo "A container with that name exists, chose a different name" | |
441 | exit 1 | |
442 | fi | |
443 | ||
444 | install_openmandriva | |
445 | if [ $? -ne 0 ]; then | |
446 | echo "failed to install openmandriva" | |
447 | exit 1 | |
448 | fi | |
449 | ||
450 | configure_openmandriva | |
451 | if [ $? -ne 0 ]; then | |
452 | echo "failed to configure openmandriva for a container" | |
453 | exit 1 | |
454 | fi | |
455 | ||
edcf9b59 AK |
456 | # If the systemd configuration directory exists - set it up for what we need. |
457 | if [ -d ${rootfs_path}/etc/systemd/system ] | |
458 | then | |
459 | configure_openmandriva_systemd | |
460 | fi | |
461 | ||
9aad9d12 AK |
462 | populate_dev |
463 | if [ $? -ne 0 ]; then | |
464 | echo "failed to populated /dev/ devices" | |
465 | exit 1 | |
466 | fi | |
467 | ||
468 | set_guest_root_password | |
469 | if [ $? -ne 0 ]; then | |
470 | echo "failed to configure password for chroot" | |
471 | exit 1 | |
472 | fi | |
473 | ||
474 | copy_configuration | |
475 | if [ $? -ne 0 ]; then | |
476 | echo "failed write configuration file" | |
477 | exit 1 | |
478 | fi | |
479 | ||
c4834f3c | 480 | if [ ! -z "$clean" ]; then |
9aad9d12 AK |
481 | clean || exit 1 |
482 | exit 0 | |
483 | fi | |
484 | echo "container rootfs and config created" |