Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CI build/run image for aarch64 oxerun unikernel #12

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .buildkite/smoke-tests.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"tests": [
{
"test_name": "oxerun: run hello world unikernel",
"command": "cd tests && cargo test test_run_aarch64_smoke_test_in_qemu -- --nocapture",
"soft_fail": "true",
"docker_plugin": {
"privileged": true
},
"platform": [
"x86_64"
]
}
]
}
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ exclude = [
"oxerun",
"examples/ioctls",
"examples/xstore",
"tests",
]
165 changes: 165 additions & 0 deletions oxerun/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
FROM debian:bookworm-slim
RUN <<EOF
#!/bin/sh

apt-get update -y
apt-get install -y \
--no-install-suggests \
--no-install-recommends \
ca-certificates \
wget \
qemu-system-arm \
ipxe-qemu \
gcc-aarch64-linux-gnu \
libc6-dev-arm64-cross \
crossbuild-essential-arm64 \
build-essential \
flex \
bison \
ninja-build \
make \
gpg \
gpg-agent \
git \
curl
rm -rf /var/lib/apt/lists/*
EOF

COPY <<EOF [email protected]
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBEu7PVUBCADN/1+JPpAxp3fDk8jZQ3cUKA3W0maOlyI/4+nlDai1gh83m9CN
uGyY5kYLPBIR/sdG2hN5TVxTcE8qPCD9MivJXzOhBAmhQl0eXra0qmBBNu9kv+ZP
qtPORPg2Jch1zZL5jOMawIE0xARZPgu21rPKNJo7V+HejWAHh0/LfFxzzI8LZ1LJ
ACUuHEgfDJEi+u2wxDfjVaTO8HluNXm4TUIr16ExTx+61VDIE9qd3ikXkHgjp8xF
sH0qG5IfcFDTPx9L2Fyk0utTnuNW014P4R31n32U9OolFm1MyOzWrMwVBoTi34aE
nJRT6Aq/WaRfhjIWWkxhWnUgFbPPjMAkWL9fABEBAAG0WFhlbi5vcmcgWGVuIHRy
ZWUgY29kZSBzaWduaW5nIChzaWduYXR1cmVzIG9uIHRoZSB4ZW4gaHlwZXJ2aXNv
ciBhbmQgdG9vbHMpIDxwZ3BAeGVuLm9yZz6JAU0EEwECACAFAku7PVUCGwMGCwkI
BwMCBBUCCAMEFgIDAQIeAQIXgAAhCRCD/hTJV+gr2RYhBCPjIiwUX0R1+oBgp4P+
FMlX6CvZbMsH/jTs0LU/GouRrkjP71eOuEN/j127hYNbeDmTNclIz0PIhs0Ojsa4
hu6nPZkKuLniHBSgSo3MHwYYYzuiqaCFN4JtoRAZPtVpUPsGj/qgXeSgSBv0gKWk
TOIdpqAtlJCvo2QgI2qC68tRDlraLAyX1Ert/HGx8uAJ44a4RorhBmSJuWt0NiEu
LrlWoRJech/G7VO6gC0CLzaxmxwu3HuTfZqCYnnNEUgszAi+KShdZUMZkwffuFpd
6H8+pguFqIaGsXQIWBG1+FVCi9kdiN7Eme8Mxz75nKQnmEsP+d1p9uCzIui24me3
XGXPw9dq7cCDIXZv+iq5Si7zMPm76S74Yyc=
=h6NI
-----END PGP PUBLIC KEY BLOCK-----
EOF

RUN <<EOF
#!/bin/sh

set -ve

gpg --import [email protected]
EOF

RUN <<EOF
#!/bin/sh

set -ve

wget https://downloads.xenproject.org/release/xen/4.18.3/xen-4.18.3.tar.gz
EOF

RUN <<EOF
#!/bin/sh

set -ve

wget https://downloads.xenproject.org/release/xen/4.18.3/xen-4.18.3.tar.gz.sig
gpg --verify xen-4.18.3.tar.gz.sig xen-4.18.3.tar.gz
EOF

RUN <<EOF
#!/bin/sh

set -ve

tar xzf xen-4.18.3.tar.gz
EOF

RUN <<EOF
#!/bin/sh

set -ve

export WORKING_DIR="$(realpath `pwd`)"
echo WORKING_DIR=${WORKING_DIR}
cd ./xen-4.18.3/
export EXTRA_CFLAGS_XEN_CORE=" -Wno-array-bounds "
./configure --build=x86_64-unknown-linux-gnu --host=aarch64-linux-gnu \
--disable-monitors \
--disable-ocamltools \
--disable-tools \
--disable-docs \
--disable-systemd \
--enable-debug
make debug=y debug_symbols=y XEN_TARGET_ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
ls $(pwd)/dist/install/boot/
file $(pwd)/dist/install/boot/*
export XEN_KERNEL=$(realpath dist/install/boot/xen-4.18.3)
echo XEN_KERNEL=${XEN_KERNEL}
cp "${XEN_KERNEL}" "${WORKING_DIR}"/xen-4.18.3-kernel
EOF

#RUN <<EOF
##!/bin/sh

#curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused --location --silent --show-error --fail "https://sh.rustup.rs" | sh -s -- --default-toolchain none -y
#. "${HOME}/.cargo/env"
#rustup toolchain install --profile minimal nightly --target aarch64-linux-none
#EOF

COPY ./target/aarch64-xen-hvm/release/oxerun.bin /oxerun.bin

COPY <<"EOF" /run_qemu_oxerun.sh
#!/bin/sh

QEMU_OUTPUT=${QEMU_OUTPUT:-/qemu_output.stdout}
XEN_KERNEL=${XEN_KERNEL:-/xen-4.18.3-kernel}
DOM0_UNIKERNEL=${DOM0_UNIKERNEL:-/oxerun.bin}

echo QEMU_OUTPUT="${QEMU_OUTPUT}"
echo XEN_KERNEL="${XEN_KERNEL}"
echo DOM0_UNIKERNEL="${DOM0_UNIKERNEL}"

if [ ! -f "${XEN_KERNEL}" ]; then
printf 'XEN_KERNEL value %s does not exist!\n' "${XEN_KERNEL}" 1>&2
fi

if [ ! -f "${DOM0_UNIKERNEL}" ]; then
printf 'DOM0_UNIKERNEL value %s does not exist!\n' "${DOM0_UNIKERNEL}" 1>&2
fi

qemu-system-aarch64 \
-D qemu.log \
-d guest_errors \
-machine virt,virtualization=on,gic-version=3 \
-cpu cortex-a57 \
-chardev file,id=char0,path="${QEMU_OUTPUT}" \
-serial chardev:char0 \
-monitor none \
-display none \
-m 8192 \
-smp 4 \
-kernel "${XEN_KERNEL}" \
-append 'dom0_mem=4G loglvl=none guest_loglvl=none sync_console=true' \
-device guest-loader,addr=0x80000000,kernel="${DOM0_UNIKERNEL}",bootargs='dom0_mem=4G loglvl=none guest_loglvl=none sync_console=true'

cat > /tmp/expected_output <<DOF
Xen 4.18.3
oxerun hello world
DOF

if ! diff -w -u /tmp/expected_output "${QEMU_OUTPUT}"> /dev/null 2>&1; then
diff -w -u /tmp/expected_output "${QEMU_OUTPUT}"
exit 1
fi

exit 0
EOF

CMD ["/bin/sh", "/run_qemu_oxerun.sh"]
9 changes: 9 additions & 0 deletions tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "tests"
authors = ["Manos Pitsidianakis <[email protected]>"]
version = "0.1.0"
edition = "2021"
publish = false
license = "Apache-2.0 OR BSD-3-Clause"

[dependencies]
1 change: 1 addition & 0 deletions tests/LICENSE-APACHE
1 change: 1 addition & 0 deletions tests/LICENSE-BSD-3-Clause
2 changes: 2 additions & 0 deletions tests/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"
1 change: 1 addition & 0 deletions tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
90 changes: 90 additions & 0 deletions tests/tests/oxerun_smoke_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause

use std::{
io::BufRead,
path::Path,
process::{Command, Stdio},
sync::{Arc, Mutex},
thread::sleep,
time::{Duration, Instant},
};

#[test]
fn test_run_aarch64_smoke_test_in_qemu() {
let repo_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../oxerun");
let cargo_bin_path = Path::new(env!("CARGO"));
//cargo build --target aarch64-xen-hvm.json -Zbuild-std=core
// -Zbuild-std-features=compiler-builtins-mem --release

dbg!(Command::new(&cargo_bin_path)
.args([
"build",
"--target",
"./aarch64-xen-hvm.json",
"-Zbuild-std=core",
"-Zbuild-std-features=compiler-builtins-mem",
"--release"
])
.current_dir(&repo_path)
.stdin(Stdio::null())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()
.unwrap());

// aarch64-linux-gnu-objcopy target/aarch64-xen-hvm/release/oxerun -O binary
// target/aarch64-xen-hvm/release/oxerun.bin
dbg!(Command::new("aarch64-linux-gnu-objcopy")
.args([
"./target/aarch64-xen-hvm/release/oxerun",
"-O",
"binary",
"./target/aarch64-xen-hvm/release/oxerun.bin"
])
.current_dir(&repo_path)
.stdin(Stdio::null())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()
.unwrap());

// podman build . | tail -n 1
let output = dbg!(Command::new("podman")
.args(["build", "."])
.current_dir(&repo_path)
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
.output()
.unwrap());
let id = dbg!(output.stdout.lines().last().unwrap().unwrap());

// podman run $img
let mut child = dbg!(Command::new("podman")
.args(["run", &id])
.current_dir(&repo_path)
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap());
// wait 30 secs max
let start = Instant::now();
while Instant::now() - start <= Duration::from_secs(30) {
if child.try_wait().is_ok() {
let output = child.wait_with_output().unwrap();
eprintln!("output:\n{:?}", &output);
eprintln!("{}", String::from_utf8_lossy(&output.stdout));
return;
}
sleep(Duration::from_millis(250));
}
if child.try_wait().is_err() {
if let Err(err) = child.kill() {
eprintln!("Could not wait for podmun run: {}", err);
}
let output = child.wait_with_output().unwrap();
eprintln!("output:\n{:?}", &output);
eprintln!("{}", String::from_utf8_lossy(&output.stdout));
}
}