use anyhow::{Context, Result};
use arcbox_connect::v1 as pb;
use arcbox_connect::v1::SystemServiceClient;
use arcbox_connect::v1::SystemVmBackend;
use clap::{Subcommand, ValueEnum};
use crate::connect;
#[derive(Debug, Subcommand)]
pub enum SystemCommands {
Backend {
#[arg(value_enum)]
set: Option<BackendArg>,
},
}
#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum BackendArg {
Hv,
Vz,
}
impl From<BackendArg> for SystemVmBackend {
fn from(arg: BackendArg) -> Self {
match arg {
BackendArg::Hv => Self::Hv,
BackendArg::Vz => Self::Vz,
}
}
}
fn label(backend: SystemVmBackend) -> &'static str {
match backend {
SystemVmBackend::Hv => "hv (Hypervisor.framework + FEX)",
SystemVmBackend::Vz => "vz (Virtualization.framework)",
SystemVmBackend::Unspecified => "unspecified",
}
}
fn system_client() -> SystemServiceClient<connectrpc::client::SharedHttp2Connection> {
let (transport, config) = connect::daemon(&super::resolve_grpc_socket_path());
SystemServiceClient::new(transport, config)
}
pub async fn execute(cmd: SystemCommands) -> Result<()> {
match cmd {
SystemCommands::Backend { set } => {
let client = system_client();
let info: pb::SystemVmBackendInfo = if let Some(arg) = set {
let backend = SystemVmBackend::from(arg);
println!(
"Switching System VM backend to {} — restarting the System VM...",
label(backend)
);
client
.set_system_vm_backend(pb::SetSystemVmBackendRequest {
backend: backend.into(),
..Default::default()
})
.await
.context("failed to switch System VM backend")?
.into_owned()
} else {
client
.get_system_vm_backend(pb::Empty::default())
.await
.context("failed to query System VM backend")?
.into_owned()
};
let current = info.backend.as_known().unwrap_or_default();
println!("System VM backend: {}", label(current));
Ok(())
}
}
}