mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
264 lines
8.5 KiB
Bash
Executable File
264 lines
8.5 KiB
Bash
Executable File
#!/bin/sh
|
||
|
||
# Travis doesn't provide FreeBSD machines, so we just take a Linux one and run
|
||
# FreeBSD in qemu virtual machine. qemu is being ran in curses mode inside a
|
||
# screen session, because screen allows to easily send input and read output.
|
||
# The input is sent using `screen -S session-name -X stuff ...` and the output
|
||
# is read from the screen's log file. Note that for some reason you can't send
|
||
# long input lines on Travis (it works just fine when I do it on my machine...),
|
||
# but that limitation is not an issue, as we don't really need to send long
|
||
# lines of input anyway. Also, note that since we run qemu in curses mode, the
|
||
# output contains control characters intended for a terminal emulator telling
|
||
# how to position and color the text, so it might be a little tricky to read it
|
||
# sometimes. The only time when this script has to send input to and read the
|
||
# output from the screen session is during the initial setup when we setup the
|
||
# network, install and configure the ssh server, and update the system. After
|
||
# this initial setup, ssh is used to communicate with the FreeBSD running in the
|
||
# VM, which is a lot friendlier way of communication. Please note that Travis
|
||
# doesn't seem to allow KVM passthrough, so qemu has to emulate all the
|
||
# hardware, which makes it quite slow compared to the host machine. We cache
|
||
# the qemu image since it takes a long time to run the initial system and
|
||
# package updates, and we do incremental system and package updates on every
|
||
# change to the list of git tags (i.e. on every toxcore release, presumably).
|
||
|
||
sudo apt-get install -y qemu
|
||
|
||
git tag -l --sort=version:refname > GIT_TAGS
|
||
|
||
OLD_PWD="$PWD"
|
||
|
||
mkdir -p /opt/freebsd/cache
|
||
cd /opt/freebsd/cache
|
||
|
||
# Make sure to update DL_SHA512 when bumping the version
|
||
FREEBSD_VERSION="11.1"
|
||
IMAGE_NAME=FreeBSD-${FREEBSD_VERSION}-RELEASE-amd64.raw
|
||
|
||
# Sends keys to the VM as they are
|
||
send_keys()
|
||
{
|
||
screen -S $SCREEN_SESSION -X stuff "$1"
|
||
}
|
||
|
||
# Blocks until a specific text appears on VM's screen
|
||
wait_for()
|
||
{
|
||
while ! grep -q "$1" screenlog.0
|
||
do
|
||
sleep 1
|
||
done
|
||
}
|
||
|
||
# Starts VM and waits until it's fully running (until a login prompt is shown)
|
||
start_vm()
|
||
{
|
||
rm -f screenlog.0
|
||
|
||
# Start emulator. 2000mb RAM should be enough, right? The build machine has over 7gb.
|
||
screen -L -S $SCREEN_SESSION -d -m \
|
||
qemu-system-x86_64 -curses -m 2000 -smp $NPROC \
|
||
-net user,hostfwd=tcp::${SSH_PORT}-:22 -net nic $IMAGE_NAME
|
||
|
||
# Wait for the boot screen options
|
||
wait_for "Autoboot in"
|
||
|
||
# Select the 1st option
|
||
send_keys '
|
||
'
|
||
|
||
# Wait for the system to boot and present the login prompt
|
||
wait_for "FreeBSD/amd64 ("
|
||
}
|
||
|
||
# Shuts VM down and waits until its process finishes
|
||
stop_vm()
|
||
{
|
||
# Turn it off
|
||
RUN poweroff
|
||
|
||
# Wait for qemu process to terminate
|
||
while ps aux | grep qemu | grep -vq grep
|
||
do
|
||
sleep 1
|
||
done
|
||
}
|
||
|
||
# Let's see what's in the cache directory
|
||
ls -lh
|
||
|
||
# === Get the VM running, configured to run ssh server and updated ===
|
||
|
||
# Create image if it's not cached
|
||
if [ ! -f ./$IMAGE_NAME.tgz ]; then
|
||
|
||
rm -rf ./*
|
||
|
||
# https://download.freebsd.org/ftp/releases/VM-IMAGES/11.1-RELEASE/amd64/Latest/
|
||
DL_SHA512="c569776334131fdc85cd25a2a0d5aecafdc3e4b2e6e010dffaa2488d934293ce4f091f23481079dd91ad20dfd2dfc3d3487707096c59448f1d8914c5d7d6b582"
|
||
# Selecting random mirror from https://www.freebsd.org/doc/handbook/mirrors-ftp.html
|
||
# Note that not all mirrors listed on that page are working, so we have removed them
|
||
# I'm so sorry, there are no arrays in sh and we are not using bash...
|
||
DL_MIRROR_1=1
|
||
DL_MIRROR_2=4
|
||
DL_MIRROR_3=5
|
||
DL_MIRROR_4=6
|
||
DL_MIRROR_5=8
|
||
DL_MIRROR_6=10
|
||
DL_MIRROR_7=14
|
||
DL_MIRROR_8=15
|
||
# There are 8 mirrors
|
||
DL_MIRROR_RANDOM=`expr $(date +%s) % 8 + 1`
|
||
DL_URL=ftp://ftp$(eval echo \$DL_MIRROR_$DL_MIRROR_RANDOM).us.freebsd.org/pub/FreeBSD/releases/VM-IMAGES/${FREEBSD_VERSION}-RELEASE/amd64/Latest/${IMAGE_NAME}.xz
|
||
|
||
wget $DL_URL
|
||
|
||
if ! ( echo "$DL_SHA512 $IMAGE_NAME.xz" | sha512sum -c --status - ) ; then
|
||
echo "Error: sha512 of $IMAGE_NAME.xz doesn't match the known one"
|
||
exit 1
|
||
fi
|
||
|
||
unxz $IMAGE_NAME.xz
|
||
|
||
# With this we don't have to guess how long a command will run for and sleeping
|
||
# for that amount of time, risking either under sleeping or over sleeping, instead
|
||
# we will sleep exactly until the command is finished by printing out a unique
|
||
# string after the command is executed and then checking if it was printed.
|
||
execute_shell_and_wait()
|
||
{
|
||
# $RANDOM is a bash built-in, so we try to avoid name collision here by using ugly RANDOM_STR name
|
||
RANDOM_STR=$(< /dev/urandom tr -dc _A-Za-z0-9 | head -c16)
|
||
send_keys "$1;echo $RANDOM_STR
|
||
|
||
"
|
||
# \[1B is a control escape sequence for a new line in the terminal.
|
||
# We want to wait for <new-line>$RANDOM_STR instead of just $RANDOM_STR because
|
||
# $RANDOM_STR we have inputted with send_keys above would appear in the screenlog.0
|
||
# file and we don't want to match our input, we want to match the echo's output.
|
||
# The .\? optionally matches any character. Sometimes it happens that there is some
|
||
# random character inserved between the new line control escape sequence and $RANDOM_STR.
|
||
wait_for "\[1B.\?$RANDOM_STR"
|
||
}
|
||
|
||
start_vm
|
||
|
||
# Login as root user
|
||
send_keys 'root
|
||
|
||
'
|
||
|
||
# Wait for the prompt
|
||
wait_for "root@:~"
|
||
|
||
# Configure network, ssh and start changing password
|
||
execute_shell_and_wait 'echo "ifconfig_em0=DHCP" >> /etc/rc.conf'
|
||
execute_shell_and_wait 'echo "Port 22" >> /etc/ssh/sshd_config'
|
||
execute_shell_and_wait 'echo "PermitRootLogin yes" >> /etc/ssh/sshd_config'
|
||
execute_shell_and_wait 'echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config'
|
||
execute_shell_and_wait 'echo "PermitEmptyPasswords yes" >> /etc/ssh/sshd_config'
|
||
execute_shell_and_wait 'echo "sshd_enable=YES" >> /etc/rc.conf'
|
||
send_keys 'sh /etc/rc.d/netif restart && sh /etc/rc.d/sshd start && passwd
|
||
'
|
||
|
||
# Wait for the password prompt
|
||
wait_for "Changing local password for root"
|
||
|
||
# Reset password to empty for the passwordless ssh to work
|
||
send_keys '
|
||
'
|
||
wait_for "New Password"
|
||
send_keys '
|
||
'
|
||
|
||
# Update system
|
||
RUN env PAGER=cat env ASSUME_ALWAYS_YES=YES freebsd-update --not-running-from-cron fetch
|
||
# It fails if there is nothing to install, so we make it always succeed with true
|
||
RUN env PAGER=cat env ASSUME_ALWAYS_YES=YES freebsd-update --not-running-from-cron install || true
|
||
|
||
# Update packages
|
||
RUN env PAGER=cat env ASSUME_ALWAYS_YES=YES pkg upgrade
|
||
|
||
# Install and set bash as the default shell for the root user
|
||
RUN env PAGER=cat env ASSUME_ALWAYS_YES=YES pkg install bash
|
||
RUN chsh -s /usr/local/bin/bash root
|
||
|
||
# Install required toxcore dependencies
|
||
RUN PAGER=cat ASSUME_ALWAYS_YES=YES pkg install git \
|
||
opus \
|
||
libvpx \
|
||
libsodium \
|
||
gmake \
|
||
cmake \
|
||
pkgconf \
|
||
check \
|
||
opencv \
|
||
portaudio \
|
||
libsndfile \
|
||
texinfo \
|
||
autotools
|
||
|
||
# === Cache the VM image ===
|
||
|
||
stop_vm
|
||
|
||
# Create cache
|
||
tar -Sczvf $IMAGE_NAME.tgz $IMAGE_NAME
|
||
rm screenlog.0
|
||
|
||
cp "$OLD_PWD/GIT_TAGS" .
|
||
|
||
ls -lh
|
||
fi
|
||
|
||
if [ ! -f ./$IMAGE_NAME ]; then
|
||
# Extract the cached image
|
||
tar -Sxzvf $IMAGE_NAME.tgz
|
||
fi
|
||
|
||
# === Update the image on new version (tag) of toxcore ===
|
||
if ! diff -u ./GIT_TAGS "$OLD_PWD/GIT_TAGS" ; then
|
||
start_vm
|
||
|
||
# Update system
|
||
RUN PAGER=cat ASSUME_ALWAYS_YES=YES freebsd-update --not-running-from-cron fetch
|
||
RUN PAGER=cat ASSUME_ALWAYS_YES=YES freebsd-update --not-running-from-cron install || true
|
||
|
||
# Update packages
|
||
RUN PAGER=cat ASSUME_ALWAYS_YES=YES pkg upgrade
|
||
|
||
# === Cache the updated VM image ===
|
||
|
||
stop_vm
|
||
|
||
# Create/Update cache
|
||
rm $IMAGE_NAME.tgz
|
||
tar -Sczvf $IMAGE_NAME.tgz $IMAGE_NAME
|
||
rm screenlog.0
|
||
|
||
cp "$OLD_PWD/GIT_TAGS" .
|
||
|
||
ls -lh
|
||
fi
|
||
|
||
# Get the image we will be using out of the cached directory
|
||
mv $IMAGE_NAME ..
|
||
ls -lh
|
||
|
||
cd ..
|
||
|
||
ls -lh
|
||
|
||
# === Get VM ready to build the code ===
|
||
|
||
start_vm
|
||
|
||
# Display FreeBSD kernel info and last login
|
||
RUN uname -a
|
||
RUN last
|
||
|
||
cd "$OLD_PWD"
|
||
|
||
# Copy over toxcore code from Travis to qemu
|
||
scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -P $SSH_PORT -r ./* root@localhost:~
|
||
|
||
RUN ls -lh
|