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