use std::{env, net::Ipv4Addr, path::PathBuf};
use monocore::{
config::{Group, Service},
runtime::Supervisor,
vm::MicroVm,
MonocoreError, MonocoreResult,
};
use tokio::signal::unix::{signal, SignalKind};
use tracing::{error, info};
#[tokio::main]
pub async fn main() -> MonocoreResult<()> {
let args: Vec<_> = env::args().collect();
if args.len() == 7 && args[1] == "--run-microvm" {
let service: Service = serde_json::from_str(&args[2])?;
let group: Group = serde_json::from_str(&args[3])?;
let local_only: bool = serde_json::from_str(&args[4])?;
let group_ip: Option<Ipv4Addr> = serde_json::from_str(&args[5])?;
let rootfs_path = PathBuf::from(&args[6]);
let env_pairs = service.resolve_environment_variables(&group)?;
let volumes = service.resolve_volumes(&group)?;
let mut builder = MicroVm::builder()
.root_path(rootfs_path)
.num_vcpus(service.get_cpus())
.ram_mib(service.get_ram())
.port_map(service.get_port().cloned().into_iter())
.workdir_path(service.get_workdir().unwrap_or("/"))
.exec_path(service.get_command().unwrap_or("/bin/sh"))
.args(service.get_args().iter().map(|s| s.as_str()))
.env(env_pairs)
.mapped_dirs(volumes)
.local_only(local_only);
if let Some(ip) = group_ip {
builder = builder.assigned_ip(ip);
}
let microvm = builder.build()?;
microvm.start()?;
return Ok(());
}
if args.len() == 6 && args[1] == "--run-supervisor" {
tracing_subscriber::fmt().init();
let service: Service = serde_json::from_str(&args[2])?;
let group: Group = serde_json::from_str(&args[3])?;
let group_ip: Option<Ipv4Addr> = serde_json::from_str(&args[4])?;
let rootfs_path = PathBuf::from(&args[5]);
let mut supervisor = Supervisor::new(service, group, group_ip, rootfs_path).await?;
let mut term_signal = signal(SignalKind::terminate())?;
let supervisor_handle = supervisor.start().await?;
tokio::select! {
result = supervisor_handle => {
match result {
Ok(result) => {
info!("Supervisor exited normally");
result?;
}
Err(e) => {
error!("Supervisor task failed: {}", e);
return Err(MonocoreError::SupervisorError(e.to_string()));
}
}
}
_ = term_signal.recv() => {
info!("Received SIGTERM signal, initiating graceful shutdown");
supervisor.stop().await?;
}
}
return Ok(());
}
Err(MonocoreError::InvalidSupervisorArgs(
"Usage: monokrun --run-supervisor <service_json> <group_json> <group_ip> <rootfs_path>\n monokrun --run-microvm <service_json> <env_json> <local_only> <group_ip> <rootfs_path>".into(),
))
}