139 lines
3.9 KiB
Bash
Executable File
139 lines
3.9 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# make sure this was run as root
|
|
if [ $UID -ne 0 ] ; then
|
|
echo "Need to be root; trying sudo"
|
|
exec sudo env BUILD_CONFIG=$BUILD_CONFIG $0 "$@"
|
|
fi
|
|
. config || exit 0
|
|
|
|
# Spawn a systemd container that boots the machine, then run the given
|
|
# command. We can't execute systemd-nspawn directly, because that
|
|
# only allows us to either boot the machine, or run a command (not
|
|
# both). Instead let's execute systemd-nspawn in a transient systemd
|
|
# unit, then enter it using machinectl.
|
|
|
|
UNIT=nilmbuntu-run-$NONPRIV_UID-$VERSION
|
|
MACH=nilmbuntu-$NONPRIV_UID-$VERSION
|
|
|
|
setup_networking() {
|
|
# We use a virtual ethernet adapter -- this requires that
|
|
# systemd-networkd is installed and running on the host.
|
|
if ! systemctl is-active systemd-networkd ; then
|
|
echo "Starting systemd-networkd"
|
|
systemctl start systemd-networkd
|
|
fi
|
|
|
|
# However, the current systemd-networkd from Debian is broken and
|
|
# won't enable masquerading -- so do it manually
|
|
# IFACE=$(ip -4 route list default | head -1 | awk '{print $5}')
|
|
# echo 1 > /proc/sys/net/ipv4/ip_forward
|
|
# iptables -t nat -D POSTROUTING -o $IFACE -j MASQUERADE >/dev/null || true
|
|
# iptables -t nat -A POSTROUTING -o $IFACE -j MASQUERADE
|
|
}
|
|
|
|
kill_container() {
|
|
# Kill any running container
|
|
if systemctl --quiet is-active $UNIT ; then
|
|
echo "Stopping container..."
|
|
# We could use "machinectl terminate", but that will wait
|
|
# for a clean shutdown or timeout; we don't need a clean
|
|
# shutdown, so send a SIGTERM twice to get systemd-nspawn
|
|
# to terminate pretty quickly
|
|
systemctl kill $UNIT
|
|
sleep 2
|
|
systemctl kill $UNIT
|
|
|
|
# Then wait for it to really stop
|
|
systemctl stop $UNIT
|
|
fi
|
|
|
|
# If systemd-nspawn returned with a failure code,
|
|
# the transient service unit file will stick around,
|
|
# so make sure we clear that.
|
|
if systemctl --quiet is-failed $UNIT ; then
|
|
systemctl reset-failed $UNIT
|
|
fi
|
|
}
|
|
|
|
start_container() {
|
|
kill_container
|
|
echo "Starting container..."
|
|
systemd-run --unit=$UNIT systemd-nspawn \
|
|
--quiet \
|
|
--keep-unit \
|
|
--boot \
|
|
--network-veth \
|
|
--directory $(realpath $FS) \
|
|
--machine $MACH
|
|
echo "Waiting..."
|
|
while ! env SYSTEMD_LOG_LEVEL=0 machinectl shell $MACH /bin/true ; do
|
|
sleep 0.1
|
|
done
|
|
}
|
|
|
|
FAILED=0
|
|
run() {
|
|
# Run a command inside the container
|
|
echo "+" "$1"
|
|
|
|
# machinectl doesn't propagate return codes, so append something
|
|
# to the command that saves the result of what we ran.
|
|
echo "99" > $FS/jim-cmd-result
|
|
CMD="$1 ; echo \$? > /jim-cmd-result"
|
|
|
|
# Run it
|
|
env SYSTEMD_LOG_LEVEL=notice machinectl \
|
|
shell $MACH /usr/bin/env IN_CHROOT=1 \
|
|
bash -c "$CMD"
|
|
|
|
# Check result
|
|
RET=$(cat $FS/jim-cmd-result)
|
|
rm -f $FS/jim-cmd-result
|
|
if [ $RET -ne 0 ] && [ "$1" != "exec bash" ] ; then
|
|
printf "%s\n" "----------- WARNING: failed with exit code $RET"
|
|
FAILED=$RET
|
|
sleep 5
|
|
fi
|
|
}
|
|
|
|
set -e
|
|
|
|
rsync -avP --delete files/ ${FS}/root/files/
|
|
|
|
setup_networking
|
|
start_container
|
|
|
|
run "cat /etc/hosts.nilm >>/etc/hosts 2>/dev/null || true"
|
|
run "hostnamectl --transient set-hostname nilmbuntu"
|
|
|
|
set +e
|
|
if [ -z "$1" ] ; then
|
|
run "exec bash"
|
|
else
|
|
run "$1"
|
|
fi
|
|
|
|
echo "Cleaning up..."
|
|
|
|
# Manually clean up some things that show up after booting an image
|
|
# and installing packages. This doesn't get everything, but what's
|
|
# left should be fine.
|
|
run "apt clean"
|
|
run "dpkg --clear-avail"
|
|
run "> /etc/machine-id"
|
|
run "rm -f /core /boot/grub/grubenv"
|
|
run "rm -f /var/lib/systemd/random-seed"
|
|
run "rm -f /var/lib/ubuntu-drivers-common/last_gfx_boot"
|
|
run "rm -f /var/lib/NetworkManager/*"
|
|
run "rm -f /root/.bash_history"
|
|
run "rm -rf /root/files"
|
|
|
|
kill_container
|
|
|
|
echo "Done"
|
|
if [ $FAILED -ne 0 ] ; then
|
|
exit $FAILED
|
|
fi
|
|
exit 0
|