4 # template script for generating PLD Linux container for LXC
8 # lxc: Linux Container library
11 # Elan Ruusamäe <glen@pld-linux.org>
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.
18 # This library is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 # Lesser General Public License for more details.
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
25 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 # Detect use under userns (unsupported)
29 [ "$arg" = "--" ] && break
30 if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
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
39 cache_base
=@LOCALSTATEDIR@
/cache
/lxc
/pld
/$arch
40 default_path
=@LXCPATH@
43 if [ -e /etc
/os-release
]; then
44 # This is a shell friendly configuration file. We can just source it.
45 # What we're looking for in here is the ID, VERSION_ID and the CPE_NAME
47 echo "Host CPE ID from /etc/os-release: ${CPE_NAME}"
50 if [ "${CPE_NAME}" != "" -a "${ID}" = "pld" -a "${VERSION_ID}" != "" ]; then
51 pld_host_ver
=${VERSION_ID}
53 elif [ -e /etc
/pld-release
]; then
54 # Only if all other methods fail, try to parse the pld-release file.
55 pld_host_ver
=$
(sed -e '/PLD /!d' -e 's/^\([0-9.]*\)\sPLD.*/\1/' < /etc
/pld-release
)
56 if [ "$pld_host_ver" != "" ]; then
61 # Map a few architectures to their generic PLD Linux repository archs.
62 case "$pld_host_ver:$arch" in
63 3.0:i586
) arch
=i486
;;
70 mkdir
-p $rootfs_path/selinux
71 echo 0 > $rootfs_path/selinux
/enforce
73 # configure the network using the dhcp
74 sed -i -e "s/^HOSTNAME=.*/HOSTNAME=${utsname}/" ${rootfs_path}/etc
/sysconfig
/network
76 # set hostname on systemd
77 if [ $release = "3.0" ]; then
78 echo "${utsname}" > ${rootfs_path}/etc
/hostname
82 test -e $rootfs_path/etc
/hosts || \
83 cat <<EOF > $rootfs_path/etc/hosts
84 127.0.0.1 localhost.localdomain localhost $utsname
85 ::1 localhost6.localdomain6 localhost6
88 dev_path
="${rootfs_path}/dev"
91 mknod
-m 666 ${dev_path}/null c
1 3
92 mknod
-m 666 ${dev_path}/zero c
1 5
93 mknod
-m 666 ${dev_path}/random c
1 8
94 mknod
-m 666 ${dev_path}/urandom c
1 9
95 mkdir
-m 755 ${dev_path}/pts
96 mkdir
-m 1777 ${dev_path}/shm
97 mknod
-m 666 ${dev_path}/tty c
5 0
98 mknod
-m 666 ${dev_path}/tty0 c
4 0
99 mknod
-m 666 ${dev_path}/tty1 c
4 1
100 mknod
-m 666 ${dev_path}/tty2 c
4 2
101 mknod
-m 666 ${dev_path}/tty3 c
4 3
102 mknod
-m 666 ${dev_path}/tty4 c
4 4
103 mknod
-m 600 ${dev_path}/console c
5 1
104 mknod
-m 666 ${dev_path}/full c
1 7
105 mknod
-m 600 ${dev_path}/initctl p
106 mknod
-m 666 ${dev_path}/ptmx c
5 2
108 echo "setting root passwd to $root_password"
109 echo "root:$root_password" | chroot
$rootfs_path chpasswd
116 # default powerfail action waits 2 minutes. for lxc we want it immediately
117 sed -i -e '/^pf::powerfail:/ s,/sbin/shutdown.*,/sbin/halt,' ${rootfs_path}/etc
/inittab
120 configure_pld_systemd
()
122 unlink
${rootfs_path}/etc
/systemd
/system
/default.target
123 chroot
${rootfs_path} ln -s /dev
/null
/etc
/systemd
/system
/udev.service
124 chroot
${rootfs_path} ln -s /lib
/systemd
/system
/multi-user.target
/etc
/systemd
/system
/default.target
126 # Actually, the After=dev-%i.device line does not appear in the
127 # Fedora 17 or Fedora 18 systemd getty@.service file. It may be left
128 # over from an earlier version and it's not doing any harm. We do need
129 # to disable the "ConditionalPathExists=/dev/tty0" line or no gettys are
130 # started on the ttys in the container. Lets do it in an override copy of
131 # the service so it can still pass rpm verifies and not be automatically
132 # updated by a new systemd version. -- mhw /\/\|=mhw=|\/\/
134 sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \
135 -e 's/After=dev-%i.device/After=/' \
136 < ${rootfs_path}/lib
/systemd
/system
/getty@.service \
137 > ${rootfs_path}/etc
/systemd
/system
/getty@.service
139 # Setup getty service on the 4 ttys we are going to allow in the
140 # default config. Number should match lxc.tty
142 ln -sf ..
/getty@.service
${rootfs_path}/etc
/systemd
/system
/getty.target.wants
/getty@tty
${i}.service
149 # check the mini pld was not already downloaded
150 INSTALL_ROOT
=$cache/partial
151 mkdir
-p $INSTALL_ROOT
152 if [ $?
-ne 0 ]; then
153 echo "Failed to create '$INSTALL_ROOT' directory"
157 # download a mini pld into a cache
158 echo "Downloading PLD Linux minimal ..."
159 POLDEK
="poldek --root $INSTALL_ROOT --noask --nohold --noignore"
160 PKG_LIST
="basesystem filesystem pld-release rpm poldek vserver-packages rc-scripts pwdutils mingetty"
162 mkdir
-p $INSTALL_ROOT@LOCALSTATEDIR@
/lib
/rpm
163 rpm
--root $INSTALL_ROOT --initdb
166 if [ $?
-ne 0 ]; then
167 echo "Failed to download the rootfs, aborting."
171 mv "$INSTALL_ROOT" "$cache/rootfs"
172 echo "Download complete."
180 # make a local copy of the minipld
181 echo -n "Copying rootfs to $rootfs_path ..."
182 cp -a $cache/rootfs
/* $rootfs_path ||
return 1
188 POLDEK
="poldek --root $cache/rootfs --noask"
189 $POLDEK --upgrade-dist
194 mkdir
-p @LOCALSTATEDIR@
/lock
/subsys
/
197 if [ $?
-ne 0 ]; then
198 echo "Cache repository is busy."
202 echo "Checking cache download in $cache/rootfs ... "
203 if [ ! -e "$cache/rootfs" ]; then
205 if [ $?
-ne 0 ]; then
206 echo "Failed to download 'pld base'"
210 echo "Cache found. Updating..."
212 if [ $?
-ne 0 ]; then
213 echo "Failed to update 'pld base', continuing with last known good cache"
215 echo "Update finished"
219 echo "Copy $cache/rootfs to $rootfs_path ... "
221 if [ $?
-ne 0 ]; then
222 echo "Failed to copy rootfs"
227 ) 9>@LOCALSTATEDIR@
/lock
/subsys
/lxc-pld
235 mkdir
-p $config_path
236 grep -q "^lxc.rootfs" $config_path/config
2>/dev
/null ||
echo "lxc.rootfs = $rootfs_path" >> $config_path/config
237 cat <<EOF >> $config_path/config
238 # Most of below settings should be taken as defaults from
239 # lxc.include = /usr/share/lxc/config/common.conf
240 lxc.utsname = $utsname
243 # Consider if below line is right for systemd container
244 lxc.mount = $config_path/fstab
245 lxc.cap.drop = sys_module mac_admin mac_override sys_time
247 lxc.autodev = $auto_dev
249 # When using LXC with apparmor, uncomment the next line to run unconfined:
250 #lxc.aa_profile = unconfined
254 #lxc.cgroup.devices.allow = a
256 lxc.cgroup.devices.deny = a
257 # Allow to mknod all devices (but not using them)
258 lxc.cgroup.devices.allow = c *:* m
259 lxc.cgroup.devices.allow = b *:* m
262 lxc.cgroup.devices.allow = c 1:3 rwm
263 lxc.cgroup.devices.allow = c 1:5 rwm
265 lxc.cgroup.devices.allow = c 5:1 rwm
266 lxc.cgroup.devices.allow = c 5:0 rwm
267 lxc.cgroup.devices.allow = c 4:0 rwm
268 lxc.cgroup.devices.allow = c 4:1 rwm
270 lxc.cgroup.devices.allow = c 1:9 rwm
271 lxc.cgroup.devices.allow = c 1:8 rwm
272 lxc.cgroup.devices.allow = c 136:* rwm
273 lxc.cgroup.devices.allow = c 5:2 rwm
275 lxc.cgroup.devices.allow = c 254:0 rm
278 cat <<EOF > $config_path/fstab
279 proc proc proc nodev,noexec,nosuid 0 0
280 sysfs sys sysfs defaults 0 0
282 if [ $?
-ne 0 ]; then
283 echo "Failed to add configuration"
293 if [ ! -e $cache ]; then
297 # lock, so we won't purge while someone is creating a repository
301 echo "Cache repository is busy."
305 echo -n "Purging the download cache for PLD Linux $release..."
306 rm --preserve-root --one-file-system -rf $cache && echo "Done." ||
exit 1
308 ) 9>@LOCALSTATEDIR@
/lock
/subsys
/lxc-pld
315 $1 -n|--name=<container_name>
316 [-p|--path=<path>] [-c|--clean] [-R|--release=<PLD Release>] [--fqdn=<network name of container>] [-A|--arch=<arch of the container>]
319 -n,--name container name, used to as an identifier for that container from now on
321 -p,--path path to where the container will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case
322 --rootfs path for actual rootfs.
323 -c,--clean clean the cache
324 -R,--release PLD Linux release for the new container. if the host is PLD Linux, then it will default to the host's release.
325 --fqdn fully qualified domain name (FQDN) for DNS and system naming
326 -A,--arch NOT USED YET. Define what arch the container will be [i686,x86_64]
327 -h,--help print this help
332 options
=$
(getopt
-o hp
:n
:cR
: -l help,path
:,rootfs
:,name
:,clean
,release
:,fqdn
: -- "$@")
333 if [ $?
-ne 0 ]; then
337 eval set -- "$options"
341 -h|
--help) usage
$0 && exit 0;;
342 -p|
--path) path
=$2; shift 2;;
343 --rootfs) rootfs
=$2; shift 2;;
344 -n|
--name) name
=$2; shift 2;;
345 -c|
--clean) clean
=$2; shift 2;;
346 -R|
--release) release
=$2; shift 2;;
347 --fqdn) utsname
=$2; shift 2;;
348 --) shift 1; break ;;
353 if [ ! -z "$clean" -a -z "$path" ]; then
358 if [ -z "${utsname}" ]; then
362 # This follows a standard "resolver" convention that an FQDN must have
363 # at least two dots or it is considered a local relative host name.
364 # If it doesn't, append the dns domain name of the host system.
366 # This changes one significant behavior when running
367 # "lxc_create -n Container_Name" without using the
371 # utsname and hostname = Container_Name
373 # utsname and hostname = Container_Name.Domain_Name
375 if [ $
(expr "$utsname" : '.*\..*\.') = 0 ]; then
376 if [ -n "$(dnsdomainname)" ]; then
377 utsname
=${utsname}.$
(dnsdomainname
)
382 type poldek
>/dev
/null
2>&1
383 if [ $?
-ne 0 ]; then
384 needed_pkgs
="poldek $needed_pkgs"
387 #type curl >/dev/null 2>&1
388 #if [ $? -ne 0 ]; then
389 # needed_pkgs="curl $needed_pkgs"
392 if [ -n "$needed_pkgs" ]; then
393 echo "Missing commands: $needed_pkgs"
394 echo "Please install these using \"sudo poldek -u $needed_pkgs\""
398 if [ -z "$path" ]; then
399 path
=$default_path/$name
402 if [ -z "$release" ]; then
403 if [ "$is_pld" -a "$pld_host_ver" ]; then
404 release
=$pld_host_ver
406 echo "This is not a PLD Linux host and release missing, defaulting to 3.0. use -R|--release to specify release"
411 # pld th have systemd. We need autodev enabled to keep systemd from causing problems.
412 if [ $release = 3.0 ]; then
418 if [ "$(id -u)" != "0" ]; then
419 echo "This script should be run as 'root'"
423 if [ -z "$rootfs" ]; then
424 rootfs_path
=$path/rootfs
425 # check for 'lxc.rootfs' passed in through default config by lxc-create
426 # TODO: should be lxc.rootfs.mount used instead?
427 if grep -q '^lxc.rootfs' $path/config
2>/dev
/null
; then
428 rootfs_path
=$
(awk -F= '/^lxc.rootfs =/{ print $2 }' $path/config
)
433 config_path
=$default_path/$name
434 cache
=$cache_base/$release
438 echo "Interrupted, so cleaning up"
440 # maybe was interrupted before copy config
442 rm -rf $default_path/$name
447 trap revert SIGHUP SIGINT SIGTERM
450 if [ $?
-ne 0 ]; then
451 echo "Failed write configuration file"
456 if [ $?
-ne 0 ]; then
457 echo "Failed to install PLD Linux"
462 if [ $?
-ne 0 ]; then
463 echo "Failed to configure PLD Linux for a container"
467 # If the systemd configuration directory exists - set it up for what we need.
468 if [ -d ${rootfs_path}/etc
/systemd
/system
]; then
469 configure_pld_systemd
472 # This configuration (rc.sysinit) is not inconsistent with the systemd stuff
473 # above and may actually coexist on some upgraded systems. Let's just make
474 # sure that, if it exists, we update this file, even if it's not used...
475 if [ -f ${rootfs_path}/etc
/rc.sysinit
]; then
479 if [ ! -z $clean ]; then
483 echo "container rootfs and config created"