diff mbox

[6/6] scripts: create a template to use with lxc-create

Message ID 1377820005-3835-7-git-send-email-laurent@vivier.eu
State New
Headers show

Commit Message

Laurent Vivier Aug. 29, 2013, 11:46 p.m. UTC
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 scripts/lxc-cross-debian | 353 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 353 insertions(+)
 create mode 100755 scripts/lxc-cross-debian

Comments

Peter Maydell Sept. 6, 2013, 4:33 p.m. UTC | #1
On 30 August 2013 00:46, Laurent Vivier <laurent@vivier.eu> wrote:
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  scripts/lxc-cross-debian | 353 +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 353 insertions(+)
>  create mode 100755 scripts/lxc-cross-debian
>
> diff --git a/scripts/lxc-cross-debian b/scripts/lxc-cross-debian
> new file mode 100755
> index 0000000..aded1d3
> --- /dev/null
> +++ b/scripts/lxc-cross-debian
> @@ -0,0 +1,353 @@
> +#!/bin/bash
> +#
> +# Some parts from lxc-debian, Daniel Lezcano <daniel.lezcano@free.fr>
> +#
> +# Copy this script to /usr/share/lxc/templates
> +#
> +# and use it with
> +# lxc-create -t cross-debian -n xxxx  -- --arch xxx --interpreter-path /a/b/c/qemu-xxx
> +#

I'm afraid I don't know enough about lxc to be able
to review this, or even to say whether it makes sense
for it to be in the QEMU git tree. (It needs a
copyright/license header if it does go in, though.)

-- PMM
Laurent Vivier Sept. 6, 2013, 4:56 p.m. UTC | #2
Le 06/09/2013 18:33, Peter Maydell a écrit :
> On 30 August 2013 00:46, Laurent Vivier <laurent@vivier.eu> wrote:
>> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
>> ---
>>   scripts/lxc-cross-debian | 353 +++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 353 insertions(+)
>>   create mode 100755 scripts/lxc-cross-debian
>>
>> diff --git a/scripts/lxc-cross-debian b/scripts/lxc-cross-debian
>> new file mode 100755
>> index 0000000..aded1d3
>> --- /dev/null
>> +++ b/scripts/lxc-cross-debian
>> @@ -0,0 +1,353 @@
>> +#!/bin/bash
>> +#
>> +# Some parts from lxc-debian, Daniel Lezcano <daniel.lezcano@free.fr>
>> +#
>> +# Copy this script to /usr/share/lxc/templates
>> +#
>> +# and use it with
>> +# lxc-create -t cross-debian -n xxxx  -- --arch xxx --interpreter-path /a/b/c/qemu-xxx
>> +#
> I'm afraid I don't know enough about lxc to be able
> to review this, or even to say whether it makes sense
> for it to be in the QEMU git tree. (It needs a
> copyright/license header if it does go in, though.)
Yes, you should be right. I'm going to try to push this into lxc project.

Thank you for your comments.

Regards,
Laurent
diff mbox

Patch

diff --git a/scripts/lxc-cross-debian b/scripts/lxc-cross-debian
new file mode 100755
index 0000000..aded1d3
--- /dev/null
+++ b/scripts/lxc-cross-debian
@@ -0,0 +1,353 @@ 
+#!/bin/bash
+#
+# Some parts from lxc-debian, Daniel Lezcano <daniel.lezcano@free.fr>
+#
+# Copy this script to /usr/share/lxc/templates
+#
+# and use it with
+# lxc-create -t cross-debian -n xxxx  -- --arch xxx --interpreter-path /a/b/c/qemu-xxx
+#
+
+SUITE=${SUITE:-stable}
+MIRROR=${MIRROR:-http://ftp.debian.org/debian}
+
+find_interpreter() {
+    qemu=$(basename "$1")
+
+    if [ ! -d /proc/sys/fs/binfmt_misc/ ] ; then
+        return 1
+    fi
+    for file in /proc/sys/fs/binfmt_misc/* ; do
+        if [ "$file" = "/proc/sys/fs/binfmt_misc/register" -o \
+             "$file" = "/proc/sys/fs/binfmt_misc/status" ] ; then
+            continue
+        fi
+        interpreter_path=$(sed -n "/^interpreter/s/interpreter \([^[:space:]]*\)/\1/p" "$file")
+        interpreter=$(basename $interpreter_path)
+        if [ "$qemu" = "$interpreter" ] ; then
+            echo "$interpreter_path"
+            return 0
+        fi
+    done
+    return 1
+}
+
+download_debian()
+{
+    cache="$1"
+    arch="$2"
+
+    if [ ! -d "$cache/archives-$SUITE-$arch" ]; then
+        if ! mkdir -p "$cache/archives-$SUITE-$arch" ; then
+            echo "Failed to create '$cache/archives-$SUITE-$arch' directory"
+            return 1
+        fi
+    fi
+
+    echo "Downloading debian $SUITE $arch..."
+    if ! debootstrap --download-only \
+                     --no-check-gpg \
+                     --arch=$arch \
+                     --include="locales" \
+                     ${SUITE} "$cache/archives-$SUITE-$arch" \
+                     ${MIRROR} ; then
+        echo "ERROR: failed to download to $cache/archives-$SUITE-$arch" 1>&2
+        exit 1
+    fi
+    echo "Download complete."
+    trap EXIT
+    trap SIGINT
+    trap SIGTERM
+    trap SIGHUP
+
+    return 0
+}
+
+copy_debian()
+{
+    cache=$1
+    arch=$2
+    rootfs=$3
+
+    echo -n "Copying rootfs to $rootfs..."
+    mkdir -p $rootfs
+    rsync -Ha "$cache/archives-$SUITE-$arch"/ $rootfs/ || return 1
+    echo "Copy complete."
+    return 0
+}
+
+install_debian()
+{
+    cache="/var/cache/lxc/debian"
+    rootfs="$1"
+    arch="$2"
+
+    mkdir -p /var/lock/subsys/
+    (
+        if ! flock -x 200 ; then
+            echo "Cache repository is busy."
+            return 1
+        fi
+
+        if ! download_debian $cache $arch ; then
+            echo "Failed to download 'debian base'"
+            return 1
+        fi
+
+        if ! copy_debian $cache $arch $rootfs ; then
+            echo "Failed to copy rootfs"
+            return 1
+        fi
+
+        return 0
+
+    ) 200>/var/lock/subsys/lxc-debian
+
+    return $?
+}
+
+create_root() {
+
+    rootfs="$1"
+    hostname="$2"
+    qemu="$3"
+    arch="$4"
+    interpreter_path="$5"
+    include="$6"
+
+    if ! install_debian "$rootfs" "$arch" ; then
+        echo "ERROR: failed to update cache" 1>&2
+        exit 1
+    fi
+
+    if [ "${include}" = "" ] ; then
+      include="locales"
+    else
+      include="locales,${include}"
+    fi
+
+    # Debian bootstrap
+
+    if ! debootstrap --no-check-gpg --foreign \
+                     --arch=$arch \
+                     --include="${include}" \
+                     ${SUITE} "$rootfs" \
+                     ${MIRROR} ; then
+        echo "ERROR: failed to debootstrap to $rootfs" 1>&2
+        exit 1
+    fi
+
+    # adding qemu binary
+
+    if ! cp "$qemu" "$rootfs/$interpreter_path" ; then
+        echo "ERROR: failed to copy $qemu to $rootfs/$interpreter_path" 1>&2
+        exit 1
+    fi
+
+    # debian bootstrap second stage
+
+    chroot "$rootfs" debootstrap/debootstrap --second-stage
+}
+
+configure_debian() {
+
+    rootfs="$1"
+    hostname="$2"
+    debian_sign="$3"
+
+    # set timezone
+
+    cat /etc/timezone > "$rootfs/etc/timezone"
+    chroot $rootfs dpkg-reconfigure -fnoninteractive tzdata
+
+    # configuration
+
+    cat >> "$rootfs/etc/fstab" <<!EOF
+# <file system> <mount point>   <type>  <options>       <dump>  <pass>
+devpts		/dev/pts	devpts	nodev,noexec,nosuid 0	1
+!EOF
+
+    echo "$hostname" > "$rootfs/etc/hostname"
+    echo "c:2345:respawn:/sbin/getty 38400 console" >> "$rootfs/etc/inittab"
+
+    cat >> "$rootfs/etc/network/interfaces" <<!EOF
+auto eth0
+iface eth0 inet dhcp
+!EOF
+
+    cat > "$rootfs/etc/apt/sources.list" <<!EOF
+deb ${MIRROR} ${SUITE} main contrib non-free
+#deb-src ${MIRROR} ${SUITE} main contrib non-free
+!EOF
+
+    if [ "$debian_sign" != "" ]
+    then
+        HOME=/root chroot "$rootfs" gpg --keyserver pgpkeys.mit.edu --recv-key ${debian_sign}
+        HOME=/root chroot "$rootfs" gpg -a --export ${debian_sign} | chroot "$rootfs"  apt-key add -
+    fi
+
+    chroot "$rootfs" apt-get update
+
+    if [ -z "$LANG" ]; then
+        echo "en_US.UTF-8 UTF-8" > "$rootfs/etc/locale.gen"
+        chroot $rootfs locale-gen
+        chroot $rootfs update-locale LANG=en_US.UTF-8
+    else
+        echo "$LANG $(echo $LANG | cut -d. -f2)" > "$rootfs/etc/locale.gen"
+        chroot $rootfs locale-gen
+        chroot $rootfs update-locale LANG=$LANG
+    fi
+
+    # remove pointless services in a container
+
+    if [ -x "$rootfs/usr/sbin/update-rc.d" ] ; then
+        chroot $rootfs /usr/sbin/update-rc.d -f checkroot.sh remove
+        chroot $rootfs /usr/sbin/update-rc.d -f umountfs remove
+        chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh remove
+        chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh remove
+        chroot $rootfs /usr/sbin/update-rc.d -f module-init-tools remove
+    fi
+
+    echo "root:root" | chroot $rootfs chpasswd
+    echo "Root password is 'root', please change !"
+}
+
+get_rootfs() {
+    config="$1/config"
+    rootfs=$(sed -n "s/^lxc.rootfs[[:space:]]*=[[:space:]]*\(.*\)/\1/p" $config)
+    if [ "$rootfs" = "" ]
+    then
+        echo "$path/rootfs"
+    else
+        echo "$rootfs"
+    fi
+}
+
+create_lxc() {
+    path="$1"
+    rootfs="$2"
+    hostname="$3"
+
+    grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> "$path/config"
+    cat >> "$path/config" <<!EOF
+lxc.utsname = $hostname
+
+lxc.pts=1023
+lxc.tty=12
+
+lxc.cgroup.devices.deny = a
+lxc.cgroup.devices.allow = c 136:* rwm # pts
+lxc.cgroup.devices.allow = c 254:0 rwm # rtc
+lxc.cgroup.devices.allow = c 5:* rwm
+lxc.cgroup.devices.allow = c 4:* rwm # ttyXX
+lxc.cgroup.devices.allow = c 1:* rwm
+lxc.cgroup.devices.allow = b 7:* rwm # loop
+lxc.cgroup.devices.allow = b 1:* rwm # ram
+
+lxc.mount.entry=proc proc proc nodev,noexec,nosuid 0 0
+lxc.mount.entry=sysfs sys sysfs defaults  0 0
+
+!EOF
+    if [ $? -ne 0 ] ; then
+        echo "ERROR: failed to create LXC configuration" 1>&2
+        exit 1
+    fi
+}
+
+usage()
+{
+    cat <<!EOF
+Usage: $1 --path PATH --name NAME --arch ARCH --interpreter-path QEMU
+          [--mirror MIRROR][--suite SUITE]
+
+    --path is configuration path
+    --name is container name
+    --arch is debian architecture
+    --interpreter-path is path to the interpreter to copy to rootfs
+    --mirror is URL of debian mirror to use
+    --suite is debian suite to install
+    --include is the list of package to add to debootstrap
+!EOF
+}
+
+options=$(getopt -o hp:n:I:a:s:m:k:i: -l help,path:,name:,interpreter-path:,arch:,suite:,mirror:,deb-sign:,include: -- "$@")
+if [ $? -ne 0 ]; then
+        usage $(basename $0)
+        exit 1
+fi
+eval set -- "$options"
+
+while true ; do
+    case "$1" in
+    -p|--path)
+        shift
+        path="$1"
+        ;;
+    -n|--name)
+        shift
+        name="$1"
+        ;;
+    -a|--arch)
+        shift
+        arch="$1"
+        ;;
+    -I|--interpreter-path)
+        shift
+        qemu="$1"
+        ;;
+    -s|--suite)
+        shift
+        SUITE="$1"
+        ;;
+    -m|--mirror)
+        shift
+        MIRROR="$1"
+        ;;
+    -i|--include)
+        shift
+        include="$1"
+        ;;
+    -k|--deb-sign)
+        shift
+        debian_sign="$1"
+        ;;
+    -h|--help)
+        usage
+        exit 1
+        ;;
+    *)
+        break
+        ;;
+    esac
+    shift
+done
+
+if [ "$path" = "" -o "$name" = "" -o "$arch" = "" -o "$qemu" = "" ] ; then
+    echo "ERROR: missing parameter" 1>&2
+    usage
+    exit 1
+fi
+
+if ! type debootstrap ; then
+    echo "ERROR: 'debootstrap' command is missing" 1>&2
+    exit 1
+fi
+
+if ! file -b "${qemu}" |grep -q "statically linked" ; then
+    echo "ERROR: '${qemu}' must be statically linked" 1>&2
+    exit 1
+fi
+
+interpreter_path=$(find_interpreter "$qemu")
+if [ $? -ne 0 ] ; then
+    echo "ERROR: no binfmt interpreter using $(basename $qemu)" 1>&2
+    exit 1
+fi
+
+rootfs=$(get_rootfs $path)
+
+create_root "$rootfs" "$name" "$qemu" "$arch" "$interpreter_path" "$include"
+
+configure_debian "$rootfs" "$name" "$debian_sign"
+
+create_lxc "$path" "$rootfs" "$name"