use anyhow::Result;
use clap::Parser;
use monocore::{
utils,
vm::{LogLevel, MicroVm},
};
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
#[arg(short, long)]
server: bool,
#[arg(short, long, default_value = "127.0.0.1")]
ip: String,
}
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt::init();
let args = Args::parse();
let build_dir = format!("{}/build", env!("CARGO_MANIFEST_DIR"));
let oci_dir = format!("{}/oci", build_dir);
let image_ref = "library/alpine:latest";
let (_, _, rootfs_name) = utils::parse_image_ref(image_ref).unwrap();
let rootfs_dir = format!("{}/rootfs/reference/{}", build_dir, rootfs_name);
utils::pull_docker_image(&oci_dir, image_ref).await?;
utils::merge_image_layers(&oci_dir, &rootfs_dir, image_ref).await?;
let vm = if args.server {
tracing::info!("Server mode: Listening on {}:3456 (UDP)...", args.ip);
MicroVm::builder()
.log_level(LogLevel::Info)
.root_path(format!("{}/merged", rootfs_dir))
.port_map(["3456:3456".parse()?])
.exec_path("/bin/busybox")
.args([
"timeout",
"10",
"busybox",
"nc",
"-u", "-l", "-v", "-p", "3456", "-e", "echo", "Hello from UDP server!", ])
.assigned_ip(args.ip.parse()?)
.ram_mib(512)
.build()?
} else {
tracing::info!("Client mode: Connecting to {}:3456 (UDP)...", args.ip);
MicroVm::builder()
.log_level(LogLevel::Info)
.root_path(format!("{}/merged", rootfs_dir))
.exec_path("/bin/busybox")
.args([
"nc", "-u", "-w", "1", "127.0.0.1", "3456", ])
.assigned_ip(args.ip.parse()?)
.ram_mib(512)
.build()?
};
tracing::info!("Starting MicroVm...");
vm.start()?;
Ok(())
}