[lxc-devel] [PATCH] Add lxc-cross-debian to create debian containers for non native architectures.
Laurent Vivier
Laurent at Vivier.EU
Thu Dec 26 10:17:25 UTC 2013
Le 26/12/2013 00:12, Laurent Vivier a écrit :
> Le 25/12/2013 21:47, Stéphane Graber a écrit :
>> On Wed, Dec 25, 2013 at 09:38:57PM +0100, Laurent Vivier wrote:
>>> These containers will use the binfmt kernel module and
>>> an interpreter to execute binaries inside the container.
>>>
>>> To use it :
>>> 1- configure correctly binfmt on your system to load the
>>> interpreter.
>>> 2- provide the path to the interpreter to the lxc template.
>>> The interpreter must be statically linked.
>>> 3- provide the architecture to install (armhf, mips, m68k, sparc, ...)
>>> 4- provide the suite to install (stable, lenny, etch, ...)
>>>
>>> For instance, if you want to use qemu as an interpreter, check this:
>>>
>>> If you want to create an m68k containers on your x86_64 system,
>>> you can use a script to do all the work :
>>>
>>> git clone git at gitorious.org:qemu-m68k/qemu-m68k.git
>>> cd qemu-m68k
>>> scripts/debian-create-lxc.sh m68k
>>>
>>> You can change "m68k", but m68k is the one really tested...
>>> [TIPS: want to create a raspberry-pi container ?
>>> scripts/debian-create-lxc.sh raspberrypi ]
>>>
>> Why not do it the same way we do in lxc-ubuntu?
>>
>> In lxc-ubuntu, foreign architecture containers are completely
>> transparent, basically if qemu-debootstrap is on the system, it'll be
>> called automatically and then some tweaks are done to setup multi-arch
>> post-install and install the few bits that don't work properly under
>> qemu-user-static (netlink mostly).
> Because my goal is to have a real install I can use on the real
> machine. I don't want to put inconsistent binaries in it.
> Moreover, I'm before all a qemu developer, so I prefer to correct qemu
> instead of using some tweaks to use qemu with linux containers.
OK, I think I missed the point. What you want is I merge lxc-debian and
my lxc-cross-debian to manage the both cases in the same script. I
didn't do that because I don't want to break the original script, but if
you think it is better, I can try...
>
>> I personaly would much rather the feature be added to lxc-debian than
>> have another template for that which would mostly create some extra
>> confusion (I already don't like the two Ubuntu templates for that reason
>> though those are at least entirely different in the way they work and so
>> vaguely make sense).
>>
>>> Signed-off-by: Laurent Vivier <laurent at vivier.eu>
>>> ---
>>> configure.ac | 1 +
>>> templates/Makefile.am | 3 +-
>>> templates/lxc-cross-debian.in | 360
>>> ++++++++++++++++++++++++++++++++++++++++++
>>> 3 files changed, 363 insertions(+), 1 deletion(-)
>>> create mode 100755 templates/lxc-cross-debian.in
>>>
>>> diff --git a/configure.ac b/configure.ac
>>> index 4c5f002..feb1771 100644
>>> --- a/configure.ac
>>> +++ b/configure.ac
>>> @@ -583,6 +583,7 @@ AC_CONFIG_FILES([
>>> templates/lxc-archlinux
>>> templates/lxc-alpine
>>> templates/lxc-plamo
>>> + templates/lxc-cross-debian
>>> src/Makefile
>>> src/lxc/Makefile
>>> diff --git a/templates/Makefile.am b/templates/Makefile.am
>>> index abdca6f..33939b4 100644
>>> --- a/templates/Makefile.am
>>> +++ b/templates/Makefile.am
>>> @@ -15,4 +15,5 @@ templates_SCRIPTS = \
>>> lxc-archlinux \
>>> lxc-alpine \
>>> lxc-cirros \
>>> - lxc-plamo
>>> + lxc-plamo \
>>> + lxc-cross-debian
>>> diff --git a/templates/lxc-cross-debian.in
>>> b/templates/lxc-cross-debian.in
>>> new file mode 100755
>>> index 0000000..a12caa1
>>> --- /dev/null
>>> +++ b/templates/lxc-cross-debian.in
>>> @@ -0,0 +1,360 @@
>>> +#!/bin/bash
>>> +#
>>> +# Some parts from lxc-debian, Daniel Lezcano <daniel.lezcano at 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() {
>>> + given_interpreter=$(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 [ "$given_interpreter" = "$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="@LOCALSTATEDIR@/cache/lxc/debian"
>>> + rootfs="$1"
>>> + arch="$2"
>>> +
>>> + mkdir -p @LOCALSTATEDIR@/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>@LOCALSTATEDIR@/lock/subsys/lxc-cross-debian
>>> +
>>> + return $?
>>> +}
>>> +
>>> +create_root() {
>>> +
>>> + rootfs="$1"
>>> + hostname="$2"
>>> + interpreter="$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 interpreter binary
>>> +
>>> + if ! cp "$interpreter" "$rootfs/$interpreter_path" ; then
>>> + echo "ERROR: failed to copy $interpreter 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,rootfs:,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"
>>> + ;;
>>> + --rootfs)
>>> + shift
>>> + rootfs="$1"
>>> + ;;
>>> + -n|--name)
>>> + shift
>>> + name="$1"
>>> + ;;
>>> + -a|--arch)
>>> + shift
>>> + arch="$1"
>>> + ;;
>>> + -I|--interpreter-path)
>>> + shift
>>> + interpreter="$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 "$interpreter"
>>> = "" ] ; 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 "${interpreter}" |grep -q "statically linked" ; then
>>> + echo "ERROR: '${interpreter}' must be statically linked" 1>&2
>>> + exit 1
>>> +fi
>>> +
>>> +interpreter_path=$(find_interpreter "$interpreter")
>>> +if [ $? -ne 0 ] ; then
>>> + echo "ERROR: no binfmt interpreter using $(basename
>>> $interpreter)" 1>&2
>>> + exit 1
>>> +fi
>>> +
>>> +if [ "$rootfs" = "" ] ; then
>>> + rootfs=$(get_rootfs $path)
>>> +fi
>>> +
>>> +create_root "$rootfs" "$name" "$interpreter" "$arch"
>>> "$interpreter_path" "$include"
>>> +
>>> +configure_debian "$rootfs" "$name" "$debian_sign"
>>> +
>>> +create_lxc "$path" "$rootfs" "$name"
>>> --
>>> 1.8.3.2
>>>
>>> _______________________________________________
>>> lxc-devel mailing list
>>> lxc-devel at lists.linuxcontainers.org
>>> http://lists.linuxcontainers.org/listinfo/lxc-devel
>
More information about the lxc-devel
mailing list