mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-27 23:04:15 +00:00
lxc-debian: allow to specify a binfmt interpreter
If you specify an interpreter path with "-I" or "--interpreter-path", the architecture of the debian container can differ from the one of the host. Before creating the container, binfmt must be configured on the host: the script checks the name of the interpreter in /proc/sys/fs/binfmt_misc/ to know where to install it in the container. To create a MIPS container on an x86_64 host: $ cat /proc/sys/fs/binfmt_misc/qemu-mips enabled interpreter //qemu-mips flags: OC offset 0 magic 7f454c4601020100000000000000000000020008 mask ffffffffffffff00fffffffffffffffffffeffff $ sudo lxc-create -n virtmips-stretch -t debian -- \ --arch=mips \ --interpreter-path=./mips-linux-user/qemu-mips \ --mirror=http://ftp.debian.org/debian \ --release=stretch Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
parent
56c80e0d4d
commit
d50cebd697
@ -41,6 +41,29 @@ LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
|
|||||||
# Allows the lxc-cache directory to be set by environment variable
|
# Allows the lxc-cache directory to be set by environment variable
|
||||||
LXC_CACHE_PATH=${LXC_CACHE_PATH:-"$LOCALSTATEDIR/cache/lxc"}
|
LXC_CACHE_PATH=${LXC_CACHE_PATH:-"$LOCALSTATEDIR/cache/lxc"}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
configure_debian()
|
configure_debian()
|
||||||
{
|
{
|
||||||
rootfs=$1
|
rootfs=$1
|
||||||
@ -252,6 +275,8 @@ openssh-server
|
|||||||
cache=$1
|
cache=$1
|
||||||
arch=$2
|
arch=$2
|
||||||
release=$3
|
release=$3
|
||||||
|
interpreter="$4"
|
||||||
|
interpreter_path="$5"
|
||||||
|
|
||||||
trap cleanup EXIT SIGHUP SIGINT SIGTERM
|
trap cleanup EXIT SIGHUP SIGINT SIGTERM
|
||||||
|
|
||||||
@ -285,12 +310,33 @@ openssh-server
|
|||||||
|
|
||||||
# download a mini debian into a cache
|
# download a mini debian into a cache
|
||||||
echo "Downloading debian minimal ..."
|
echo "Downloading debian minimal ..."
|
||||||
debootstrap --verbose --variant=minbase --arch=$arch \
|
if [ "$interpreter" = "" ] ; then
|
||||||
--include=$packages --keyring=${releasekeyring} \
|
debootstrap --verbose --variant=minbase --arch=$arch \
|
||||||
"$release" "$cache/partial-$release-$arch" $MIRROR
|
--include=$packages --keyring=${releasekeyring} \
|
||||||
if [ $? -ne 0 ]; then
|
"$release" "$cache/partial-$release-$arch" $MIRROR
|
||||||
echo "Failed to download the rootfs, aborting."
|
if [ $? -ne 0 ]; then
|
||||||
return 1
|
echo "Failed to download the rootfs, aborting."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debootstrap --foreign --verbose --variant=minbase --arch=$arch \
|
||||||
|
--include=$packages --keyring=${releasekeyring} \
|
||||||
|
"$release" "$cache/partial-$release-$arch" $MIRROR
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Failed to download the rootfs, aborting."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
mkdir -p $(basename "$cache/partial-$release-$arch/$interpreter_path")
|
||||||
|
cp "$interpreter" "$cache/partial-$release-$arch/$interpreter_path"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "failed to copy $interpreter to $cache/partial-$release-$arch/$interpreter_path"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
chroot "$cache/partial-$release-$arch" debootstrap/debootstrap --second-stage
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "failed to update the rootfs, aborting"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mv "$1/partial-$release-$arch" "$1/rootfs-$release-$arch"
|
mv "$1/partial-$release-$arch" "$1/rootfs-$release-$arch"
|
||||||
@ -323,6 +369,8 @@ install_debian()
|
|||||||
release=$2
|
release=$2
|
||||||
arch=$3
|
arch=$3
|
||||||
cache="$4/debian"
|
cache="$4/debian"
|
||||||
|
interpreter="$5"
|
||||||
|
interpreter_path="$6"
|
||||||
mkdir -p $LOCALSTATEDIR/lock/subsys/
|
mkdir -p $LOCALSTATEDIR/lock/subsys/
|
||||||
(
|
(
|
||||||
flock -x 9
|
flock -x 9
|
||||||
@ -333,7 +381,7 @@ install_debian()
|
|||||||
|
|
||||||
echo "Checking cache download in $cache/rootfs-$release-$arch ... "
|
echo "Checking cache download in $cache/rootfs-$release-$arch ... "
|
||||||
if [ ! -e "$cache/rootfs-$release-$arch" ]; then
|
if [ ! -e "$cache/rootfs-$release-$arch" ]; then
|
||||||
download_debian $cache $arch $release
|
download_debian $cache $arch $release "$interpreter" "$interpreter_path"
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Failed to download 'debian base'"
|
echo "Failed to download 'debian base'"
|
||||||
return 1
|
return 1
|
||||||
@ -388,6 +436,7 @@ copy_configuration()
|
|||||||
lxc.tty = $num_tty
|
lxc.tty = $num_tty
|
||||||
lxc.utsname = $hostname
|
lxc.utsname = $hostname
|
||||||
lxc.arch = $arch
|
lxc.arch = $arch
|
||||||
|
lxc.pts=1023
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
@ -404,6 +453,7 @@ post_process()
|
|||||||
local release="$1"; shift
|
local release="$1"; shift
|
||||||
local arch="$1"; shift
|
local arch="$1"; shift
|
||||||
local hostarch="$1"; shift
|
local hostarch="$1"; shift
|
||||||
|
local interpreter="$1"; shift
|
||||||
local packages="$*"
|
local packages="$*"
|
||||||
|
|
||||||
# Disable service startup
|
# Disable service startup
|
||||||
@ -414,7 +464,7 @@ EOF
|
|||||||
chmod +x ${rootfs}/usr/sbin/policy-rc.d
|
chmod +x ${rootfs}/usr/sbin/policy-rc.d
|
||||||
|
|
||||||
# If the container isn't running a native architecture, setup multiarch
|
# If the container isn't running a native architecture, setup multiarch
|
||||||
if [ "${arch}" != "${hostarch}" ]; then
|
if [ "$interpreter" = "" -a "${arch}" != "${hostarch}" ]; then
|
||||||
# Test if dpkg supports multiarch
|
# Test if dpkg supports multiarch
|
||||||
if ! chroot $rootfs dpkg --print-foreign-architecture 2>&1; then
|
if ! chroot $rootfs dpkg --print-foreign-architecture 2>&1; then
|
||||||
chroot $rootfs dpkg --add-architecture ${hostarch}
|
chroot $rootfs dpkg --add-architecture ${hostarch}
|
||||||
@ -423,7 +473,7 @@ EOF
|
|||||||
|
|
||||||
# Write a new sources.list containing both native and multiarch entries
|
# Write a new sources.list containing both native and multiarch entries
|
||||||
> ${rootfs}/etc/apt/sources.list
|
> ${rootfs}/etc/apt/sources.list
|
||||||
if [ "${arch}" = "${hostarch}" ]; then
|
if [ "$interpreter" != "" -a "${arch}" = "${hostarch}" ]; then
|
||||||
write_sourceslist ${rootfs} ${release} ${arch}
|
write_sourceslist ${rootfs} ${release} ${arch}
|
||||||
else
|
else
|
||||||
write_sourceslist ${rootfs} ${release}
|
write_sourceslist ${rootfs} ${release}
|
||||||
@ -492,6 +542,7 @@ Template specific options can be passed to lxc-create after a '--' like this:
|
|||||||
Usage: $1 -h|--help -p|--path=<path> [-c|--clean] [-a|--arch=<arch>] [-r|--release=<release>]
|
Usage: $1 -h|--help -p|--path=<path> [-c|--clean] [-a|--arch=<arch>] [-r|--release=<release>]
|
||||||
[--mirror=<mirror>] [--security-mirror=<security mirror>]
|
[--mirror=<mirror>] [--security-mirror=<security mirror>]
|
||||||
[--package=<package_name1,package_name2,...>]
|
[--package=<package_name1,package_name2,...>]
|
||||||
|
[-I|--interpreter-path=<interpreter path>]
|
||||||
|
|
||||||
Options :
|
Options :
|
||||||
|
|
||||||
@ -510,6 +561,8 @@ Options :
|
|||||||
List of additional packages to install. Comma separated, without space.
|
List of additional packages to install. Comma separated, without space.
|
||||||
-c, --clean only clean up the cache and terminate
|
-c, --clean only clean up the cache and terminate
|
||||||
--enable-non-free include also Debian's contrib and non-free repositories.
|
--enable-non-free include also Debian's contrib and non-free repositories.
|
||||||
|
-I|--interpreter-path=INTERPRETER-PATH
|
||||||
|
Path of the binfmt interpreter to copy to the rootfs
|
||||||
|
|
||||||
Environment variables:
|
Environment variables:
|
||||||
|
|
||||||
@ -522,7 +575,7 @@ EOF
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
options=$(getopt -o hp:n:a:r:c -l arch:,clean,help,enable-non-free,mirror:,name:,packages:,path:,release:,rootfs:,security-mirror: -- "$@")
|
options=$(getopt -o hp:n:a:r:cI: -l arch:,clean,help,enable-non-free,mirror:,name:,packages:,path:,release:,rootfs:,security-mirror:,interpreter-path: -- "$@")
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
usage $(basename $0)
|
usage $(basename $0)
|
||||||
exit 1
|
exit 1
|
||||||
@ -547,6 +600,8 @@ do
|
|||||||
--) shift 1; break ;;
|
--) shift 1; break ;;
|
||||||
|
|
||||||
-a|--arch) arch=$2; shift 2;;
|
-a|--arch) arch=$2; shift 2;;
|
||||||
|
-I|--interpreter-path)
|
||||||
|
interpreter="$2"; shift 2;;
|
||||||
-c|--clean) clean=1; shift 1;;
|
-c|--clean) clean=1; shift 1;;
|
||||||
--enable-non-free) mainonly=0; shift 1;;
|
--enable-non-free) mainonly=0; shift 1;;
|
||||||
--mirror) MIRROR=$2; shift 2;;
|
--mirror) MIRROR=$2; shift 2;;
|
||||||
@ -573,20 +628,32 @@ if [ "$arch" = "x86_64" ]; then
|
|||||||
arch=amd64
|
arch=amd64
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $hostarch = "i386" -a $arch = "amd64" ]; then
|
if [ "$interpreter" = "" ] ; then
|
||||||
echo "can't create $arch container on $hostarch"
|
if [ $hostarch = "i386" -a $arch = "amd64" ]; then
|
||||||
exit 1
|
echo "can't create $arch container on $hostarch"
|
||||||
fi
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $hostarch = "armhf" -o $hostarch = "armel" ] && \
|
if [ $hostarch = "armhf" -o $hostarch = "armel" ] && \
|
||||||
[ $arch != "armhf" -a $arch != "armel" ]; then
|
[ $arch != "armhf" -a $arch != "armel" ]; then
|
||||||
echo "can't create $arch container on $hostarch"
|
echo "can't create $arch container on $hostarch"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $hostarch = "powerpc" -a $arch != "powerpc" ]; then
|
if [ $hostarch = "powerpc" -a $arch != "powerpc" ]; then
|
||||||
echo "can't create $arch container on $hostarch"
|
echo "can't create $arch container on $hostarch"
|
||||||
exit 1
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if ! file -b "${interpreter}" |grep -q "statically linked" ; then
|
||||||
|
echo "'${interpreter}' must be statically linked" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
interpreter_path=$(find_interpreter "$interpreter")
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
echo "no binfmt interpreter using $(basename $interpreter)" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
type debootstrap
|
type debootstrap
|
||||||
@ -630,7 +697,7 @@ else
|
|||||||
num_tty=4
|
num_tty=4
|
||||||
fi
|
fi
|
||||||
|
|
||||||
install_debian $rootfs $release $arch $LXC_CACHE_PATH
|
install_debian $rootfs $release $arch $LXC_CACHE_PATH "$interpreter" "$interpreter_path"
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "failed to install debian"
|
echo "failed to install debian"
|
||||||
exit 1
|
exit 1
|
||||||
@ -650,7 +717,7 @@ fi
|
|||||||
|
|
||||||
configure_debian_systemd $path $rootfs $config $num_tty
|
configure_debian_systemd $path $rootfs $config $num_tty
|
||||||
|
|
||||||
post_process ${rootfs} ${release} ${arch} ${hostarch} ${packages}
|
post_process ${rootfs} ${release} ${arch} ${hostarch} "${interpreter}" ${packages}
|
||||||
|
|
||||||
if [ ! -z "$clean" ]; then
|
if [ ! -z "$clean" ]; then
|
||||||
clean || exit 1
|
clean || exit 1
|
||||||
|
Loading…
Reference in New Issue
Block a user