]> git.proxmox.com Git - mirror_lxc.git/blame - templates/lxc-altlinux.in
lxc-oci: rely on jq instead of sed to transform values
[mirror_lxc.git] / templates / lxc-altlinux.in
CommitLineData
262f4e48
AS
1#!/bin/bash
2
3#
4# template script for generating altlinux container for LXC
5#
6
7#
8# lxc: linux Container library
9
10# Authors:
11# Alexey Shabalin <shaba@altlinux.org>
12
13# This library is free software; you can redistribute it and/or
14# modify it under the terms of the GNU Lesser General Public
15# License as published by the Free Software Foundation; either
16# version 2.1 of the License, or (at your option) any later version.
17
18# This library is distributed in the hope that it will be useful,
19# but WITHOUT ANY WARRANTY; without even the implied warranty of
14d9c0f0 20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
262f4e48
AS
21# Lesser General Public License for more details.
22
23# You should have received a copy of the GNU Lesser General Public
24# License along with this library; if not, write to the Free Software
250b1eec 25# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
262f4e48 26
8ec981fc 27# Detect use under userns (unsupported)
c63c04fc 28for arg in "$@"; do
96283b54
SG
29 [ "$arg" = "--" ] && break
30 if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
8ec981fc
SG
31 echo "This template can't be used for unprivileged containers." 1>&2
32 echo "You may want to try the \"download\" template instead." 1>&2
33 exit 1
34 fi
35done
36
207bf0e4
SG
37# Make sure the usual locations are in PATH
38export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
39
262f4e48 40#Configurations
ed4616b1 41arch=$(uname -m)
e29bf450 42cache_base=@LOCALSTATEDIR@/cache/lxc/altlinux/$arch
b031f0d2 43default_path=@LXCPATH@
262f4e48
AS
44default_profile=default
45profile_dir=/etc/lxc/profiles
262f4e48
AS
46lxc_network_type=veth
47lxc_network_link=virbr0
48
49# is this altlinux?
50[ -f /etc/altlinux-release ] && is_altlinux=true
51
52configure_altlinux()
53{
54
55 # disable selinux in altlinux
56 mkdir -p $rootfs_path/selinux
57 echo 0 > $rootfs_path/selinux/enforce
58
5c60f990
DP
59 mkdir -p ${rootfs_path}/etc/net/ifaces/eth0
60 cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/options
b031f0d2 61BOOTPROTO=${BOOTPROTO}
262f4e48 62ONBOOT=yes
5c60f990 63NM_CONTROLLED=yes
262f4e48
AS
64TYPE=eth
65EOF
66
b031f0d2
AS
67if [ ${BOOTPROTO} != "dhcp" ]; then
68 # ip address
5c60f990 69 cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/ipv4address
b031f0d2
AS
70${ipv4}
71EOF
72
5c60f990 73 cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/ipv4route
b031f0d2
AS
74${gw}
75EOF
76
5c60f990 77 cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/resolv.conf
b031f0d2
AS
78nameserver ${dns}
79EOF
80
5c60f990 81 cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/ipv6address
b031f0d2
AS
82${ipv6}
83EOF
84
5c60f990 85 cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/ipv6route
b031f0d2
AS
86${gw6}
87EOF
88
89fi
90
262f4e48
AS
91 # set the hostname
92 cat <<EOF > ${rootfs_path}/etc/sysconfig/network
93NETWORKING=yes
94CONFMETHOD=etcnet
95HOSTNAME=${UTSNAME}
96RESOLV_MODS=yes
97EOF
98
99 # set minimal hosts
100 cat <<EOF > $rootfs_path/etc/hosts
101127.0.0.1 localhost.localdomain localhost $name
102EOF
103 # Allow to login at virsh console. loginuid.so doen't work in the absence of auditd.
b031f0d2 104# sed -i 's/^.*loginuid.so.*$/\#&/' ${rootfs_path}/etc/pam.d/common-login
262f4e48
AS
105
106 # Allow root to login at virsh console
107 echo "pts/0" >> ${rootfs_path}/etc/securetty
b031f0d2 108 echo "console" >> ${rootfs_path}/etc/securetty
262f4e48 109
05e61b82 110 # Enable services
5c60f990 111 for service in network syslogd random NetworkManager
05e61b82
DP
112 do
113 chroot ${rootfs_path} chkconfig $service --list &>/dev/null && chroot ${rootfs_path} chkconfig $service on || true
5c60f990
DP
114 # For systemd
115 chroot ${rootfs_path} systemctl -q enable $service &>/dev/null|| true
05e61b82
DP
116 done
117 # Disable services
118 for service in rawdevices fbsetfont
119 do
120 chroot ${rootfs_path} chkconfig $service --list &>/dev/null && chroot ${rootfs_path} chkconfig $service off || true
5c60f990 121 chroot ${rootfs_path} systemctl -q disable $service &>/dev/null || true
05e61b82 122 done
262f4e48 123
b031f0d2
AS
124 subst 's/^\([3-9]\+:[0-9]\+:respawn:\/sbin\/mingetty.*\)/#\1/' ${rootfs_path}/etc/inittab
125 echo "c1:2345:respawn:/sbin/mingetty --noclear console" >> ${rootfs_path}/etc/inittab
05e61b82
DP
126
127 [ -f "${rootfs_path}/etc/syslog.conf" ] && \
128 subst 's,\/dev\/tty12,/var/log/syslog/console,' ${rootfs_path}/etc/syslog.conf
262f4e48
AS
129
130 dev_path="${rootfs_path}/dev"
b031f0d2
AS
131 rm -rf ${dev_path}
132 mkdir -p ${dev_path}
262f4e48
AS
133 mknod -m 666 ${dev_path}/null c 1 3
134 mknod -m 666 ${dev_path}/zero c 1 5
135 mknod -m 644 ${dev_path}/random c 1 8
136 mknod -m 644 ${dev_path}/urandom c 1 9
137 mkdir -m 755 ${dev_path}/pts
138 mkdir -m 1777 ${dev_path}/shm
139 mknod -m 666 ${dev_path}/tty c 5 0
b031f0d2
AS
140 chown root:tty ${dev_path}/tty
141 mknod -m 600 ${dev_path}/tty0 c 4 0
142 mknod -m 600 ${dev_path}/tty1 c 4 1
143 mknod -m 600 ${dev_path}/tty2 c 4 2
144 mknod -m 600 ${dev_path}/tty3 c 4 3
145 mknod -m 600 ${dev_path}/tty4 c 4 4
262f4e48
AS
146 mknod -m 600 ${dev_path}/console c 5 1
147 mknod -m 666 ${dev_path}/full c 1 7
148 mknod -m 600 ${dev_path}/initctl p
149 mknod -m 666 ${dev_path}/ptmx c 5 2
b031f0d2
AS
150 chown root:tty ${dev_path}/ptmx
151 ln -s /proc/self/fd ${dev_path}/fd
152 ln -s /proc/kcore ${dev_path}/core
153 mkdir -m 755 ${dev_path}/mapper
154 mknod -m 600 ${dev_path}/mapper/control c 10 236
155 mkdir -m 755 ${dev_path}/net
156 mknod -m 666 ${dev_path}/net/tun c 10 200
262f4e48 157
436ab4be
EG
158 if [ -n "${root_password}" ]; then
159 echo "setting root passwd to $root_password"
160 echo "root:$root_password" | chroot $rootfs_path chpasswd
161 fi
262f4e48
AS
162
163 return 0
164}
165
166download_altlinux()
167{
168
bffda95b
DP
169 if [ -z "$aptconfver" ]; then
170 case "$release" in
171 sisyphus)
172 aptconfver=apt-conf-sisyphus ;;
173 *)
174 aptconfver=apt-conf-branch ;;
175 esac
176 fi
177
262f4e48
AS
178 # check the mini altlinux was not already downloaded
179 INSTALL_ROOT=$cache/partial
180 mkdir -p $INSTALL_ROOT
181 if [ $? -ne 0 ]; then
14d9c0f0
SG
182 echo "Failed to create '$INSTALL_ROOT' directory"
183 return 1
262f4e48
AS
184 fi
185
186 # download a mini altlinux into a cache
187 echo "Downloading altlinux minimal ..."
188 APT_GET="apt-get -o RPM::RootDir=$INSTALL_ROOT -y"
189 PKG_LIST="$(grep -hs '^[^#]' "$profile_dir/$profile")"
a9ae28a0 190 # if no configuration file $profile -- fall back to default list of packages
bffda95b 191 [ -z "$PKG_LIST" ] && PKG_LIST="interactivesystem apt $aptconfver etcnet-full openssh-server systemd-sysvinit systemd-units systemd NetworkManager-daemon"
262f4e48
AS
192
193 mkdir -p $INSTALL_ROOT/var/lib/rpm
194 rpm --root $INSTALL_ROOT --initdb
a9ae28a0
DP
195
196 # some scripts want to have /dev/null at least
197 dev_path="$INSTALL_ROOT/dev"
198 if [ ! -c "${dev_path}/null" ]; then
199 mkdir -p "${dev_path}"
200 mknod -m 666 "${dev_path}/null" c 1 3
201 fi
202
262f4e48
AS
203 $APT_GET install $PKG_LIST
204
205 if [ $? -ne 0 ]; then
14d9c0f0
SG
206 echo "Failed to download the rootfs, aborting."
207 return 1
262f4e48
AS
208 fi
209
210 mv "$INSTALL_ROOT" "$cache/rootfs"
211 echo "Download complete."
212
213 return 0
214}
215
216copy_altlinux()
217{
218
219 # make a local copy of the minialtlinux
220 echo -n "Copying rootfs to $rootfs_path ..."
221 #cp -a $cache/rootfs-$arch $rootfs_path || return 1
222 # i prefer rsync (no reason really)
223 mkdir -p $rootfs_path
6273aef1 224 rsync -SHaAX $cache/rootfs/ $rootfs_path/
262f4e48
AS
225 return 0
226}
227
228update_altlinux()
229{
230 chroot $cache/rootfs apt-get update
231 chroot $cache/rootfs apt-get -y dist-upgrade
232}
233
234install_altlinux()
235{
e29bf450 236 mkdir -p @LOCALSTATEDIR@/lock/subsys/
262f4e48 237 (
17abf278 238 flock -x 9
14d9c0f0
SG
239 if [ $? -ne 0 ]; then
240 echo "Cache repository is busy."
241 return 1
242 fi
243
244 echo "Checking cache download in $cache/rootfs ... "
245 if [ ! -e "$cache/rootfs" ]; then
246 download_altlinux
247 if [ $? -ne 0 ]; then
248 echo "Failed to download 'altlinux base'"
249 return 1
250 fi
262f4e48 251 else
14d9c0f0 252 echo "Cache found. Updating..."
262f4e48 253 update_altlinux
14d9c0f0
SG
254 if [ $? -ne 0 ]; then
255 echo "Failed to update 'altlinux base', continuing with last known good cache"
262f4e48
AS
256 else
257 echo "Update finished"
14d9c0f0
SG
258 fi
259 fi
260
261 echo "Copy $cache/rootfs to $rootfs_path ... "
262 copy_altlinux
263 if [ $? -ne 0 ]; then
264 echo "Failed to copy rootfs"
265 return 1
266 fi
267 return 0
17abf278 268 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-altlinux
262f4e48
AS
269
270 return $?
271}
272
273copy_configuration()
274{
275
276 mkdir -p $config_path
7a96a068 277 grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs_path" >> $config_path/config
262f4e48 278 cat <<EOF >> $config_path/config
b67771bc 279lxc.uts.name = $name
fe1c5887 280lxc.tty.max = 4
232763d6 281lxc.pty.max = 1024
eee3ba81 282lxc.cap.drop = sys_module mac_admin mac_override sys_time
f02ce27d
SG
283
284# When using LXC with apparmor, uncomment the next line to run unconfined:
a1d5fdfd 285#lxc.apparmor.profile = unconfined
f02ce27d 286
262f4e48 287#networking
7fa3f2e9 288#lxc.net.0.type = $lxc_network_type
289#lxc.net.0.flags = up
290#lxc.net.0.link = $lxc_network_link
291#lxc.net.0.name = veth0
292#lxc.net.0.mtu = 1500
b031f0d2
AS
293EOF
294if [ ! -z ${ipv4} ]; then
295 cat <<EOF >> $config_path/config
9ff60df2 296lxc.net.0.ipv4.address = $ipv4
b031f0d2
AS
297EOF
298fi
299if [ ! -z ${gw} ]; then
300 cat <<EOF >> $config_path/config
7fa3f2e9 301lxc.net.0.ipv4.gateway = $gw
b031f0d2
AS
302EOF
303fi
304if [ ! -z ${ipv6} ]; then
305 cat <<EOF >> $config_path/config
2e44ae28 306lxc.net.0.ipv6.address = $ipv6
b031f0d2
AS
307EOF
308fi
309if [ ! -z ${gw6} ]; then
310 cat <<EOF >> $config_path/config
7fa3f2e9 311lxc.net.0.ipv6.gateway = $gw6
b031f0d2
AS
312EOF
313fi
314 cat <<EOF >> $config_path/config
262f4e48
AS
315#cgroups
316lxc.cgroup.devices.deny = a
317# /dev/null and zero
318lxc.cgroup.devices.allow = c 1:3 rwm
319lxc.cgroup.devices.allow = c 1:5 rwm
320# consoles
321lxc.cgroup.devices.allow = c 5:1 rwm
322lxc.cgroup.devices.allow = c 5:0 rwm
323lxc.cgroup.devices.allow = c 4:0 rwm
324lxc.cgroup.devices.allow = c 4:1 rwm
325# /dev/{,u}random
326lxc.cgroup.devices.allow = c 1:9 rwm
327lxc.cgroup.devices.allow = c 1:8 rwm
328lxc.cgroup.devices.allow = c 136:* rwm
329lxc.cgroup.devices.allow = c 5:2 rwm
330# rtc
b031f0d2 331lxc.cgroup.devices.allow = c 10:135 rwm
262f4e48 332
f24a52d5 333lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
262f4e48
AS
334EOF
335
336 if [ $? -ne 0 ]; then
14d9c0f0
SG
337 echo "Failed to add configuration"
338 return 1
262f4e48
AS
339 fi
340
341 return 0
342}
343
344clean()
345{
346
347 if [ ! -e $cache ]; then
14d9c0f0 348 exit 0
262f4e48
AS
349 fi
350
351 # lock, so we won't purge while someone is creating a repository
352 (
17abf278 353 flock -x 9
14d9c0f0
SG
354 if [ $? != 0 ]; then
355 echo "Cache repository is busy."
356 exit 1
357 fi
358
359 echo -n "Purging the download cache for ALTLinux-$release..."
360 rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
361 exit 0
17abf278 362 ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-altlinux
262f4e48
AS
363}
364
365usage()
366{
367 cat <<EOF
368usage:
369 $1 -n|--name=<container_name>
370 [-p|--path=<path>] [-c|--clean] [-R|--release=<ALTLinux_release>]
b031f0d2
AS
371 [-4|--ipv4=<ipv4 address>] [-6|--ipv6=<ipv6 address>]
372 [-g|--gw=<gw address>] [-d|--dns=<dns address>]
1897e3bc 373 [-P|--profile=<name of the profile>] [--rootfs=<path>]
bffda95b 374 [-a|--apt-conf=<apt-conf>]
262f4e48
AS
375 [-A|--arch=<arch of the container>]
376 [-h|--help]
377Mandatory args:
378 -n,--name container name, used to as an identifier for that container from now on
379Optional args:
e29bf450 380 -p,--path path to where the container rootfs will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case
262f4e48
AS
381 -c,--clean clean the cache
382 -R,--release ALTLinux release for the new container. if the host is ALTLinux, then it will defaultto the host's release.
b031f0d2
AS
383 -4,--ipv4 specify the ipv4 address to assign to the virtualized interface, eg. 192.168.1.123/24
384 -6,--ipv6 specify the ipv6 address to assign to the virtualized interface, eg. 2003:db8:1:0:214:1234:fe0b:3596/64
385 -g,--gw specify the default gw, eg. 192.168.1.1
386 -G,--gw6 specify the default gw, eg. 2003:db8:1:0:214:1234:fe0b:3596
387 -d,--dns specify the DNS server, eg. 192.168.1.2
bffda95b 388 -a,--apt-conf specify preferred 'apt-conf' package, eg. 'apt-conf-branch'
262f4e48
AS
389 -P,--profile Profile name is the file name in /etc/lxc/profiles contained packages name for install to cache.
390 -A,--arch NOT USED YET. Define what arch the container will be [i686,x86_64]
1897e3bc 391 ---rootfs rootfs path
262f4e48
AS
392 -h,--help print this help
393EOF
394 return 0
395}
396
bffda95b 397options=$(getopt -o hp:n:P:cR:4:6:g:d:a: -l help,rootfs:,path:,name:,profile:,clean,release:,ipv4:,ipv6:,gw:,dns:,apt-conf: -- "$@")
262f4e48
AS
398if [ $? -ne 0 ]; then
399 usage $(basename $0)
400 exit 1
401fi
402eval set -- "$options"
403
404while true
405do
406 case "$1" in
14d9c0f0
SG
407 -h|--help) usage $0 && exit 0;;
408 -p|--path) path=$2; shift 2;;
1897e3bc 409 --rootfs) rootfs_path=$2; shift 2;;
14d9c0f0
SG
410 -n|--name) name=$2; shift 2;;
411 -P|--profile) profile=$2; shift 2;;
217535de 412 -c|--clean) clean=1; shift 1;;
14d9c0f0
SG
413 -R|--release) release=$2; shift 2;;
414 -4|--ipv4) ipv4=$2; shift 2;;
415 -6|--ipv6) ipv6=$2; shift 2;;
416 -g|--gw) gw=$2; shift 2;;
417 -d|--dns) dns=$2; shift 2;;
bffda95b 418 -a|--apt-conf) aptconfver=$2; shift 2;;
14d9c0f0 419 --) shift 1; break ;;
262f4e48
AS
420 *) break ;;
421 esac
422done
423
424if [ ! -z "$clean" -a -z "$path" ]; then
425 clean || exit 1
426 exit 0
427fi
428
429type apt-get >/dev/null 2>&1
430if [ $? -ne 0 ]; then
431 echo "'apt-get' command is missing"
432 exit 1
433fi
434
435if [ -z "$path" ]; then
436 path=$default_path
437fi
438
439if [ -z "$profile" ]; then
440 profile=$default_profile
441fi
442
443if [ -z "$release" ]; then
444 if [ "$is_altlinux" ]; then
445 release=$(cat /etc/altlinux-release |awk '/^ALT/ {print $3}')
446 else
447 echo "This is not a ALTLinux host and release missing, use -R|--release to specify release"
448 exit 1
449 fi
450fi
451
b031f0d2
AS
452if [ -z "$ipv4" -a -z "$ipv6" ]; then
453 BOOTPROTO="dhcp"
454else
455 BOOTPROTO="static"
456fi
457
262f4e48
AS
458if [ "$(id -u)" != "0" ]; then
459 echo "This script should be run as 'root'"
460 exit 1
461fi
462
7a96a068 463# check for 'lxc.rootfs.path' passed in through default config by lxc-create
1897e3bc 464if [ -z "$rootfs_path" ]; then
7a96a068
CB
465 if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then
466 rootfs_path=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config)
1897e3bc 467 else
44b430e2 468 rootfs_path=$path/rootfs
1897e3bc
SH
469 fi
470fi
471
262f4e48
AS
472config_path=$default_path/$name
473cache=$cache_base/$release/$profile
474
262f4e48
AS
475install_altlinux
476if [ $? -ne 0 ]; then
477 echo "failed to install altlinux"
478 exit 1
479fi
480
481configure_altlinux
482if [ $? -ne 0 ]; then
483 echo "failed to configure altlinux for a container"
484 exit 1
485fi
486
487copy_configuration
488if [ $? -ne 0 ]; then
489 echo "failed write configuration file"
490 exit 1
491fi
492
4986f1c4 493if [ ! -z "$clean" ]; then
262f4e48
AS
494 clean || exit 1
495 exit 0
496fi
497echo "container rootfs and config created"
eba7df9e 498echo "network configured as $lxc_network_type in the $lxc_network_link"