]>
Commit | Line | Data |
---|---|---|
7a49a081 | 1 | #!/bin/bash -eu |
cab79123 KY |
2 | |
3 | # | |
4 | # template script for generating Plamo Linux container for LXC | |
5 | # | |
6 | ||
7 | # | |
8 | # lxc: linux Container library | |
9 | ||
10 | # Authors: | |
11 | # KATOH Yasufumi <karma@jazz.email.ne.jp> | |
12 | # TAMUKI Shoichi <tamuki@linet.gr.jp> | |
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 | # ref. https://github.com/Ponce/lxc-slackware/blob/master/lxc-slackware | |
29 | # lxc-ubuntu script | |
30 | ||
8ec981fc | 31 | # Detect use under userns (unsupported) |
c63c04fc | 32 | for arg in "$@"; do |
96283b54 SG |
33 | [ "$arg" = "--" ] && break |
34 | if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then | |
8ec981fc SG |
35 | echo "This template can't be used for unprivileged containers." 1>&2 |
36 | echo "You may want to try the \"download\" template instead." 1>&2 | |
37 | exit 1 | |
38 | fi | |
39 | done | |
40 | ||
207bf0e4 SG |
41 | # Make sure the usual locations are in PATH |
42 | export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin | |
43 | ||
cab79123 KY |
44 | [ -r /etc/default/lxc ] && . /etc/default/lxc |
45 | ||
7a49a081 | 46 | DLSCHEME=${DLSCHEME:-"http"} |
64600fe3 | 47 | MIRRORSRV=${MIRRORSRV:-"repository.plamolinux.org"} |
7a49a081 | 48 | MIRRORPATH=${MIRRORPATH:-"/pub/linux/Plamo"} |
8c3a756e KY |
49 | CATEGORIES=${CATEGORIES-"00_base 01_minimum"} |
50 | EXTRACTGRS=${EXTRACTGRS-""} | |
51 | IGNOREPKGS=${IGNOREPKGS-"grub kernel lilo linux_firmware microcode_ctl | |
1dd810a1 | 52 | cpufreqd cpufrequtils gpm ntp kmod"} |
8c3a756e | 53 | ADDONPKGS=${ADDONPKGS-"`echo contrib/Hamradio/{morse,qrq}`"} |
cab79123 KY |
54 | |
55 | download_plamo() { | |
56 | # check the mini plamo was not already downloaded | |
57 | if ! mkdir -p $ptcache ; then | |
58 | echo "Failed to create '$ptcache' directory." | |
59 | return 1 | |
60 | fi | |
61 | # download a mini plamo into a cache | |
62 | echo "Downloading Plamo-$release minimal..." | |
8adef761 | 63 | cd $ptcache |
7a49a081 KY |
64 | case $DLSCHEME in http) depth=2 ;; ftp) depth=3 ;; esac |
65 | rej=${IGNOREPKGS%% *} ; [ -n "$rej" ] && rej="$rej-*" | |
8c3a756e | 66 | if [ `echo $IGNOREPKGS | wc -w` -gt 1 ] ; then |
adf4b408 KY |
67 | for p in ${IGNOREPKGS#* } ; do rej="$rej,$p-*" ; done |
68 | fi | |
7a49a081 | 69 | for i in $CATEGORIES ; do |
adf4b408 | 70 | wget -nv -e robots=off -r -l $depth -nd -A .tgz,.txz -R "$rej" \ |
7a49a081 KY |
71 | -I $MIRRORPATH/Plamo-$release/$arch/plamo/$i \ |
72 | -X $MIRRORPATH/Plamo-$release/$arch/plamo/$i/old \ | |
73 | $DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/plamo/$i | |
74 | if [ $? -ne 0 ] ; then | |
75 | echo "Failed to download the rootfs, aborting." | |
76 | return 1 | |
77 | fi | |
78 | done | |
79 | for i in $EXTRACTGRS ; do | |
adf4b408 | 80 | wget -nv -e robots=off -r -l $depth -nd -A .tgz,.txz -R "$rej" \ |
7a49a081 KY |
81 | -I $MIRRORPATH/Plamo-$release/$arch/contrib/$i \ |
82 | -X $MIRRORPATH/Plamo-$release/$arch/contrib/$i/old \ | |
83 | $DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/contrib/$i | |
84 | if [ $? -ne 0 ] ; then | |
85 | echo "Failed to download the rootfs, aborting." | |
8adef761 KY |
86 | return 1 |
87 | fi | |
cab79123 | 88 | done |
adf4b408 KY |
89 | for p in $ADDONPKGS ; do |
90 | wget -nv -e robots=off -r -l $depth -nd -A "`basename $p`-*" \ | |
91 | -I $MIRRORPATH/Plamo-$release/$arch/`dirname $p` \ | |
92 | -X $MIRRORPATH/Plamo-$release/$arch/`dirname $p`/old \ | |
93 | $DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/`dirname $p` | |
94 | if [ $? -ne 0 ] ; then | |
95 | echo "Failed to download the rootfs, aborting." | |
96 | return 1 | |
97 | fi | |
98 | done | |
cab79123 KY |
99 | mv $ptcache $dlcache |
100 | echo "Download complete." | |
101 | return 0 | |
102 | } | |
103 | ||
104 | copy_plamo() { | |
105 | # make a local copy of the mini plamo | |
106 | echo "Copying $rtcache to $rootfs..." | |
107 | mkdir -p $rootfs | |
108 | find $rtcache -mindepth 1 -maxdepth 1 -exec cp -a {} $rootfs \; || return 1 | |
109 | return 0 | |
110 | } | |
111 | ||
112 | install_plamo() { | |
113 | mkdir -p @LOCALSTATEDIR@/lock/subsys | |
114 | ( | |
ffeb76b4 | 115 | if ! flock -n 9 ; then |
cab79123 KY |
116 | echo "Cache repository is busy." |
117 | return 1 | |
118 | fi | |
119 | echo "Checking cache download in $dlcache..." | |
120 | if [ ! -d $dlcache ] ; then | |
121 | if ! download_plamo ; then | |
122 | echo "Failed to download plamo $release base packages." | |
123 | return 1 | |
124 | fi | |
125 | fi | |
d0348408 TS |
126 | # install "installpkg" command temporarily with static linked tar |
127 | # command into the lxc cache directory to keep the original uid/ | |
128 | # gid of files/directories. | |
129 | echo "Installing 'installpkg' command into $dlcache/sbin..." | |
130 | ( cd $dlcache ; tar xpJf hdsetup-*.txz ; rm -rf tmp usr var ) | |
131 | sed -i "/ldconfig/!s@/sbin@$dlcache&@g" $dlcache/sbin/installpkg* | |
132 | PATH=$dlcache/sbin:$PATH | |
cab79123 KY |
133 | echo "Installing packages to $rtcache..." |
134 | if [ ! -d $rtcache ] ; then | |
135 | mkdir -p $rtcache | |
7a49a081 | 136 | for p in `ls -cr $dlcache/*.t?z` ; do |
8adef761 | 137 | installpkg -root $rtcache -priority ADD $p |
cab79123 KY |
138 | done |
139 | fi | |
140 | echo "Copy $rtcache to $rootfs..." | |
141 | if ! copy_plamo ; then | |
142 | echo "Failed to copy rootfs." | |
143 | return 1 | |
144 | fi | |
145 | return 0 | |
ffeb76b4 | 146 | ) 9> @LOCALSTATEDIR@/lock/subsys/lxc-plamo |
cab79123 KY |
147 | } |
148 | ||
149 | configure_plamo() { | |
cab79123 KY |
150 | # suppress log level output for udev |
151 | sed -i 's/="err"/=0/' $rootfs/etc/udev/udev.conf | |
152 | # /etc/fstab | |
153 | cat <<- "EOF" > $rootfs/etc/fstab | |
154 | none /proc proc defaults 0 0 | |
155 | none /sys sysfs defaults 0 0 | |
156 | none /dev tmpfs defaults 0 0 | |
157 | none /tmp tmpfs defaults 0 0 | |
158 | none /dev/pts devpts gid=5,mode=620 0 0 | |
159 | none /proc/bus/usb usbfs noauto 0 0 | |
160 | none /var/lib/nfs/rpc_pipefs rpc_pipefs defaults 0 0 | |
161 | EOF | |
162 | # /etc/inittab | |
163 | cat <<- "EOF" | patch $rootfs/etc/inittab | |
db821c3a KY |
164 | 32,33c32,33 |
165 | < # What to do when power fails (shutdown to single user). | |
166 | < pf::powerfail:/sbin/shutdown -f +5 "THE POWER IS FAILING" | |
167 | --- | |
168 | > # What to do when power fails (shutdown). | |
169 | > pf::powerfail:/sbin/shutdown -h +0 "THE POWER IS FAILING" | |
cab79123 KY |
170 | 47a48 |
171 | > 1:1235:respawn:/sbin/agetty 38400 console | |
172 | 52,53d52 | |
173 | < c5:1235:respawn:/sbin/agetty 38400 tty5 linux | |
174 | < c6:12345:respawn:/sbin/agetty 38400 tty6 linux | |
175 | EOF | |
176 | # set the hostname | |
177 | echo "$name" > $rootfs/etc/HOSTNAME | |
178 | # set minimal hosts | |
179 | echo "127.0.0.1 localhost $name" > $rootfs/etc/hosts | |
180 | # configure the network using the dhcp | |
181 | echo "DHCP" > $rootfs/var/run/inet1-scheme | |
182 | # localtime (JST) | |
183 | ln -s ../usr/share/zoneinfo/Asia/Tokyo $rootfs/etc/localtime | |
184 | # disable pam_loginuid.so in /etc/pam.d/login (for libvirt's lxc driver) | |
185 | sed -i '/pam_loginuid/s/^/#/' $rootfs/etc/pam.d/login | |
a1e4c206 | 186 | # glibc configure |
0dc29614 | 187 | mv $rootfs/etc/ld.so.conf{.new,} |
a1e4c206 | 188 | chroot $rootfs ldconfig |
d3953cdc KY |
189 | |
190 | # delete unnecessary process from rc.S | |
cab79123 | 191 | ed - $rootfs/etc/rc.d/rc.S <<- "EOF" |
a61848fe KY |
192 | /^mount -w -n -t proc/;/^mkdir \/dev\/shm/-1d |
193 | /^mknod \/dev\/null/;/^# Clean \/etc\/mtab/-2d | |
ffeb76b4 TS |
194 | /^# copy the rules/;/^# Set the hostname/-1d |
195 | /^# Check the integrity/;/^# Clean up temporary/-1d | |
cab79123 KY |
196 | w |
197 | EOF | |
d3953cdc KY |
198 | |
199 | # delete unnecessary process from rc.M | |
cab79123 | 200 | ed - $rootfs/etc/rc.d/rc.M <<- "EOF" |
ffeb76b4 TS |
201 | /^# Screen blanks/;/^# Initialize ip6tables/-1d |
202 | /^# Initialize sysctl/;/^echo "Starting services/-1d | |
203 | /^sync/;/^# All done/-1d | |
cab79123 KY |
204 | w |
205 | EOF | |
d3953cdc KY |
206 | |
207 | # delete unnecessary process from rc.6 | |
208 | ed - $rootfs/etc/rc.d/rc.6 <<- "EOF" | |
209 | /^# Save system time/;/^# Unmount any remote filesystems/-1d | |
210 | /^# Turn off swap/;/^# See if this is a powerfail situation/-1d | |
211 | w | |
212 | EOF | |
213 | ||
cab79123 KY |
214 | # /etc/rc.d/rc.inet1.tradnet |
215 | head -n-93 $rootfs/sbin/netconfig.tradnet > /tmp/netconfig.rconly | |
216 | cat <<- EOF >> /tmp/netconfig.rconly | |
217 | PCMCIA=n | |
218 | RC=$rootfs/etc/rc.d/rc.inet1.tradnet | |
219 | IFCONFIG=sbin/ifconfig | |
220 | ROUTE=sbin/route | |
221 | INET1SCHEME=var/run/inet1-scheme | |
222 | IPADDR=127.0.0.1 | |
223 | NETWORK=127.0.0.0 | |
224 | DHCPCD=usr/sbin/dhclient | |
225 | LOOPBACK=y | |
226 | make_config_file | |
227 | EOF | |
228 | rm -f $rootfs/etc/rc.d/rc.inet1.tradnet | |
229 | sh /tmp/netconfig.rconly | |
230 | rm -f /tmp/netconfig.rconly | |
d0348408 | 231 | sed -i '/cmdline/s/if/& false \&\&/' $rootfs/etc/rc.d/rc.inet1.tradnet |
1dd810a1 KY |
232 | # /etc/rc.d/rc.inet2 |
233 | sed -i '/rpc.mountd/s/^/#/' $rootfs/etc/rc.d/rc.inet2 | |
234 | sed -i '/modprobe/s/^/#/' $rootfs/etc/rc.d/rc.inet2 | |
235 | # configure to start only the minimum of service | |
236 | chmod 644 $rootfs/etc/rc.d/init.d/saslauthd | |
237 | chmod 644 $rootfs/etc/rc.d/init.d/open-iscsi | |
238 | rm -f $rootfs/etc/rc.d/init.d/postfix | |
239 | rm -f $rootfs/var/log/initpkg/shadow | |
cab79123 KY |
240 | return 0 |
241 | } | |
242 | ||
243 | copy_configuration() { | |
7a49a081 KY |
244 | ret=0 |
245 | cat <<- EOF >> $path/config || let ret++ | |
b67771bc | 246 | lxc.uts.name = $name |
7a49a081 | 247 | lxc.arch = $arch |
cab79123 | 248 | EOF |
7a49a081 KY |
249 | if [ -f "@LXCTEMPLATECONFIG@/plamo.common.conf" ] ; then |
250 | cat <<- "EOF" >> $path/config || let ret++ | |
251 | ||
252 | lxc.include = @LXCTEMPLATECONFIG@/plamo.common.conf | |
253 | EOF | |
254 | fi | |
7a49a081 | 255 | if [ $ret -ne 0 ] ; then |
cab79123 KY |
256 | echo "Failed to add configuration." |
257 | return 1 | |
258 | fi | |
259 | return 0 | |
260 | } | |
261 | ||
262 | post_process() { | |
263 | # nothing do in Plamo Linux | |
264 | true | |
265 | } | |
266 | ||
267 | do_bindhome() { | |
268 | # bind-mount the user's path into the container's /home | |
269 | h=`getent passwd $bindhome | cut -d: -f6` | |
270 | mkdir -p $rootfs/$h | |
f24a52d5 | 271 | echo "lxc.mount.entry = $h $rootfs/$h none bind 0 0" >> $path/config |
cab79123 KY |
272 | # copy /etc/passwd, /etc/shadow, and /etc/group entries into container |
273 | if ! pwd=`getent passwd $bindhome` ; then | |
274 | echo "Warning: failed to copy password entry for $bindhome." | |
275 | else | |
276 | echo $pwd >> $rootfs/etc/passwd | |
277 | fi | |
278 | echo `getent shadow $bindhome` >> $rootfs/etc/shadow | |
279 | } | |
280 | ||
281 | cleanup() { | |
282 | [ -d $dlcache -a -d $rtcache ] || return 0 | |
283 | # lock, so we won't purge while someone is creating a repository | |
284 | ( | |
ffeb76b4 | 285 | if ! flock -n 9 ; then |
cab79123 KY |
286 | echo "Cache repository is busy." |
287 | return 1 | |
288 | fi | |
289 | echo "Purging the download cache..." | |
290 | rm -rf --one-file-system $dlcache $rtcache || return 1 | |
291 | echo "Done." | |
292 | return 0 | |
ffeb76b4 | 293 | ) 9> @LOCALSTATEDIR@/lock/subsys/lxc-plamo |
cab79123 KY |
294 | } |
295 | ||
296 | usage() { | |
297 | cat <<- EOF | |
298 | $prog [-h|--help] -p|--path=<path> -n|--name=<name> --rootfs=<rootfs> | |
ea00a202 | 299 | [-c|--clean] [-r|--release=<release>] [-a|--arch=<arch>] |
ffeb76b4 | 300 | [-b|--bindhome=<user>] |
cab79123 | 301 | release: $release |
cab79123 | 302 | arch: x86 or x86_64: defaults to host arch |
ffeb76b4 | 303 | bindhome: bind <user>'s home into the container |
cab79123 KY |
304 | EOF |
305 | } | |
306 | ||
307 | prog=`basename $0` | |
308 | path="" ; name="" ; rootfs="" | |
309 | clean=0 | |
64600fe3 | 310 | release=${release:-6.x} |
cab79123 | 311 | arch=`uname -m | sed 's/i.86/x86/'` ; hostarch=$arch |
ffeb76b4 TS |
312 | bindhome="" |
313 | sopts=hp:n:cr:a:b: | |
314 | lopts=help,path:,name:,rootfs:,clean,release:,arch:,bindhome: | |
cab79123 KY |
315 | if ! options=`getopt -o $sopts -l $lopts -- "$@"` ; then |
316 | usage | |
317 | exit 1 | |
318 | fi | |
319 | eval set -- "$options" | |
320 | while true ; do | |
321 | case "$1" in | |
322 | -h|--help) usage && exit 0 ;; | |
323 | -p|--path) path=$2 ; shift 2 ;; | |
324 | -n|--name) name=$2 ; shift 2 ;; | |
325 | --rootfs) rootfs=$2 ; shift 2 ;; | |
326 | -c|--clean) clean=1 ; shift 1 ;; | |
327 | -r|--release) release=$2 ; shift 2 ;; | |
cab79123 | 328 | -a|--arch) arch=$2 ; shift 2 ;; |
ffeb76b4 | 329 | -b|--bindhome) bindhome=$2 ; shift 2 ;; |
cab79123 KY |
330 | --) shift 1 ; break ;; |
331 | *) break ;; | |
332 | esac | |
333 | done | |
334 | if [ $clean -eq 1 -a -z "$path" ] ; then | |
335 | cleanup || exit 1 | |
336 | exit 0 | |
337 | fi | |
338 | if [ $hostarch == "x86" -a $arch == "x86_64" ] ; then | |
339 | echo "Can't create x86_64 container on x86." | |
340 | exit 1 | |
341 | fi | |
cab79123 KY |
342 | if [ -z "$path" ] ; then |
343 | echo "'path' parameter is required." | |
344 | exit 1 | |
345 | fi | |
346 | if [ -z "$name" ] ; then | |
347 | echo "'name' parameter is required." | |
348 | exit 1 | |
349 | fi | |
350 | if [ `id -u` -ne 0 ] ; then | |
351 | echo "This script should be run as 'root'." | |
352 | exit 1 | |
353 | fi | |
da7b3231 | 354 | cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc}" |
cab79123 KY |
355 | ptcache=$cache/partial-${prog##*-}-$release-$arch |
356 | dlcache=$cache/cache-${prog##*-}-$release-$arch | |
357 | rtcache=$cache/rootfs-${prog##*-}-$release-$arch | |
358 | if [ -z "$rootfs" ] ; then | |
7a96a068 CB |
359 | if grep -q "^lxc.rootfs.path" $path/config ; then |
360 | rootfs=`awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config` | |
cab79123 KY |
361 | else |
362 | rootfs=$path/rootfs | |
363 | fi | |
364 | fi | |
365 | if ! install_plamo ; then | |
366 | echo "Failed to install plamo $release." | |
367 | exit 1 | |
368 | fi | |
369 | if ! configure_plamo ; then | |
370 | echo "Failed to configure plamo $release for a container." | |
371 | exit 1 | |
372 | fi | |
373 | if ! copy_configuration ; then | |
374 | echo "Failed to write configuration file." | |
375 | exit 1 | |
376 | fi | |
377 | post_process | |
378 | if [ -n "$bindhome" ] ; then | |
379 | do_bindhome | |
380 | fi | |
381 | if [ $clean -eq 1 ] ; then | |
382 | cleanup || exit 1 | |
383 | exit 0 | |
384 | fi |