# This script consolidates and extends the existing lxc ubuntu scripts
#
-# Copyright © 2011 Serge Hallyn <serge.hallyn@canonical.com>
-# Copyright © 2010 Wilhelm Meier
+# Copyright © 2011 Serge Hallyn <serge.hallyn@canonical.com>
+# Copyright © 2010 Wilhelm Meier
# Author: Wilhelm Meier <wilhelm.meier@fh-kl.de>
#
# This library is free software; you can redistribute it and/or
set -e
+LOCALSTATEDIR="@LOCALSTATEDIR@"
+LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
+
if [ -r /etc/default/lxc ]; then
. /etc/default/lxc
fi
fi
# generate new SSH keys
- if [ -x $rootfs@LOCALSTATEDIR@/lib/dpkg/info/openssh-server.postinst ]; then
+ if [ -x $rootfs$LOCALSTATEDIR/lib/dpkg/info/openssh-server.postinst ]; then
cat > $rootfs/usr/sbin/policy-rc.d << EOF
#!/bin/sh
exit 101
rm -f $rootfs/etc/ssh/ssh_host_*key*
mv $rootfs/etc/init/ssh.conf $rootfs/etc/init/ssh.conf.disabled
- DPKG_MAINTSCRIPT_PACKAGE=openssh DPKG_MAINTSCRIPT_NAME=postinst chroot $rootfs @LOCALSTATEDIR@/lib/dpkg/info/openssh-server.postinst configure
+ DPKG_MAINTSCRIPT_PACKAGE=openssh DPKG_MAINTSCRIPT_NAME=postinst chroot $rootfs $LOCALSTATEDIR/lib/dpkg/info/openssh-server.postinst configure
mv $rootfs/etc/init/ssh.conf.disabled $rootfs/etc/init/ssh.conf
+ sed -i "s/root@$(hostname)/root@$hostname/g" $rootfs/etc/ssh/ssh_host_*.pub
+
rm -f $rootfs/usr/sbin/policy-rc.d
fi
return 0
}
+# A function to try and autodetect squid-deb-proxy servers on the local network
+# if either the squid-deb-proxy-client package is installed on the host or
+# a parent container set the 50squid-deb-proxy-client file.
+squid_deb_proxy_autodetect()
+{
+ local apt_discover=/usr/share/squid-deb-proxy-client/apt-avahi-discover
+ local proxy_file=/etc/apt/apt.conf.d/50squid-deb-proxy-client
+ squid_proxy_line= # That's a global :/
+
+ # Maybe the host is aware of a squid-deb-proxy?
+ if [ -f $apt_discover ]; then
+ echo -n "Discovering squid-deb-proxy..."
+ squid_proxy_line=$($apt_discover)
+ if [ -n "$squid_proxy_line" ]; then
+ echo "found squid-deb-proxy: $squid_proxy_line"
+ else
+ echo "no squid-deb-proxy found"
+ fi
+ fi
+
+ # Are we in a nested container, and the parent already knows of a proxy?
+ if [ -f $proxy_file ]; then
+ # Extract the squid URL from the file (whatever is between "")
+ squid_proxy_line=`cat $proxy_file | sed "s/.*\"\(.*\)\".*/\1/"`
+ fi
+}
+
#
# Choose proxies for container
# http_proxy will be used by debootstrap on the host.
fi
case "$HTTP_PROXY" in
none)
- APT_PROXY=
+ squid_deb_proxy_autodetect
+ if [ -n "$squid_proxy_line" ]; then
+ APT_PROXY=$squid_proxy_line
+ export http_proxy=$squid_proxy_line
+ else
+ APT_PROXY=
+ fi
;;
apt)
RES=`apt-config shell APT_PROXY Acquire::http::Proxy`
fi
}
+install_packages()
+{
+ local rootfs="$1"
+ shift
+ local packages="$*"
+ if [ -z $update ]
+ then
+ chroot $rootfs apt-get update
+ update=true
+ fi
+ if [ -n "${packages}" ]
+ then
+ chroot $rootfs apt-get install --force-yes -y --no-install-recommends ${packages}
+ fi
+}
+
cleanup()
{
rm -rf $cache/partial-$arch
suggest_flush()
{
echo "Container upgrade failed. The container cache may be out of date,"
- echo "in which case flushing the case (see -F in the hep output) may help."
+ echo "in which case flushing the cache (see -F in the help output) may help."
}
download_ubuntu()
cache=$1
arch=$2
release=$3
- packages=$4
+
+ packages_template=${packages_template:-"ssh,vim"}
# Try to guess a list of langpacks to install
langpacks="language-pack-en"
dpkg -l | grep -E "^ii language-pack-[a-z]* " |
cut -d ' ' -f3) | sort -u`
fi
- packages="$packages,$(echo $langpacks | sed 's/ /,/g')"
+ packages_template="${packages_template},$(echo $langpacks | sed 's/ /,/g')"
- echo "installing packages: $packages"
+ echo "Installing packages in template: ${packages_template}"
trap cleanup EXIT SIGHUP SIGINT SIGTERM
# check the mini ubuntu was not already downloaded
# download a mini ubuntu into a cache
echo "Downloading ubuntu $release minimal ..."
if [ -n "$(which qemu-debootstrap)" ]; then
- qemu-debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
+ qemu-debootstrap --verbose --components=main,universe --arch=$arch --include=${packages_template} $release $cache/partial-$arch $MIRROR
else
- debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
+ debootstrap --verbose --components=main,universe --arch=$arch --include=${packages_template} $release $cache/partial-$arch $MIRROR
fi
if [ $? -ne 0 ]; then
rootfs=$1
release=$2
flushcache=$3
- cache="@LOCALSTATEDIR@/cache/lxc/$release"
- mkdir -p @LOCALSTATEDIR@/lock/subsys/
+ cache="$LOCALSTATEDIR/cache/lxc/$release"
+ mkdir -p $LOCALSTATEDIR/lock/subsys/
(
- flock -x 200
+ flock -x 9
if [ $? -ne 0 ]; then
echo "Cache repository is busy."
return 1
echo "Checking cache download in $cache/rootfs-$arch ... "
if [ ! -e "$cache/rootfs-$arch" ]; then
- download_ubuntu $cache $arch $release $packages
+ download_ubuntu $cache $arch $release
if [ $? -ne 0 ]; then
echo "Failed to download 'ubuntu $release base'"
return 1
return 0
- ) 200>@LOCALSTATEDIR@/lock/subsys/lxc-ubuntu
+ ) 9>$LOCALSTATEDIR/lock/subsys/lxc-ubuntu$release
return $?
}
arch="i686"
fi
- ttydir=""
- if [ -f $rootfs/etc/init/container-detect.conf ]; then
- ttydir=" lxc"
- fi
-
# if there is exactly one veth network entry, make sure it has an
# associated hwaddr.
nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
grep -q "^lxc.network.hwaddr" $path/config || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config
fi
+ # Generate the configuration file
+ ## Create the fstab (empty by default)
+ touch $path/fstab
+
+ ## Relocate all the network config entries
+ sed -i -e "/lxc.network/{w ${path}/config-network" -e "d}" $path/config
+
+ ## Relocate any other config entries
+ sed -i -e "/lxc./{w ${path}/config-auto" -e "d}" $path/config
+
+ ## Add all the includes
+ echo "" >> $path/config
+ echo "# Common configuration" >> $path/config
+ if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu.common.conf" ]; then
+ echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.common.conf" >> $path/config
+ fi
+ if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu.${release}.conf" ]; then
+ echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.${release}.conf" >> $path/config
+ fi
+
+ ## Add the container-specific config
+ echo "" >> $path/config
+ echo "# Container specific configuration" >> $path/config
+ [ -e "$path/config-auto" ] && cat $path/config-auto >> $path/config && rm $path/config-auto
grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config
cat <<EOF >> $path/config
lxc.mount = $path/fstab
-lxc.pivotdir = lxc_putold
-
-lxc.devttydir =$ttydir
-lxc.tty = 4
-lxc.pts = 1024
-
lxc.utsname = $name
lxc.arch = $arch
-lxc.cap.drop = sys_module mac_admin mac_override sys_time
-
-# When using LXC with apparmor, uncomment the next line to run unconfined:
-#lxc.aa_profile = unconfined
-
-# To support container nesting on an Ubuntu host, uncomment next two lines:
-#lxc.aa_profile = lxc-container-default-with-nesting
-#lxc.hook.mount = /usr/share/lxc/hooks/mountcgroups
-
-lxc.cgroup.devices.deny = a
-# Allow any mknod (but not using the node)
-lxc.cgroup.devices.allow = c *:* m
-lxc.cgroup.devices.allow = b *:* m
-# /dev/null and zero
-lxc.cgroup.devices.allow = c 1:3 rwm
-lxc.cgroup.devices.allow = c 1:5 rwm
-# consoles
-lxc.cgroup.devices.allow = c 5:1 rwm
-lxc.cgroup.devices.allow = c 5:0 rwm
-# /dev/{,u}random
-lxc.cgroup.devices.allow = c 1:9 rwm
-lxc.cgroup.devices.allow = c 1:8 rwm
-lxc.cgroup.devices.allow = c 136:* rwm
-lxc.cgroup.devices.allow = c 5:2 rwm
-# rtc
-lxc.cgroup.devices.allow = c 254:0 rm
-# fuse
-lxc.cgroup.devices.allow = c 10:229 rwm
-# tun
-lxc.cgroup.devices.allow = c 10:200 rwm
-# full
-lxc.cgroup.devices.allow = c 1:7 rwm
-# hpet
-lxc.cgroup.devices.allow = c 10:228 rwm
-# kvm
-lxc.cgroup.devices.allow = c 10:232 rwm
EOF
- cat <<EOF > $path/fstab
-proc proc proc nodev,noexec,nosuid 0 0
-sysfs sys sysfs defaults 0 0
-/sys/fs/fuse/connections sys/fs/fuse/connections none bind,optional 0 0
-/sys/kernel/debug sys/kernel/debug none bind,optional 0 0
-/sys/kernel/security sys/kernel/security none bind,optional 0 0
-/sys/fs/pstore sys/fs/pstore none bind,optional 0 0
-EOF
+ ## Re-add the previously removed network config
+ echo "" >> $path/config
+ echo "# Network configuration" >> $path/config
+ cat $path/config-network >> $path/config
+ rm $path/config-network
if [ $? -ne 0 ]; then
echo "Failed to add configuration"
{
rootfs=$1
release=$2
+ packages=$3
+
+ # Disable service startup
+ cat > $rootfs/usr/sbin/policy-rc.d << EOF
+#!/bin/sh
+exit 101
+EOF
+ chmod +x $rootfs/usr/sbin/policy-rc.d
if [ ! -f $rootfs/etc/init/container-detect.conf ]; then
# Make sure we have a working resolv.conf
# ppa and install lxcguest
if [ $release = "lucid" ]; then
chroot $rootfs apt-get update
- chroot $rootfs apt-get install --force-yes -y python-software-properties
+ install_packages $rootfs "python-software-properties"
chroot $rootfs add-apt-repository ppa:ubuntu-virt/ppa
fi
else
HOST_PACKAGES="$HOST_PACKAGES iproute:${hostarch}"
fi
- chroot $rootfs apt-get install --force-yes -y --no-install-recommends $HOST_PACKAGES
+ install_packages $rootfs $HOST_PACKAGES
+ fi
+
+ # Install Packages in container
+ if [ -n "$packages" ]
+ then
+ local packages="`echo $packages | sed 's/,/ /g'`"
+ echo "Installing packages: ${packages}"
+ install_packages $rootfs $packages
+ fi
+
+ # Set initial timezone as on host
+ if [ -f /etc/timezone ]; then
+ cat /etc/timezone > $rootfs/etc/timezone
+ chroot $rootfs dpkg-reconfigure -f noninteractive tzdata
+ elif [ -f /etc/sysconfig/clock ]; then
+ . /etc/sysconfig/clock
+ echo $ZONE > $rootfs/etc/timezone
+ chroot $rootfs dpkg-reconfigure -f noninteractive tzdata
+ else
+ echo "Timezone in container is not configured. Adjust it manually."
fi
# rmdir /dev/shm for containers that have /run/shm
# I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did
# get bind mounted to the host's /run/shm. So try to rmdir
# it, and in case that fails move it out of the way.
+ # NOTE: This can only be removed once 12.04 goes out of support
if [ ! -L $rootfs/dev/shm ] && [ -d $rootfs/run/shm ] && [ -e $rootfs/dev/shm ]; then
- mv $rootfs/dev/shm $rootfs/dev/shm.bak
+ rmdir $rootfs/dev/shm 2>/dev/null || mv $rootfs/dev/shm $rootfs/dev/shm.bak
ln -s /run/shm $rootfs/dev/shm
fi
+
+ # Re-enable service startup
+ rm $rootfs/usr/sbin/policy-rc.d
}
do_bindhome()
echo "shell $shell for user $user was not found in the container."
pkg=`dpkg -S $(readlink -m $shell) | cut -d ':' -f1`
echo "Installing $pkg"
- chroot $rootfs apt-get --force-yes -y install $pkg
+ install_packages $rootfs $pkg
fi
shad=`getent shadow $user`
return 0
}
-options=$(getopt -o a:b:hp:r:n:FS:du: -l arch:,bindhome:,help,path:,release:,name:,flush-cache,auth-key:,debug,rootfs:,packages:,user:,password: -- "$@")
+options=$(getopt -o a:b:hp:r:n:FS:du: -l arch:,bindhome:,help,path:,release:,name:,flush-cache,auth-key:,debug,rootfs:,packages:,user:,password:,mirror:,security-mirror: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
debug=0
hostarch=$arch
flushcache=0
-packages="vim,ssh"
+packages=""
user="ubuntu"
password="ubuntu"
while true
-a|--arch) arch=$2; shift 2;;
-S|--auth-key) auth_key=$2; shift 2;;
-d|--debug) debug=1; shift 1;;
+ --mirror) MIRROR=$2; shift 2;;
+ --security-mirror) SECURITY_MIRROR=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
fi
-if [ "$arch" == "i686" ]; then
+if [ "$arch" = "i686" ]; then
arch=i386
fi
fi
fi
-install_ubuntu $rootfs $release $flushcache $packages
+install_ubuntu $rootfs $release $flushcache
if [ $? -ne 0 ]; then
echo "failed to install ubuntu $release"
exit 1
exit 1
fi
-post_process $rootfs $release $trim_container
+post_process $rootfs $release $trim_container $packages
if [ -n "$bindhome" ]; then
do_bindhome $rootfs $bindhome