]>
Commit | Line | Data |
---|---|---|
beabd0a2 WC |
1 | #!/bin/sh |
2 | # | |
3 | # Template script for generating Linux for SPARC for LXC | |
4 | # based on lxc-fedora, lxc-ubuntu | |
5 | # | |
6 | # Copyright © 2011 Wim Coekaerts <wim.coekaerts@oracle.com> | |
7 | # Copyright © 2012 Dwight Engen <dwight.engen@oracle.com> | |
8 | # Copyright � 2015 Wim Coekaerts <wim.coekaerts@oracle.com> | |
9 | # | |
10 | # Modified for Oracle Linux 5 | |
11 | # Wim Coekaerts <wim.coekaerts@oracle.com> | |
12 | # | |
13 | # Modified for Oracle Linux 6,7 combined OL4,5,6 into one template script | |
14 | # Dwight Engen <dwight.engen@oracle.com> | |
15 | # | |
16 | # Modified for Linux for SPARC 1.0 | |
17 | # Wim Coekaerts <wim.coekaerts@oracle.com> | |
18 | # | |
19 | # This library is free software; you can redistribute it and/or | |
20 | # modify it under the terms of the GNU Lesser General Public | |
21 | # License as published by the Free Software Foundation; either | |
22 | # version 2.1 of the License, or (at your option) any later version. | |
23 | # | |
24 | # This library is distributed in the hope that it will be useful, | |
25 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
27 | # Lesser General Public License for more details. | |
28 | # | |
29 | # You should have received a copy of the GNU Lesser General Public | |
30 | # License along with this library; if not, write to the Free Software | |
31 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
32 | # | |
33 | ||
34 | # Detect use under userns (unsupported) | |
35 | for arg in "$@"; do | |
36 | [ "$arg" = "--" ] && break | |
37 | if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then | |
38 | echo "This template can't be used for unprivileged containers." 1>&2 | |
39 | echo "You may want to try the \"download\" template instead." 1>&2 | |
40 | exit 1 | |
41 | fi | |
42 | done | |
43 | ||
44 | # Make sure the usual locations are in PATH | |
45 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin | |
46 | ||
beabd0a2 WC |
47 | die() |
48 | { | |
49 | echo "failed: $1" | |
50 | exit 1 | |
51 | } | |
52 | ||
53 | is_btrfs_subvolume() | |
54 | { | |
55 | if which btrfs >/dev/null 2>&1 && \ | |
56 | btrfs subvolume list "$1" >/dev/null 2>&1; then | |
57 | return 0 | |
58 | fi | |
59 | return 1 | |
60 | } | |
61 | ||
62 | can_chcon() | |
63 | { | |
64 | if which chcon >/dev/null 2>&1; then | |
65 | selinuxenabled >/dev/null 2>&1 | |
66 | return $? | |
67 | fi | |
68 | return 1 | |
69 | } | |
70 | ||
71 | # fix up the container_rootfs | |
72 | container_rootfs_patch() | |
73 | { | |
74 | echo "Patching container rootfs $container_rootfs for Linux for SPARC $container_release_major.$container_release_minor" | |
75 | ||
76 | # copy ourself into the container to be used to --patch the rootfs when | |
77 | # yum update on certain packages is done. we do this here instead of in | |
78 | # container_rootfs_configure() in case the patching done in this function | |
79 | # is updated in the future, we can inject the updated version of ourself | |
80 | # into older containers. | |
81 | if [ $container_rootfs != "/" ]; then | |
82 | cp -f `readlink -f $0` $container_rootfs/usr/bin/lxc-patch | |
83 | mkdir -p $container_rootfs/usr/share/yum-plugins | |
84 | cp @DATADIR@/lxc/lxc-patch.py $container_rootfs/usr/share/yum-plugins | |
85 | mkdir -p $container_rootfs/etc/yum/pluginconf.d | |
86 | cat <<EOF > $container_rootfs/etc/yum/pluginconf.d/lxc-patch.conf | |
87 | [main] | |
88 | enabled=1 | |
89 | packages=dbus,initscripts,iptables,openssh-server,setup,selinux-policy,readahead,udev,util-linux,util-linux-ng | |
90 | EOF | |
91 | fi | |
92 | ||
93 | # "disable" selinux in the guest. The policy in the container isn't | |
94 | # likely to match the hosts (unless host == guest exactly) and the | |
95 | # kernel can only be enforcing one policy. | |
96 | # | |
97 | mkdir -p $container_rootfs/selinux | |
98 | echo 0 > $container_rootfs/selinux/enforce | |
99 | if [ -e $container_rootfs/etc/selinux/config ]; then | |
100 | sed -i 's|SELINUX=enforcing|SELINUX=disabled|' $container_rootfs/etc/selinux/config | |
101 | else | |
102 | mkdir -p $container_rootfs/etc/selinux | |
103 | echo "SELINUX=disabled" >$container_rootfs/etc/selinux/config | |
104 | fi | |
105 | sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/login | |
106 | sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/login | |
107 | sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/sshd | |
108 | sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/sshd | |
109 | ||
110 | # setting /proc/$$/loginuid doesn't work under user namespace, which | |
111 | # prevents logins from working | |
112 | sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/sshd | |
113 | sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/login | |
114 | ||
115 | if [ -f $container_rootfs/usr/sbin/selinuxenabled ]; then | |
116 | mv $container_rootfs/usr/sbin/selinuxenabled $container_rootfs/usr/sbin/selinuxenabled.lxcorig | |
117 | ln -s /bin/false $container_rootfs/usr/sbin/selinuxenabled | |
118 | fi | |
119 | ||
120 | # ensure /dev/ptmx refers to the newinstance devpts of the container, or | |
121 | # pty's will get crossed up with the hosts (https://lkml.org/lkml/2012/1/23/512) | |
122 | rm -f $container_rootfs/dev/ptmx | |
123 | ln -s pts/ptmx $container_rootfs/dev/ptmx | |
124 | ||
125 | # silence error in checking for selinux | |
126 | sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.sysinit | |
127 | sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.d/rc.sysinit | |
128 | ||
129 | # disable ipv6 | |
130 | rm -f $container_rootfs/etc/sysconfig/network-scripts/init.ipv6-global | |
131 | ||
132 | # remove module stuff for iptables it just shows errors that are not | |
133 | # relevant in a container | |
134 | if [ -f "$container_rootfs/etc/sysconfig/iptables-config" ]; then | |
135 | sed -i 's|IPTABLES_MODULES=".*|IPTABLES_MODULES=""|' $container_rootfs/etc/sysconfig/iptables-config | |
136 | sed -i 's|IPTABLES_MODULES_UNLOAD=".*|IPTABLES_MODULES_UNLOAD="no"|' $container_rootfs/etc/sysconfig/iptables-config | |
137 | fi | |
138 | ||
139 | # disable readahead in the container | |
140 | if [ $container_release_major = "1" -a -e $container_rootfs/etc/sysconfig/readahead ]; then | |
141 | rm -f $container_rootfs/etc/init/readahead-collector.conf | |
142 | rm -f $container_rootfs/etc/init/readahead-disable-services.conf | |
143 | sed -i 's|READAHEAD="yes"|READAHEAD="no"|' $container_rootfs/etc/sysconfig/readahead | |
144 | fi | |
145 | ||
146 | ||
147 | # no need to attempt to mount / | |
148 | sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.sysinit | |
149 | sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.d/rc.sysinit | |
150 | sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.sysinit | |
151 | sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.d/rc.sysinit | |
152 | ||
153 | # disable udev in the container | |
154 | sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.sysinit | |
155 | sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.d/rc.sysinit | |
156 | ||
157 | sed -i 's|\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/init.d/halt | |
158 | sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.sysinit | |
159 | sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/rc.sysinit | |
160 | sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.sysinit | |
161 | sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.d/rc.sysinit | |
162 | ||
163 | touch $container_rootfs/.nolvm | |
164 | ||
165 | # fix assumptions that plymouth is available | |
166 | sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.sysinit | |
167 | sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.d/rc.sysinit | |
168 | rm -f $container_rootfs/etc/init/plymouth-shutdown.conf | |
169 | rm -f $container_rootfs/etc/init/quit-plymouth.conf | |
170 | rm -f $container_rootfs/etc/init/splash-manager.conf | |
171 | ||
172 | # dont try to unmount /dev/lxc devices | |
173 | sed -i 's|&& $1 !~ /^\\/dev\\/ram/|\&\& $2 !~ /^\\/dev\\/lxc/ \&\& $1 !~ /^\\/dev\\/ram/|' $container_rootfs/etc/init.d/halt | |
174 | ||
175 | # don't try to unmount swap | |
176 | sed -i 's|\[ -f /proc/swaps \]|# LXC [ -f /proc/swaps ]|' $container_rootfs/etc/init.d/halt | |
177 | ||
178 | sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.sysinit | |
179 | sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.d/rc.sysinit | |
180 | ||
181 | # there might be other services that are useless but the below set is a good start | |
182 | # some of these might not exist in the image, so we silence chkconfig complaining | |
183 | # about the service file not being found | |
184 | for service in \ | |
185 | acpid apmd auditd autofs cpuspeed dund gpm haldaemon hidd \ | |
186 | ip6tables irqbalance iscsi iscsid isdn kdump kudzu \ | |
187 | lm_sensors lvm2-monitor mdmonitor microcode_ctl \ | |
188 | ntpd pcmcia postfix sendmail udev-post xfs ; | |
189 | do | |
190 | chroot $container_rootfs chkconfig 2>/dev/null $service off | |
191 | done | |
192 | ||
193 | for service in rsyslog ; | |
194 | do | |
195 | chroot $container_rootfs chkconfig 2>/dev/null $service on | |
196 | done | |
197 | } | |
198 | ||
199 | container_rootfs_configure() | |
200 | { | |
201 | container_rootfs_patch | |
202 | echo "Configuring container for Linux for SPARC $container_release_major.$container_release_minor" | |
203 | ||
204 | # configure the network to use dhcp. we set DHCP_HOSTNAME so the guest | |
205 | # will report its name and be resolv'able by the hosts dnsmasq | |
206 | cat <<EOF > $container_rootfs/etc/sysconfig/network-scripts/ifcfg-eth0 | |
207 | DEVICE=eth0 | |
208 | BOOTPROTO=dhcp | |
209 | ONBOOT=yes | |
210 | HOSTNAME=$name | |
211 | DHCP_HOSTNAME=\`hostname\` | |
212 | NM_CONTROLLED=no | |
213 | TYPE=Ethernet | |
214 | EOF | |
215 | ||
216 | cat <<EOF > $container_rootfs/etc/sysconfig/network | |
217 | NETWORKING=yes | |
218 | NETWORKING_IPV6=no | |
219 | HOSTNAME=$name | |
220 | EOF | |
221 | ||
222 | # set minimal hosts | |
223 | echo "127.0.0.1 localhost $name" > $container_rootfs/etc/hosts | |
224 | ||
225 | # this file has to exist for libvirt/Virtual machine monitor to boot the container | |
226 | touch $container_rootfs/etc/mtab | |
227 | ||
228 | # setup console and tty[1-4] for login. note that /dev/console and | |
229 | # /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and | |
230 | # /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks. | |
231 | # lxc will maintain these links and bind mount ptys over /dev/lxc/* | |
232 | # since lxc.devttydir is specified in the config. | |
233 | ||
234 | # allow root login on console, tty[1-4], and pts/0 for libvirt | |
235 | echo "# LXC (Linux Containers)" >>$container_rootfs/etc/securetty | |
236 | echo "lxc/console" >>$container_rootfs/etc/securetty | |
237 | for i in 1 2 3 4; do | |
238 | echo "lxc/tty$i" >>$container_rootfs/etc/securetty | |
239 | done | |
240 | echo "# For libvirt/Virtual Machine Monitor" >>$container_rootfs/etc/securetty | |
241 | for i in 0 1 2 3 4; do | |
242 | echo "pts/$i" >>$container_rootfs/etc/securetty | |
243 | done | |
244 | ||
245 | # prevent mingetty from calling vhangup(2) since it fails with userns | |
246 | if [ -f $container_rootfs/etc/init/tty.conf ]; then | |
247 | sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc/init/tty.conf | |
248 | fi | |
249 | ||
250 | # create maygetty which only spawns a getty on the console when running | |
251 | # under lxc, not libvirt-lxc which symlinks /dev/console to the same pty | |
252 | # as /dev/tty1 | |
253 | cat <<EOF >$container_rootfs/sbin/maygetty | |
254 | #!/bin/sh | |
255 | if [ "\$container" = "lxc" ]; then | |
256 | exec /sbin/mingetty \$@ | |
257 | fi | |
258 | exec sleep infinity | |
259 | EOF | |
260 | chmod 755 $container_rootfs/sbin/maygetty | |
261 | ||
262 | cat <<EOF > $container_rootfs/etc/init/console.conf | |
263 | # console - getty | |
264 | # | |
265 | # This service maintains a getty on the console from the point the system is | |
266 | # started until it is shut down again. | |
267 | ||
268 | start on stopped rc RUNLEVEL=[2345] | |
269 | stop on runlevel [!2345] | |
270 | env container | |
271 | ||
272 | respawn | |
273 | exec /sbin/maygetty --nohangup --noclear /dev/console | |
274 | EOF | |
275 | ||
276 | cat <<EOF > $container_rootfs/etc/init/power-status-changed.conf | |
277 | # power-status-changed - used to cleanly shut down the container | |
278 | # | |
279 | # This task is run whenever init receives SIGPWR | |
280 | # Used to shut down the machine. | |
281 | ||
282 | start on power-status-changed | |
283 | ||
284 | exec init 0 | |
285 | EOF | |
286 | ||
287 | # start with a clean /var/log/messages | |
288 | rm -f $container_rootfs/var/log/messages | |
289 | ||
710a2553 TT |
290 | # set initial timezone as on host |
291 | if [ -f /etc/sysconfig/clock ]; then | |
292 | . /etc/sysconfig/clock | |
293 | echo ZONE=$ZONE > $container_rootfs/etc/sysconfig/clock | |
294 | chroot $container_rootfs tzdata-update | |
295 | else | |
296 | echo "Timezone in container is not configured. Adjust it manually." | |
297 | fi | |
298 | ||
beabd0a2 WC |
299 | # add oracle user, set root password |
300 | chroot $container_rootfs useradd -m -s /bin/bash oracle | |
301 | echo "oracle:oracle" | chroot $container_rootfs chpasswd | |
302 | echo "root:root" | chroot $container_rootfs chpasswd | |
303 | printf "Added container user:\033[1moracle\033[0m password:\033[1moracle\033[0m\n" | |
304 | printf "Added container user:\033[1mroot\033[0m password:\033[1mroot\033[0m\n" | |
305 | } | |
306 | ||
307 | # create the container's lxc config file | |
308 | container_config_create() | |
309 | { | |
310 | echo "Create configuration file $cfg_dir/config" | |
311 | mkdir -p $cfg_dir || die "unable to create config dir $cfg_dir" | |
312 | ||
313 | echo "# Common configuration" >> $cfg_dir/config | |
314 | if [ -e "@LXCTEMPLATECONFIG@/sparclinux.common.conf" ]; then | |
315 | echo "lxc.include = @LXCTEMPLATECONFIG@/sparclinux.common.conf" >> $cfg_dir/config | |
316 | fi | |
317 | ||
beabd0a2 WC |
318 | cat <<EOF >> $cfg_dir/config || die "unable to create $cfg_dir/config" |
319 | # Container configuration for Linux for SPARC $container_release_major.$container_release_minor | |
320 | lxc.arch = $arch | |
321 | lxc.utsname = $name | |
322 | EOF | |
323 | grep -q "^lxc.rootfs" $cfg_dir/config 2>/dev/null || echo "lxc.rootfs = $container_rootfs" >> $cfg_dir/config | |
324 | ||
325 | echo "lxc.cap.drop = sys_resource" >>$cfg_dir/config | |
326 | ||
327 | echo "lxc.cap.drop = setfcap setpcap" >>$cfg_dir/config | |
328 | ||
329 | echo "# Networking" >>$cfg_dir/config | |
bc3b3272 | 330 | # see if the default network settings were already specified |
beabd0a2 | 331 | lxc_network_type=`grep '^lxc.network.type' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` |
bc3b3272 TT |
332 | if [ -z "$lxc_network_type" ]; then |
333 | echo "lxc.network.type = veth" >>$cfg_dir/config | |
334 | lxc_network_type=veth | |
335 | fi | |
336 | ||
337 | lxc_network_link=`grep '^lxc.network.link' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` | |
338 | if [ -z "$lxc_network_link" ]; then | |
339 | echo "lxc.network.link = lxcbr0" >>$cfg_dir/config | |
340 | lxc_network_link=lxcbr0 | |
341 | fi | |
342 | ||
343 | lxc_network_hwaddr=`grep '^lxc.network.hwaddr' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` | |
344 | if [ -z "$lxc_network_hwaddr" ]; then | |
345 | # generate a hwaddr for the container | |
346 | # see http://sourceforge.net/tracker/?func=detail&aid=3411497&group_id=163076&atid=826303 | |
347 | local hwaddr="00:16:3e:`dd if=/dev/urandom bs=8 count=1 2>/dev/null |od -t x8 | \ | |
348 | head -n1 | awk '{print $2}' | cut -c1-6 | \ | |
349 | sed 's/\(..\)/\1:/g; s/.$//'`" | |
350 | echo "lxc.network.hwaddr = $hwaddr" >>$cfg_dir/config | |
351 | fi | |
352 | ||
353 | lxc_network_flags=`grep '^lxc.network.flags' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'` | |
354 | if [ -z "$lxc_network_flags" ]; then | |
355 | echo "lxc.network.flags = up" >>$cfg_dir/config | |
beabd0a2 WC |
356 | fi |
357 | ||
358 | cat <<EOF >> $cfg_dir/config || die "unable to create $cfg_dir/config" | |
359 | lxc.network.name = eth0 | |
360 | lxc.network.mtu = 1500 | |
beabd0a2 WC |
361 | EOF |
362 | } | |
363 | ||
364 | container_rootfs_clone() | |
365 | { | |
366 | if is_btrfs_subvolume $template_rootfs; then | |
367 | # lxc-create already made $container_rootfs a btrfs subvolume, but | |
368 | # in this case we want to snapshot the original subvolume so we we | |
369 | # have to delete the one that lxc-create made | |
370 | btrfs subvolume delete $container_rootfs | |
371 | btrfs subvolume snapshot $template_rootfs $container_rootfs || die "btrfs clone template" | |
372 | else | |
373 | echo "Copying rootfs ..." | |
374 | cp -axT $template_rootfs $container_rootfs || die "copy template" | |
375 | fi | |
376 | } | |
377 | ||
378 | container_rootfs_repo_create() | |
379 | { | |
380 | echo "# LXC generated .repo file" >$1 | |
381 | echo "[$2]" >>$1 | |
382 | echo "name=Linux for SPARC $container_release_major.$container_release_minor ($basearch)" >>$1 | |
383 | echo "baseurl=$3/" >>$1 | |
384 | echo "enabled=1" >>$1 | |
385 | echo "skip_if_unavailable=1" >>$1 | |
386 | ||
387 | if [ "$4" != "" ]; then | |
388 | echo "gpgkey=$yum_url/RPM-GPG-KEY-oracle-ol$container_release_major" >>$1 | |
389 | echo "gpgcheck=1" >>$1 | |
390 | else | |
391 | echo "gpgcheck=0" >>$1 | |
392 | fi | |
393 | } | |
394 | ||
395 | container_rootfs_dev_create() | |
396 | { | |
397 | # create required devices. note that /dev/console will be created by lxc | |
398 | # or libvirt itself to be a symlink to the right pty. | |
399 | # take care to not nuke /dev in case $container_rootfs isn't set | |
400 | dev_path="$container_rootfs/dev" | |
401 | if [ $container_rootfs != "/" -a -d $dev_path ]; then | |
402 | rm -rf $dev_path | |
403 | fi | |
404 | mkdir -p $dev_path | |
405 | if can_chcon; then | |
406 | # ensure symlinks created in /dev have the right context | |
407 | chcon -t device_t $dev_path | |
408 | fi | |
409 | mknod -m 666 $dev_path/null c 1 3 | |
410 | mknod -m 666 $dev_path/zero c 1 5 | |
411 | mknod -m 666 $dev_path/random c 1 8 | |
412 | mknod -m 666 $dev_path/urandom c 1 9 | |
413 | mkdir -m 755 $dev_path/pts | |
414 | mkdir -m 1777 $dev_path/shm | |
415 | mknod -m 666 $dev_path/tty c 5 0 | |
416 | mknod -m 666 $dev_path/tty1 c 4 1 | |
417 | mknod -m 666 $dev_path/tty2 c 4 2 | |
418 | mknod -m 666 $dev_path/tty3 c 4 3 | |
419 | mknod -m 666 $dev_path/tty4 c 4 4 | |
420 | mknod -m 666 $dev_path/full c 1 7 | |
421 | mknod -m 600 $dev_path/initctl p | |
422 | ||
423 | # set selinux labels same as host | |
424 | if can_chcon; then | |
425 | for node in null zero random urandom pts shm \ | |
426 | tty tty0 tty1 tty2 tty3 tty4 full ; | |
427 | do | |
428 | chcon --reference /dev/$node $dev_path/$node 2>/dev/null | |
429 | done | |
430 | fi | |
431 | } | |
432 | ||
433 | container_rootfs_create() | |
434 | { | |
435 | if can_chcon; then | |
436 | chcon --reference / $container_rootfs 2>/dev/null | |
437 | fi | |
438 | ||
439 | cmds="rpm wget yum" | |
440 | for cmd in $cmds; do | |
441 | which $cmd >/dev/null 2>&1 | |
442 | if [ $? -ne 0 ]; then | |
443 | die "The $cmd command is required, please install it" | |
444 | fi | |
445 | done | |
446 | ||
447 | mkdir -p @LOCALSTATEDIR@/lock/subsys | |
448 | ( | |
449 | flock -x 9 | |
450 | if [ $? -ne 0 ]; then | |
451 | die "The template is busy." | |
452 | fi | |
453 | ||
454 | echo "Yum installing release $container_release_major.$container_release_minor for $basearch" | |
455 | ||
456 | if [ -n "$repourl" ]; then | |
457 | yum_url=$repourl | |
458 | else | |
459 | yum_url=http://yum.oracle.com | |
460 | fi | |
461 | ||
462 | if [ -n "$baseurl" ]; then | |
463 | # create .repo pointing at baseurl | |
464 | repo="lxc-install" | |
465 | mkdir -p $container_rootfs/etc/yum.repos.d | |
466 | container_rootfs_repo_create \ | |
467 | $container_rootfs/etc/yum.repos.d/lxc-install.repo $repo $baseurl | |
468 | else | |
469 | # get public-yum repo file | |
470 | if [ $container_release_major = "1" ]; then | |
471 | repofile=yum-linux-sparc64.repo | |
472 | else | |
473 | die "Unsupported release $container_release_major" | |
474 | fi | |
475 | ||
476 | mkdir -p $container_rootfs/etc/yum.repos.d | |
477 | wget -q $yum_url/$repofile -O $container_rootfs/etc/yum.repos.d/$repofile | |
478 | if [ $? -ne 0 ]; then | |
479 | die "Unable to download repo file $yum_url/$repofile, release unavailable" | |
480 | fi | |
481 | ||
482 | # yum will take $basearch from host, so force the arch we want | |
483 | sed -i "s|\$basearch|$basearch|" $container_rootfs/etc/yum.repos.d/$repofile | |
484 | ||
485 | # replace url if they specified one | |
486 | if [ -n "$repourl" ]; then | |
487 | sed -i "s|baseurl=http://yum.oracle.com/|baseurl=$repourl/repo|" $container_rootfs/etc/yum.repos.d/$repofile | |
488 | sed -i "s|gpgkey=http://yum.oracle.com|gpgkey=$repourl|" $container_rootfs/etc/yum.repos.d/$repofile | |
489 | ||
490 | fi | |
491 | ||
492 | # disable all repos, then enable the repo for the version we are installing. | |
493 | if [ $container_release_minor = "latest" ]; then | |
494 | repo="lfs"_$container_release_minor | |
495 | else | |
496 | die "Unsupported release $container_release_major.$container_release_minor" | |
497 | fi | |
498 | sed -i "s|enabled=1|enabled=0|" $container_rootfs/etc/yum.repos.d/$repofile | |
499 | sed -i "/\[$repo\]/,/\[/ s/enabled=0/enabled=1/" $container_rootfs/etc/yum.repos.d/$repofile | |
500 | fi | |
501 | ||
502 | container_rootfs_dev_create | |
503 | ||
504 | # don't put devpts,proc, nor sysfs in here, it will already be mounted for us by lxc/libvirt | |
505 | echo "" >$container_rootfs/etc/fstab | |
506 | ||
507 | # create rpm db, download and yum install minimal packages | |
508 | mkdir -p $container_rootfs/var/lib/rpm | |
509 | rpm --root $container_rootfs --initdb | |
510 | yum_args="--installroot $container_rootfs --disablerepo=* --enablerepo=$repo -y --nogpgcheck" | |
511 | min_pkgs="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils sparclinux-release" | |
512 | ||
513 | # we unshare the mount namespace because yum installing the ol4 | |
514 | # packages causes $rootfs/proc to be mounted on | |
515 | lxc-unshare -s MOUNT yum -- $yum_args install $min_pkgs $user_pkgs | |
516 | if [ $? -ne 0 ]; then | |
517 | die "Failed to download and install the rootfs, aborting." | |
518 | fi | |
519 | ||
520 | # rsyslog and pam depend on coreutils for some common commands in | |
521 | # their POSTIN scriptlets, but coreutils wasn't installed yet. now | |
522 | # that coreutils is installed, reinstall the packages so their POSTIN | |
523 | # runs right. similarly, libutempter depends on libselinux.so.1 when | |
524 | # it runs /usr/sbin/groupadd, so reinstall it too | |
525 | redo_pkgs="" | |
526 | if [ x"$redo_pkgs" != x ]; then | |
527 | rpm --root $container_rootfs --nodeps -e $redo_pkgs | |
528 | lxc-unshare -s MOUNT yum -- $yum_args install $redo_pkgs | |
529 | if [ $? -ne 0 ]; then | |
530 | die "Unable to reinstall packages" | |
531 | fi | |
532 | fi | |
533 | ||
534 | # these distributions put the rpm database in a place the guest is | |
535 | # not expecting it, so move it | |
536 | if [ $host_distribution = "Ubuntu" -o $host_distribution = "Debian" ]; then | |
537 | mv $container_rootfs/$HOME/.rpmdb/* $container_rootfs/var/lib/rpm | |
538 | fi | |
539 | ||
540 | # if the native rpm created the db with Hash version 9, we need to | |
541 | # downgrade it to Hash version 8 for use with OL5.x | |
542 | db_version=`file $container_rootfs/var/lib/rpm/Packages | \ | |
543 | grep -o 'version [0-9]*' |awk '{print $2}'` | |
544 | ||
545 | # the host rpm may not be the same as the guest, rebuild the db with | |
546 | # the guest rpm version | |
547 | echo "Rebuilding rpm database" | |
548 | rm -f $container_rootfs/var/lib/rpm/__db* | |
549 | chroot $container_rootfs rpm --rebuilddb >/dev/null 2>&1 | |
550 | ||
551 | ) 9>@LOCALSTATEDIR@/lock/subsys/lxc-sparclinux-$name | |
552 | if [ $? -ne 0 ]; then | |
553 | exit 1 | |
554 | fi | |
555 | } | |
556 | ||
557 | container_release_get() | |
558 | { | |
559 | if [ -f $1/etc/sparclinux-release ]; then | |
560 | container_release_version=`cat $1/etc/sparclinux-release |awk '/^Linux/ {print $5}'` | |
561 | container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'` | |
562 | container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'` | |
563 | else | |
564 | echo "Unable to determine container release version" | |
565 | exit 1 | |
566 | fi | |
567 | } | |
568 | ||
569 | usage() | |
570 | { | |
571 | cat <<EOF | |
572 | -a|--arch=<arch> architecture (sparc64) | |
573 | -R|--release=<release> release to download for the new container | |
574 | --rootfs=<path> rootfs path | |
575 | -r|--rpms=<rpm name> additional rpms to install into container | |
576 | -u|--url=<url> replace yum repo url (ie. Oracle public-yum mirror) | |
577 | --baseurl=<url> use package repository (ie. file:///mnt) | |
578 | arch and release must also be specified | |
579 | -t|--templatefs=<path> copy/clone rootfs at path instead of downloading | |
580 | -P|--patch=<path> only patch the rootfs at path for use as a container | |
581 | -h|--help | |
582 | ||
583 | Release is of the format "major.minor", for example "1.0" or "1.latest" | |
584 | This template supports Linux for SPARC release 1.0 | |
585 | EOF | |
586 | return 0 | |
587 | } | |
588 | ||
589 | options=$(getopt -o hp:n:a:R:r:u:t: -l help,rootfs:,path:,name:,arch:,release:,rpms:,url:,templatefs:,patch:,baseurl: -- "$@") | |
590 | if [ $? -ne 0 ]; then | |
591 | usage $(basename $0) | |
592 | exit 1 | |
593 | fi | |
594 | ||
595 | eval set -- "$options" | |
596 | while true | |
597 | do | |
598 | case "$1" in | |
599 | -h|--help) usage $0 && exit 0;; | |
600 | -p|--path) cfg_dir=$2; shift 2;; | |
601 | --rootfs) container_rootfs=$2; shift 2;; | |
602 | -n|--name) name=$2; shift 2;; | |
603 | -a|--arch) arch=$2; shift 2;; | |
604 | -R|--release) container_release_version=$2; shift 2;; | |
605 | -r|--rpms) user_pkgs=$2; shift 2;; | |
606 | -u|--url) repourl=$2; shift 2;; | |
607 | -t|--templatefs) template_rootfs=$2; shift 2;; | |
608 | --patch) patch_rootfs=$2; shift 2;; | |
609 | --baseurl) baseurl=$2; shift 2;; | |
610 | --) shift 1; break ;; | |
611 | *) break ;; | |
612 | esac | |
613 | done | |
614 | ||
615 | # make sure mandatory args are given and valid | |
616 | if [ "$(id -u)" != "0" ]; then | |
617 | echo "This script should be run as 'root'" | |
618 | exit 1 | |
619 | fi | |
620 | ||
621 | if [ -n "$baseurl" ]; then | |
622 | if [ "$arch" = "" -o "$container_release_version" = "" ]; then | |
623 | echo "The --arch and --release must be specified when using --baseurl" | |
624 | usage | |
625 | exit 1 | |
626 | fi | |
627 | fi | |
628 | ||
629 | if [ "$arch" = "" ]; then | |
630 | arch=$(uname -m) | |
631 | fi | |
632 | ||
633 | if [ -n "$patch_rootfs" ]; then | |
634 | container_rootfs="$patch_rootfs" | |
635 | container_release_get $container_rootfs | |
636 | container_rootfs_patch | |
637 | exit 0 | |
638 | fi | |
639 | ||
640 | if [ -z $name ]; then | |
641 | echo "Container name must be given" | |
642 | usage | |
643 | exit 1 | |
644 | fi | |
645 | ||
646 | if [ -z $cfg_dir ]; then | |
647 | echo "Configuration directory must be given, check lxc-create" | |
648 | usage | |
649 | exit 1 | |
650 | fi | |
651 | ||
652 | basearch=$arch | |
653 | ||
654 | if [ "$arch" != "sparc64" ]; then | |
655 | echo "Bad architecture given, check lxc-create" | |
656 | usage | |
657 | exit 1 | |
658 | fi | |
659 | ||
660 | if [ -f /etc/sparclinux-release ]; then | |
661 | host_distribution="SPARCLinux" | |
662 | host_release_version=`cat /etc/sparclinux-release |awk '{print $5}'` | |
663 | host_release_major=`echo $host_release_version |awk -F '.' '{print $1}'` | |
664 | host_release_minor=`echo $host_release_version |awk -F '.' '{print $2}'` | |
665 | else | |
666 | echo "Unable to determine host distribution" | |
667 | exit 1 | |
668 | fi | |
669 | ||
670 | echo "Host is $host_distribution $host_release_version" | |
671 | ||
672 | if [ -z "$container_rootfs" ]; then | |
673 | container_rootfs="$cfg_dir/rootfs" | |
674 | fi | |
675 | ||
676 | if [ -n "$template_rootfs" ]; then | |
677 | container_release_get $template_rootfs | |
678 | else | |
679 | if [ -z "$container_release_version" ]; then | |
680 | if [ $host_distribution = "SPARCLinux" ]; then | |
681 | container_release_version=$host_release_version | |
682 | else | |
683 | echo "No release specified with -R, defaulting to 1.latest" | |
684 | container_release_version="1.latest" | |
685 | fi | |
686 | fi | |
687 | container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'` | |
688 | container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'` | |
689 | fi | |
690 | ||
691 | container_config_create | |
692 | if [ -n "$template_rootfs" ]; then | |
693 | container_rootfs_clone | |
694 | else | |
695 | container_rootfs_create | |
696 | fi | |
697 | ||
698 | container_release_get $container_rootfs | |
699 | ||
700 | container_rootfs_configure | |
701 | ||
702 | echo "Container : $container_rootfs" | |
703 | echo "Config : $cfg_dir/config" | |
704 | echo "Network : eth0 ($lxc_network_type) on $lxc_network_link" |