[lxc-devel] [PATCH] add lxc-cirros
Serge Hallyn
serge.hallyn at ubuntu.com
Fri May 10 05:52:22 UTC 2013
Add a template to create a cirros container. One great thing about
cirros is that the image you download is 3.5M.
Thanks smoser!
Note by default /etc/inittab doesn't have a /dev/console entry, so you
don't get a login on the lxc-start console. Adding
console::respawn:/sbin/getty 115200 console
makes that work, but ctrl-c still gets forwarded to init which then
reboots. So I didn't bother adding console as part of the template
(yet). Instead I simply lxc-start -d, then lxc-console.
Signed-off-by: Scott Moser <scott.moser at canonical.com>
Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
configure.ac | 1 +
templates/Makefile.am | 3 +-
templates/lxc-cirros.in | 288 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 291 insertions(+), 1 deletion(-)
create mode 100644 templates/lxc-cirros.in
diff --git a/configure.ac b/configure.ac
index f27fb87..414d71b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -363,6 +363,7 @@ AC_CONFIG_FILES([
hooks/Makefile
templates/Makefile
+ templates/lxc-cirros
templates/lxc-debian
templates/lxc-ubuntu
templates/lxc-ubuntu-cloud
diff --git a/templates/Makefile.am b/templates/Makefile.am
index 0c30667..98d6d72 100644
--- a/templates/Makefile.am
+++ b/templates/Makefile.am
@@ -11,4 +11,5 @@ templates_SCRIPTS = \
lxc-busybox \
lxc-sshd \
lxc-archlinux \
- lxc-alpine
+ lxc-alpine \
+ lxc-cirros
diff --git a/templates/lxc-cirros.in b/templates/lxc-cirros.in
new file mode 100644
index 0000000..88827db
--- /dev/null
+++ b/templates/lxc-cirros.in
@@ -0,0 +1,288 @@
+#!/bin/bash
+
+# template script for generating ubuntu container for LXC
+#
+# This script consolidates and extends the existing lxc ubuntu scripts
+#
+
+# Copyright © 2013 Canonical Ltd.
+# Author: Scott Moser <scott.moser at canonical.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2, as
+# published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+VERBOSITY=0
+TEMP_D=""
+DOWNLOAD_URL="http://download.cirros-cloud.net/"
+CACHE_D="/var/cache/lxc/cirros"
+CACHE_D="@LOCALSTATEDIR@/cache/lxc/cirros"
+TMP_FILE=""
+
+UNAME_M=$(uname -m)
+ARCHES=( i386 x86_64 amd64 arm )
+STREAMS=( released devel )
+BUILD="standard"
+
+DEF_VERSION="released"
+case "${UNAME_M}" in
+ i?86) DEF_ARCH="i386";;
+ x86_64) DEF_ARCH="x86_64";;
+ arm*) DEF_ARCH="arm";;
+ *) DEF_ARCH="i386";;
+esac
+
+
+error() { echo "$@" 1>&2; }
+errorp() { printf "$@" 1>&2; }
+fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
+failp() { [ $# -eq 0 ] || errorp "$@"; exit 1; }
+inargs() {
+ local needle="$1" x=""
+ shift
+ for x in "$@"; do
+ [ "$needle" = "$x" ] && return 0
+ done
+ return 1
+}
+
+Usage() {
+ cat <<EOF
+${0##*/} [options]
+
+ -a | --arch A architecture to use [${ARCHES}]
+ default: ${DEF_ARCH}
+ -h | --help this usage
+ -v | --verbose increase verbosity
+ -S | --auth-key K insert auth key 'K'
+ -v | --version V version [${STREAMS[*]}]
+ default: ${DEF_VERSION}
+ -u | --userdata U user-data file
+EOF
+}
+
+bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
+cleanup() {
+ [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
+ [ -z "${TEMP_FILE}" ] || rm -Rf "${TEMP_FILE}"
+}
+
+debug() {
+ local level=${1}; shift;
+ [ "${level}" -gt "${VERBOSITY}" ] && return
+ error "${@}"
+}
+jsondict() {
+ local k="" v="" ret="{"
+ for arg in "$@"; do
+ k="${arg%%=*}"
+ v="${arg#*=}"
+ ret="${ret} \"${k}\": \"$v\","
+ done
+ ret="${ret%,} }"
+ echo "$ret"
+}
+
+copy_configuration()
+{
+ local path=$1 rootfs=$2 name=$3 arch=$4 release=$5
+cat >> "$path/config" <<EOF
+# Template used to create this container: cirros
+
+lxc.rootfs = $rootfs
+#lxc.mount = $path/fstab
+lxc.pivotdir = lxc_putold
+
+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 rwm
+# 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
+}
+
+insert_ds() {
+ local root_d="$1" dstype="$2" authkey="$3" userdata="$4"
+ local sdir="$root_d/var/lib/cloud/seed/nocloud"
+
+ mkdir -p "$sdir" ||
+ { error "failed to make datasource dir $sdir"; return 1; }
+ rm -f "$sdir/meta-data" "$sdir/user-data" ||
+ { error "failed to clean old data from $sdir"; return 1; }
+
+ iid="iid-local01"
+ jsondict "instance-id=$iid" \
+ ${authkeys:+"public-keys=${authkeys}"} > "$sdir/meta-data" ||
+ { error "failed to write metadata to $sdir/meta-data"; return 1; }
+
+ [ -z "$userdata" ] ||
+ echo "$userdata" > "$sdir/user-data" ||
+ { error "failed to write user-data to $sdir"; return 1; }
+}
+
+extract_rootfs() {
+ local tarball="$1" rootfs_d="$2"
+ mkdir -p "${rootfs_d}" ||
+ { error "failed to make rootfs dir ${rootfs_d}"; return 1; }
+
+ tar -C "${rootfs_d}" -Sxzf "${tarball}" ||
+ { error "failed to populate ${rootfs_d}"; return 1; }
+ return 0
+}
+
+download_tarball() {
+ local arch="$1" ver="$2" cached="$3" baseurl="$4"
+ local out="" outd="" file="" dlpath=""
+ file="cirros-$ver-$arch-lxc.tar.gz"
+ dlpath="$ver/$file"
+ outd="${cached}/${dlpath%/*}"
+ if [ -f "$cached/$dlpath" ]; then
+ _RET="$cached/$dlpath"
+ return 0
+ fi
+
+ mkdir -p "${outd}" ||
+ { error "failed to create ${outd}"; return 1; }
+
+ wget "${baseurl%/}/$dlpath" -O "$cached/${dlpath}.$$" &&
+ mv "$cached/$dlpath.$$" "$cached/$dlpath" || {
+ rm -f "$cached/$dlpath.$$";
+ error "failed to download $dlpath";
+ return 1;
+ }
+ _RET="$cached/$dlpath"
+}
+
+short_opts="a:n:p:S:huV"
+long_opts="arch:,auth-key:,name:,path:,userdata:,verbose,version:"
+getopt_out=$(getopt --name "${0##*/}" \
+ --options "${short_opts}" --long "${long_opts}" -- "$@") &&
+ eval set -- "${getopt_out}" ||
+ bad_Usage
+
+arch="${DEF_ARCH}"
+version="${DEF_VERSION}"
+authkey_f=""
+authkeys=""
+userdata=""
+seed=true
+path=""
+
+while [ $# -ne 0 ]; do
+ cur=$1; next=$2;
+ case "$cur" in
+ -a|--arch) arch="$next"; shift;;
+ -h|--help) Usage ; exit 0;;
+ -n|--name) name="$next"; shift;;
+ -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
+ -S|--auth-key) authkey_f="$next"; shift;;
+ -p|--path) path=$next; shift;;
+ -v|--version) version=$next; shift;;
+ -u|--userdata) userdata="$next"; shift;;
+ --) shift; break;;
+ esac
+ shift;
+done
+
+[ $# -eq 0 ] || bad_Usage "unexpected arguments: $*"
+[ -n "$path" ] || fail "'path' parameter is required"
+
+if [ "$(id -u)" != "0" ]; then
+ fail "must be run as root"
+fi
+
+case "$arch" in
+ i?86) arch="i386";;
+ amd64) arch="x86_65";;
+esac
+
+inargs "$arch" "${ARCHES[@]}" ||
+ fail "bad arch '$arch'. allowed: ${ARCHES[*]}"
+
+if inargs "$version" "${STREAMS[@]}"; then
+ out=$(wget -O - -q "${DOWNLOAD_URL%/}/version/$version") ||
+ fail "failed to convert 'version=$version'"
+ version="$out"
+fi
+
+if [ -n "$authkey_f" ]; then
+ if [ ! -f "$authkey_f" ]; then
+ echo "--auth-key=${authkey_f} must reference a file"
+ exit 1
+ fi
+ authkeys=$(cat "$authkey")
+fi
+
+trap cleanup EXIT
+
+download_tarball "$arch" "$version" "${CACHE_D}" "${DOWNLOAD_URL}" || fail
+tarball="$_RET"
+
+rootfs_d="$path/rootfs"
+extract_rootfs "${tarball}" "${rootfs_d}" || fail
+
+# oopsie - some cirros tarballs ship random as a blockdev, breaking
+# dropbear.
+if [ -b ${rootfs_d}/dev/random ]; then
+ rm -f ${rootfs_d}/dev/random
+ rm -f ${rootfs_d}/dev/urandom
+ mknod ${rootfs_d}/dev/random c 1 8
+ mknod ${rootfs_d}/dev/urandom c 1 9
+ chmod 777 ${rootfs_d}/dev/random ${rootfs_d}/dev/urandom
+fi
+
+if false; then
+ insert_ds "$path/rootfs" "nocloud" "$authkeys" "$userdata" ||
+ fail "failed to insert userdata to $path/rootfs"
+else
+ # disable ec2, because its annoying
+ sed -i 's,ec2,,' "$path/rootfs/etc/cirros-init/config"
+fi
+
+copy_configuration "$path" "$path/rootfs" "$name" "$arch" "$release"
+
+
+# vi: ts=4 expandtab
--
1.8.1.2
More information about the lxc-devel
mailing list