[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