Skip to content

Commit

Permalink
feat(xtask): create xtask ci rs subcommand
Browse files Browse the repository at this point in the history
Signed-off-by: Martin Kröning <[email protected]>
  • Loading branch information
mkroening committed Nov 19, 2024
1 parent 66aaaa5 commit 4694432
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 123 deletions.
54 changes: 27 additions & 27 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,58 +210,58 @@ jobs:
if: matrix.arch == 'x86_64'
- run: cargo +stable install cargo-careful
if: matrix.profile == 'dev'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package hello_world
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package hello_world --uefi
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package hello_world qemu ${{ matrix.flags }}
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package hello_world qemu ${{ matrix.flags }} --uefi
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package wasmtime-demo --features ci
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package wasmtime-demo --features ci qemu ${{ matrix.flags }}
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package hello_world --no-default-features --microvm
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package hello_world --no-default-features qemu ${{ matrix.flags }} --microvm
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package rusty_demo --features fs --virtiofsd
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package rusty_demo --features fs qemu ${{ matrix.flags }} --virtiofsd
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package rusty_demo --features fs --virtiofsd --smp 4
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package rusty_demo --features fs qemu ${{ matrix.flags }} --virtiofsd --smp 4
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package rusty_demo --features fs --virtiofsd --no-default-virtio-features
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package rusty_demo --features fs qemu ${{ matrix.flags }} --virtiofsd --no-default-virtio-features
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package rusty_demo --features fs --virtiofsd --no-default-virtio-features --smp 4
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package rusty_demo --features fs qemu ${{ matrix.flags }} --virtiofsd --no-default-virtio-features --smp 4
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package rusty_demo
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package rusty_demo --smp 4
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package rusty_demo qemu ${{ matrix.flags }}
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package rusty_demo qemu ${{ matrix.flags }} --smp 4
# https://github.com/hermit-os/kernel/issues/737
if: matrix.arch != 'aarch64'
# https://github.com/hermit-os/kernel/issues/1286
continue-on-error: ${{ matrix.arch == 'riscv64' }}
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package rusty_demo --smp 4 --uefi
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package rusty_demo qemu ${{ matrix.flags }} --smp 4 --uefi
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package rftrace-example --virtiofsd
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package rftrace-example qemu ${{ matrix.flags }} --virtiofsd
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package httpd --features ci,hermit/dhcpv4 --netdev virtio-net-pci
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package httpd --features ci,hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev virtio-net-pci
if: matrix.arch != 'riscv64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package httpd --features ci,hermit/dhcpv4 --netdev virtio-net-pci --no-default-virtio-features
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package httpd --features ci,hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev virtio-net-pci --no-default-virtio-features
if: matrix.arch != 'riscv64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package httpd --no-default-features --microvm --features ci,hermit/dhcpv4,hermit/tcp --netdev virtio-net-mmio
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package httpd --no-default-features --microvm --features ci,hermit/dhcpv4,hermit/tcp qemu ${{ matrix.flags }} --netdev virtio-net-mmio
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package httpd --features ci,hermit/dhcpv4 --netdev rtl8139 --features hermit/rtl8139
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package httpd --features ci,hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev rtl8139 --features hermit/rtl8139
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package testudp --features hermit/udp,hermit/dhcpv4 --netdev virtio-net-pci
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package testudp --features hermit/udp,hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev virtio-net-pci
if: matrix.arch != 'riscv64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package testudp --features hermit/udp,hermit/dhcpv4 --netdev rtl8139 --features hermit/rtl8139
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package testudp --features hermit/udp,hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev rtl8139 --features hermit/rtl8139
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package miotcp --features hermit/dhcpv4 --netdev virtio-net-pci
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package miotcp --features hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev virtio-net-pci
if: matrix.arch != 'riscv64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package miotcp --features hermit/dhcpv4 --netdev rtl8139 --features hermit/rtl8139
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package miotcp --features hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev rtl8139 --features hermit/rtl8139
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package poll --features hermit/dhcpv4 --netdev virtio-net-pci
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package poll --features hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev virtio-net-pci
if: matrix.arch != 'riscv64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package poll --features hermit/dhcpv4 --netdev rtl8139 --features hermit/rtl8139
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package poll --features hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev rtl8139 --features hermit/rtl8139
if: matrix.arch == 'x86_64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package mioudp --features hermit/udp,hermit/dhcpv4 --netdev virtio-net-pci
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package mioudp --features hermit/udp,hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev virtio-net-pci
if: matrix.arch != 'riscv64'
- run: cargo xtask ci qemu --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} ${{ matrix.flags }} --package mioudp --features hermit/udp,hermit/dhcpv4 --netdev rtl8139 --features hermit/rtl8139
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package mioudp --features hermit/udp,hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev rtl8139 --features hermit/rtl8139
if: matrix.arch == 'x86_64'
- run: UHYVE=$CARGO_HOME/bin/uhyve cargo xtask ci uhyve --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --sudo --package rusty_demo
- run: UHYVE=$CARGO_HOME/bin/uhyve cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --sudo --package rusty_demo uhyve
if: matrix.arch == 'x86_64'
- run: UHYVE=$CARGO_HOME/bin/uhyve cargo xtask ci uhyve --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --sudo --package rusty_demo --smp 4
- run: UHYVE=$CARGO_HOME/bin/uhyve cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --sudo --package rusty_demo uhyve --smp 4
if: matrix.arch == 'x86_64'
- run: FIRECRACKER=$HOME/.local/bin/firecracker cargo xtask ci firecracker --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --sudo --package hello_world --no-default-features
- run: FIRECRACKER=$HOME/.local/bin/firecracker cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --sudo --package hello_world --no-default-features firecracker
if: matrix.arch == 'x86_64'
15 changes: 4 additions & 11 deletions xtask/src/ci/firecracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,23 @@ use anyhow::Result;
use clap::Args;
use xshell::cmd;

use super::build::Build;

/// Run hermit-rs images on Firecracker.
/// Run image on Firecracker.
#[derive(Args)]
pub struct Firecracker {
/// Run Firecracker using `sudo`.
#[arg(long)]
sudo: bool,

#[command(flatten)]
build: Build,
}

impl Firecracker {
pub fn run(mut self) -> Result<()> {
self.build.run()?;

pub fn run(self, image: &Path, smp: usize) -> Result<()> {
let sh = crate::sh()?;

let config = format!(
include_str!("firecracker_vm_config.json"),
kernel_image_path = "hermit-loader-x86_64-fc",
initrd_path = self.build.image().display(),
vcpu_count = self.build.smp,
initrd_path = image.display(),
vcpu_count = smp,
);
eprintln!("firecracker config");
eprintln!("{config}");
Expand Down
12 changes: 3 additions & 9 deletions xtask/src/ci/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,21 @@ use std::path::Path;
use anyhow::Result;
use clap::Subcommand;

mod build;
mod firecracker;
mod qemu;
mod rs;
mod uhyve;

/// Run CI tasks.
#[derive(Subcommand)]
pub enum Ci {
Build(build::Build),
Firecracker(firecracker::Firecracker),
Qemu(qemu::Qemu),
Uhyve(uhyve::Uhyve),
Rs(rs::Rs),
}

impl Ci {
pub fn run(self) -> Result<()> {
match self {
Self::Build(mut build) => build.run(),
Self::Firecracker(firecracker) => firecracker.run(),
Self::Qemu(qemu) => qemu.run(),
Self::Uhyve(uhyve) => uhyve.run(),
Self::Rs(rs) => rs.run(),
}
}
}
Expand Down
81 changes: 34 additions & 47 deletions xtask/src/ci/qemu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ use sysinfo::{CpuRefreshKind, System};
use wait_timeout::ChildExt;
use xshell::cmd;

use super::build::Build;
use crate::arch::Arch;

/// Run hermit-rs images on QEMU.
/// Run image on QEMU.
#[derive(Args)]
pub struct Qemu {
/// Enable hardware acceleration.
Expand Down Expand Up @@ -45,9 +44,6 @@ pub struct Qemu {
/// Enable the `virtiofsd` virtio-fs vhost-user device daemon.
#[arg(long)]
virtiofsd: bool,

#[command(flatten)]
build: Build,
}

#[derive(ValueEnum, Clone, Copy)]
Expand All @@ -58,33 +54,32 @@ pub enum NetworkDevice {
}

impl Qemu {
pub fn run(mut self) -> Result<()> {
self.build.run()?;

pub fn run(self, image: &Path, smp: usize, arch: Arch, profile: &str) -> Result<()> {
let sh = crate::sh()?;

let virtiofsd = self.virtiofsd.then(spawn_virtiofsd).transpose()?;
thread::sleep(Duration::from_millis(100));

if self.build.package.contains("rftrace") {
let image_name = image.file_name().unwrap().to_str().unwrap();
if image_name.contains("rftrace") {
sh.create_dir("shared/tracedir")?;
}

let arch = self.build.cargo_build.artifact.arch.name();
let qemu = env::var("QEMU").unwrap_or_else(|_| format!("qemu-system-{arch}"));
let qemu = env::var("QEMU").unwrap_or_else(|_| format!("qemu-system-{}", arch.name()));
let program = if self.sudo { "sudo" } else { qemu.as_str() };
let arg = self.sudo.then_some(qemu.as_str());
let memory = self.memory(image_name, arch, profile);

let qemu = cmd!(sh, "{program} {arg...}")
.args(&["-display", "none"])
.args(&["-serial", "stdio"])
.args(self.image_args()?)
.args(self.machine_args())
.args(self.cpu_args())
.args(&["-smp", &self.build.smp.to_string()])
.args(self.memory_args())
.args(self.image_args(image, arch)?)
.args(self.machine_args(arch))
.args(self.cpu_args(arch))
.args(&["-smp", &smp.to_string()])
.args(&["-m".to_string(), format!("{memory}M")])
.args(self.netdev_args())
.args(self.virtiofsd_args());
.args(self.virtiofsd_args(memory));

eprintln!("$ {qemu}");
let mut qemu = KillChildOnDrop(
Expand All @@ -96,13 +91,13 @@ impl Qemu {
thread::sleep(Duration::from_millis(100));
if let Some(status) = qemu.0.try_wait()? {
ensure!(
self.qemu_success(status),
self.qemu_success(status, arch),
"QEMU exit code: {:?}",
status.code()
);
}

match self.build.package.as_str() {
match image_name {
"httpd" => test_httpd()?,
"testudp" => test_testudp()?,
"miotcp" => test_miotcp()?,
Expand All @@ -116,7 +111,7 @@ impl Qemu {
bail!("QEMU timeout")
};
ensure!(
self.qemu_success(status),
self.qemu_success(status, arch),
"QEMU exit code: {:?}",
status.code()
);
Expand All @@ -126,23 +121,22 @@ impl Qemu {
assert!(status.success());
}

if self.build.package.contains("rftrace") {
check_rftrace(&self.build.image())?;
if image_name.contains("rftrace") {
check_rftrace(image)?;
}

Ok(())
}

fn image_args(&self) -> Result<Vec<String>> {
let arch = self.build.cargo_build.artifact.arch.name();
fn image_args(&self, image: &Path, arch: Arch) -> Result<Vec<String>> {
let exe_suffix = if self.uefi { ".efi" } else { "" };
let loader = format!("hermit-loader-{arch}{exe_suffix}");
let loader = format!("hermit-loader-{}{exe_suffix}", arch.name());

let image_args = if self.uefi {
let sh = crate::sh()?;
sh.create_dir("target/esp/efi/boot")?;
sh.copy_file(loader, "target/esp/efi/boot/bootx64.efi")?;
sh.copy_file(self.build.image(), "target/esp/efi/boot/hermit-app")?;
sh.copy_file(image, "target/esp/efi/boot/hermit-app")?;

vec![
"-drive".to_string(),
Expand All @@ -156,16 +150,16 @@ impl Qemu {
]
} else {
let mut image_args = vec!["-kernel".to_string(), loader];
match self.build.cargo_build.artifact.arch {
match arch {
Arch::X86_64 | Arch::Riscv64 => {
image_args.push("-initrd".to_string());
image_args.push(self.build.image().into_os_string().into_string().unwrap());
image_args.push(image.to_str().unwrap().to_string());
}
Arch::Aarch64 => {
image_args.push("-device".to_string());
image_args.push(format!(
"guest-loader,addr=0x48000000,initrd={}",
self.build.image().display()
image.display()
));
}
}
Expand All @@ -175,7 +169,7 @@ impl Qemu {
Ok(image_args)
}

fn machine_args(&self) -> Vec<String> {
fn machine_args(&self, arch: Arch) -> Vec<String> {
if self.microvm {
let frequency = get_frequency();
vec![
Expand All @@ -189,9 +183,9 @@ impl Qemu {
"-append".to_string(),
format!("-freq {frequency}"),
]
} else if self.build.cargo_build.artifact.arch == Arch::Aarch64 {
} else if arch == Arch::Aarch64 {
vec!["-machine".to_string(), "virt,gic-version=3".to_string()]
} else if self.build.cargo_build.artifact.arch == Arch::Riscv64 {
} else if arch == Arch::Riscv64 {
vec![
"-machine".to_string(),
"virt".to_string(),
Expand All @@ -203,8 +197,8 @@ impl Qemu {
}
}

fn cpu_args(&self) -> Vec<String> {
match self.build.cargo_build.artifact.arch {
fn cpu_args(&self, arch: Arch) -> Vec<String> {
match arch {
Arch::X86_64 => {
let mut cpu_args = if self.accel {
if cfg!(target_os = "linux") {
Expand Down Expand Up @@ -242,11 +236,9 @@ impl Qemu {
}
}

fn memory(&self) -> usize {
if self.build.cargo_build.artifact.profile() == "release"
&& self.build.package == "hello_world"
{
return match self.build.cargo_build.artifact.arch {
fn memory(&self, image_name: &str, arch: Arch, profile: &str) -> usize {
if profile == "release" && image_name == "hello_world" {
return match arch {
Arch::X86_64 => {
if self.uefi {
64
Expand All @@ -262,10 +254,6 @@ impl Qemu {
1024
}

fn memory_args(&self) -> [String; 2] {
["-m".to_string(), format!("{}M", self.memory())]
}

fn netdev_args(&self) -> Vec<String> {
let Some(netdev) = self.netdev else {
return vec![];
Expand Down Expand Up @@ -297,9 +285,8 @@ impl Qemu {
netdev_args
}

fn virtiofsd_args(&self) -> Vec<String> {
fn virtiofsd_args(&self, memory: usize) -> Vec<String> {
if self.virtiofsd {
let memory = self.memory();
let default_virtio_features = if !self.no_default_virtio_features {
",packed=on"
} else {
Expand All @@ -320,8 +307,8 @@ impl Qemu {
}
}

fn qemu_success(&self, status: ExitStatus) -> bool {
if self.build.cargo_build.artifact.arch == Arch::X86_64 {
fn qemu_success(&self, status: ExitStatus, arch: Arch) -> bool {
if arch == Arch::X86_64 {
status.code() == Some(3)
} else {
status.success()
Expand Down
Loading

0 comments on commit 4694432

Please sign in to comment.