-
-
Save tpokorra/8bc85d2963ddc219ba0a to your computer and use it in GitHub Desktop.
#!/bin/bash | |
# | |
# lxc: linux Container library | |
# Authors: | |
# Original Debian: | |
# Daniel Lezcano <[email protected]> | |
# Changes for Raspberry Pi by: | |
# Oliver Heller <[email protected]> | |
# This library is free software; you can redistribute it and/or | |
# modify it under the terms of the GNU Lesser General Public | |
# License as published by the Free Software Foundation; either | |
# version 2.1 of the License, or (at your option) any later version. | |
# This library 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 | |
# Lesser General Public License for more details. | |
# You should have received a copy of the GNU Lesser General Public | |
# License along with this library; if not, write to the Free Software | |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
SUITE=${SUITE:-jessie} | |
MIRROR=${MIRROR:-http://archive.raspbian.org/raspbian} | |
configure_debian() | |
{ | |
rootfs=$1 | |
hostname=$2 | |
# squeeze only has /dev/tty and /dev/tty0 by default, | |
# therefore creating missing device nodes for tty1-4. | |
for tty in $(seq 1 4); do | |
if [ ! -e $rootfs/dev/tty$tty ]; then | |
mknod $rootfs/dev/tty$tty c 4 $tty | |
fi | |
done | |
# configure the inittab | |
cat <<EOF > $rootfs/etc/inittab | |
id:2:initdefault: | |
si::sysinit:/etc/init.d/rcS | |
l0:0:wait:/etc/init.d/rc 0 | |
l1:1:wait:/etc/init.d/rc 1 | |
l2:2:wait:/etc/init.d/rc 2 | |
l3:3:wait:/etc/init.d/rc 3 | |
l4:4:wait:/etc/init.d/rc 4 | |
l5:5:wait:/etc/init.d/rc 5 | |
l6:6:wait:/etc/init.d/rc 6 | |
# Normally not reached, but fallthrough in case of emergency. | |
z6:6:respawn:/sbin/sulogin | |
1:2345:respawn:/sbin/getty 38400 console | |
c1:12345:respawn:/sbin/getty 38400 tty1 linux | |
c2:12345:respawn:/sbin/getty 38400 tty2 linux | |
c3:12345:respawn:/sbin/getty 38400 tty3 linux | |
c4:12345:respawn:/sbin/getty 38400 tty4 linux | |
EOF | |
# disable selinux in debian | |
mkdir -p $rootfs/selinux | |
echo 0 > $rootfs/selinux/enforce | |
# configure the network using the dhcp | |
cat <<EOF > $rootfs/etc/network/interfaces | |
auto lo | |
iface lo inet loopback | |
auto eth0 | |
iface eth0 inet dhcp | |
EOF | |
# set the hostname | |
cat <<EOF > $rootfs/etc/hostname | |
$hostname | |
EOF | |
# reconfigure some services | |
LANG="${LANG:-en_US.UTF-8}" | |
locale="$LANG $(echo $LANG | cut -d. -f2)" | |
chroot $rootfs echo "locales locales/default_environment_locale select $LANG" | chroot $rootfs sh -c "LANG=C debconf-set-selections" | |
chroot $rootfs echo "locales locales/default_environment_locale seen true" | chroot $rootfs sh -c "LANG=C debconf-set-selections" | |
chroot $rootfs echo "locales locales/locales_to_be_generated seen true" | chroot $rootfs sh -c "LANG=C debconf-set-selections" | |
chroot $rootfs sed -i -e "0,/^[# ]*$locale *$/ s/^[# ]*$locale *$/$locale/" /etc/locale.gen | |
chroot $rootfs sh -c "LANG=C dpkg-reconfigure locales -f noninteractive" | |
# remove pointless services in a container | |
chroot $rootfs /usr/sbin/update-rc.d -f checkroot.sh remove # S | |
chroot $rootfs /usr/sbin/update-rc.d checkroot.sh stop 09 S . | |
chroot $rootfs /usr/sbin/update-rc.d -f umountfs remove # 0 6 | |
chroot $rootfs /usr/sbin/update-rc.d umountfs start 09 0 6 . | |
chroot $rootfs /usr/sbin/update-rc.d -f umountroot remove # 0 6 | |
chroot $rootfs /usr/sbin/update-rc.d umountroot start 10 0 6 . | |
# The following initscripts don't provide an empty start or stop block. | |
# To prevent them being enabled on upgrades, we leave a start link on | |
# runlevel 3. | |
chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh remove # S 0 6 | |
chroot $rootfs /usr/sbin/update-rc.d hwclock.sh start 10 3 . | |
chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh remove # S | |
chroot $rootfs /usr/sbin/update-rc.d hwclockfirst start 08 3 . | |
chroot $rootfs /usr/sbin/update-rc.d -f module-init-tools remove # S | |
chroot $rootfs /usr/sbin/update-rc.d module-init-tools start 10 3 . | |
echo "root:root" | chroot $rootfs chpasswd | |
echo "Root password is 'root', please change !" | |
return 0 | |
} | |
cleanup() | |
{ | |
rm -rf $cache/partial-$SUITE-$arch | |
rm -rf $cache/rootfs-$SUITE-$arch | |
} | |
download_debian() | |
{ | |
packages=\ | |
ifupdown,\ | |
locales,\ | |
libui-dialog-perl,\ | |
dialog,\ | |
isc-dhcp-client,\ | |
netbase,\ | |
net-tools,\ | |
iproute,\ | |
openssh-server | |
cache=$1 | |
arch=$2 | |
trap cleanup EXIT SIGHUP SIGINT SIGTERM | |
# check the mini debian was not already downloaded | |
mkdir -p "$cache/partial-$SUITE-$arch" | |
if [ $? -ne 0 ]; then | |
echo "Failed to create '$cache/partial-$SUITE-$arch' directory" | |
return 1 | |
fi | |
# download a mini debian into a cache | |
echo "Downloading debian minimal ..." | |
qemu-debootstrap --verbose --variant=minbase --arch=$arch \ | |
--include=$packages \ | |
"$SUITE" "$cache/partial-$SUITE-$arch" $MIRROR | |
if [ $? -ne 0 ]; then | |
echo "Failed to download the rootfs, aborting." | |
return 1 | |
fi | |
mv "$1/partial-$SUITE-$arch" "$1/rootfs-$SUITE-$arch" | |
echo "Download complete." | |
trap EXIT | |
trap SIGINT | |
trap SIGTERM | |
trap SIGHUP | |
return 0 | |
} | |
copy_debian() | |
{ | |
cache=$1 | |
arch=$2 | |
rootfs=$3 | |
# make a local copy of the minidebian | |
echo -n "Copying rootfs to $rootfs..." | |
mkdir -p $rootfs | |
rsync -a "$cache/rootfs-$SUITE-$arch"/ $rootfs/ || return 1 | |
return 0 | |
} | |
install_debian() | |
{ | |
cache="/var/cache/lxc/pi" | |
rootfs=$1 | |
mkdir -p /var/lock/subsys/ | |
( | |
flock -x 200 | |
if [ $? -ne 0 ]; then | |
echo "Cache repository is busy." | |
return 1 | |
fi | |
arch="armhf" | |
echo "Checking cache download in $cache/rootfs-$SUITE-$arch ... " | |
if [ ! -e "$cache/rootfs-$SUITE-$arch" ]; then | |
download_debian $cache $arch | |
if [ $? -ne 0 ]; then | |
echo "Failed to download 'debian base'" | |
return 1 | |
fi | |
fi | |
copy_debian $cache $arch $rootfs | |
if [ $? -ne 0 ]; then | |
echo "Failed to copy rootfs" | |
return 1 | |
fi | |
return 0 | |
) 200>/var/lock/subsys/lxc | |
return $? | |
} | |
copy_configuration() | |
{ | |
path=$1 | |
rootfs=$2 | |
name=$3 | |
cat >> $path/config << EOF | |
# $path/config | |
## Container | |
lxc.utsname = $name | |
lxc.rootfs = $rootfs | |
lxc.tty = 4 | |
lxc.pts = 1024 | |
#lxc.console = /var/log/lxc/$name.console | |
## Capabilities | |
lxc.cap.drop = sys_admin | |
# uncomment the next line to run the container unconfined: | |
#lxc.aa_profile = unconfined | |
## Devices | |
#lxc.cgroup.devices.allow = a | |
lxc.cgroup.devices.deny = a | |
# /dev/null | |
lxc.cgroup.devices.allow = c 1:3 rwm | |
# /dev/zero | |
lxc.cgroup.devices.allow = c 1:5 rwm | |
# /dev/tty[1-4] consoles | |
lxc.cgroup.devices.allow = c 5:1 rwm | |
lxc.cgroup.devices.allow = c 5:0 rwm | |
lxc.cgroup.devices.allow = c 4:0 rwm | |
lxc.cgroup.devices.allow = c 4:1 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 | |
# /dev/rtc | |
lxc.cgroup.devices.allow = c 254:0 rwm | |
## Limits | |
#lxc.cgroup.cpu.shares = 1024 | |
#lxc.cgroup.cpuset.cpus = 0 | |
#lxc.cgroup.memory.limit_in_bytes = 256M | |
#lxc.cgroup.memory.memsw.limit_in_bytes = 1G | |
## Filesystem | |
lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 | |
lxc.mount.entry = sysfs sys sysfs defaults,ro 0 0 | |
#lxc.mount.entry = /srv/$name srv/$name none defaults,bind 0 0 | |
EOF | |
if [ $? -ne 0 ]; then | |
echo "Failed to add configuration" | |
return 1 | |
fi | |
return 0 | |
} | |
clean() | |
{ | |
cache="/var/cache/lxc/pi" | |
if [ ! -e $cache ]; then | |
exit 0 | |
fi | |
# lock, so we won't purge while someone is creating a repository | |
( | |
flock -x 200 | |
if [ $? != 0 ]; then | |
echo "Cache repository is busy." | |
exit 1 | |
fi | |
echo -n "Purging the download cache..." | |
rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 | |
exit 0 | |
) 200>/var/lock/subsys/lxc | |
} | |
usage() | |
{ | |
cat <<EOF | |
$1 -h|--help -p|--rootpath=<path> --clean | |
EOF | |
return 0 | |
} | |
options=$(getopt -o hp:n:c -l help,path:,rootfs:,name:,clean -- "$@") | |
if [ $? -ne 0 ]; then | |
usage $(basename $0) | |
exit 1 | |
fi | |
eval set -- "$options" | |
while true | |
do | |
case "$1" in | |
-h|--help) usage $0 && exit 0;; | |
-p|--path) path=$2; shift 2;; | |
--rootfs) rootfs=$2; shift 2;; | |
-n|--name) name=$2; shift 2;; | |
-c|--clean) clean=$2; shift 2;; | |
--) shift 1; break ;; | |
*) break ;; | |
esac | |
done | |
if [ ! -z "$clean" -a -z "$path" ]; then | |
clean || exit 1 | |
exit 0 | |
fi | |
type qemu-debootstrap | |
if [ $? -ne 0 ]; then | |
echo "'qemu-debootstrap' command is missing" | |
exit 1 | |
fi | |
if [ -z "$path" ]; then | |
echo "'path' parameter is required" | |
exit 1 | |
fi | |
if [ "$(id -u)" != "0" ]; then | |
echo "This script should be run as 'root'" | |
exit 1 | |
fi | |
#rootfs=$path/rootfs | |
install_debian $rootfs | |
if [ $? -ne 0 ]; then | |
echo "failed to install debian" | |
exit 1 | |
fi | |
configure_debian $rootfs $name | |
if [ $? -ne 0 ]; then | |
echo "failed to configure debian for a container" | |
exit 1 | |
fi | |
copy_configuration $path $rootfs $name | |
if [ $? -ne 0 ]; then | |
echo "failed write configuration file" | |
exit 1 | |
fi | |
if [ ! -z $clean ]; then | |
clean || exit 1 | |
exit 0 | |
fi |
trying the config file from Debian Jessie:
# Distribution configuration
lxc.include = /usr/share/lxc/config/debian.common.conf
# Container specific configuration
lxc.utsname = raspberry-jessie
lxc.rootfs = /var/lib/lxc/raspberry-jessie/rootfs
# Network configuration
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = lxcbr0
lxc.network.hwaddr = 00:16:3e:bd:05:d2
lxc.network.ipv4=10.0.3.50/24
lxc.network.ipv4.gateway=10.0.3.1
lxc.aa_profile = unconfined
lxc.kmsg = 0
lxc.autodev = 1
lxc.cap.drop = mknod
shows error:
systemd 215 running in system mode. (+PAM +AUDIT +SELINUX +IMA +SYSVINIT +LIBCRYPTSETUP +GCRYPT +ACL +XZ -SECCOMP -APPARMOR)
Detected virtualization 'lxc'.
Detected architecture 'arm'.
Welcome to Raspbian GNU/Linux 8 (jessie)!
Set hostname to <raspberry-jessie>.
Unsupported ioctl: cmd=0x8933
qemu: Unsupported syscall: 355
Failed to allocate manager object: Function not implemented
original script from https://d24m.de/opensource/2013/07/19/raspbian-unter-lxc.html
goes to /usr/share/lxc/templates/lxc-pi
sudo apt-get install qemu-user-static
sudo lxc-create -t pi -n raspberry-container
on Fedora (qemu 2.3.1 in F22, https://apps.fedoraproject.org/packages/qemu):
sudo dnf install qemu
replace qemu-debootstrap with debootstrap in /usr/share/lxc/templates/lxc-pi
lxc-create -t pi -n raspberry-container
I get this error:
W: Failure trying to run: chroot /var/cache/lxc/pi/partial-jessie-armhf mount -t proc proc /proc
W: See /var/cache/lxc/pi/partial-jessie-armhf/debootstrap/debootstrap.log for details
Failed to download the rootfs, aborting.
Failed to download 'debian base'
failed to install debian
lxc-create: lxccontainer.c: create_run_template: 1201 container creation template for raspberry-container failed
lxc-create: lxc_create.c: main: 274 Error creating container raspberry-container
see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=770658, setting Path in lxc-pi before debootstrap call
PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
That does not seem to help.
Running the script directly:
/usr/share/lxc/templates/lxc-pi -p /var/cache/lxc/pi/test
I hope I could still find the debootstrap log file.
or even more directly:
debootstrap --verbose --variant=minbase --arch=armhf --include=ifupdown,locales,libui-dialog-perl,dialog,isc-dhcp-client,netbase,net-tools,iproute,openssh-server jessie /var/cache/lxc/pi/partial-jessie-armhf http://archive.raspbian.org/raspbian
Shows error:
W: Failure trying to run: chroot /var/cache/lxc/pi/partial-jessie-armhf mount -t proc proc /proc
W: See /var/cache/lxc/pi/partial-jessie-armhf/debootstrap/debootstrap.log for details
Detail in debootstrap.log:
chroot: failed to run command 'mount': No such file or directory
This happens when the arch is different. The /bin/mount works on ARM, but not on my 64 bit. So I need qemu-debootstrap, but I cannot find where to get that on Fedora...
see this: https://wiki.ubuntu.com/ARM/RootfsFromScratch/QemuDebootstrap
splitting into two parts:
rootfs=/var/cache/lxc/pi/partial-jessie-armhf
debootstrap --verbose --foreign --variant=minbase --arch=armhf --include=ifupdown,locales,libui-dialog-perl,dialog,isc-dhcp-client,netbase,net-tools,iproute,openssh-server jessie $rootfs http://archive.raspbian.org/raspbian
cp /usr/bin/qemu-arm $rootfs/usr/bin
sudo chroot $rootfs /bin/bash
that also does not work...
see https://wiki.debian.org/QemuUserEmulation and https://lists.fedoraproject.org/pipermail/arm/2014-January/007307.html
see https://copr.fedorainfracloud.org/coprs/bboozzoo/qemu-arm-static/ I have rebuilt that package for my Fedora 22, and installed it. see https://copr.fedorainfracloud.org/coprs/tpokorra/qemu-arm-static/
qemu-binfmt-conf.sh
chroot $rootfs /bin/bash
/debootstrap/debootstrap --second-stage
now works...
For Jessie see debops/ansible-lxc#15
Adding to the end of the config file of the container:
Currently that still does not start for me