photoncloud-monorepo/plasmavmc/crates/plasmavmc-server/src/main.rs
centra df80d00696 feat(T027): Unify configuration for flaredb-server and plasmavmc-server
Refactored flaredb-server and plasmavmc-server to use a unified configuration
approach, supporting TOML files, environment variables, and CLI overrides.

This completes T027.S0 Config Unification.

Changes include:
- Created dedicated  modules for both flaredb-server and plasmavmc-server
  to define  structs.
- Implemented  for  in both components.
- Modified  in flaredb-server to use  instead of .
- Modified  in plasmavmc-server to add  dependency.
- Refactored  in both components to load config from TOML/env and apply
  CLI overrides.
- Extended  in plasmavmc-server/src/config.rs to include all
  relevant Firecracker backend parameters.
- Implemented  in
  plasmavmc/crates/plasmavmc-firecracker/src/lib.rs to construct backend
  from the unified configuration.
- Updated docs/por/T027-production-hardening/task.yaml to mark S0 as complete
  and the overall task status as active.
2025-12-10 05:11:04 +09:00

120 lines
3.7 KiB
Rust

//! PlasmaVMC control plane server binary
use clap::Parser;
use plasmavmc_api::proto::vm_service_server::VmServiceServer;
use plasmavmc_hypervisor::HypervisorRegistry;
use plasmavmc_kvm::KvmBackend;
use plasmavmc_firecracker::FireCrackerBackend;
use plasmavmc_server::config::{self, ServerConfig};
use plasmavmc_server::VmServiceImpl;
use std::net::SocketAddr;
use std::path::PathBuf;
use std::sync::Arc;
use tonic::transport::Server;
use tonic_health::server::health_reporter;
use tracing_subscriber::EnvFilter;
/// PlasmaVMC control plane server
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Configuration file path
#[arg(short, long, default_value = "plasmavmc.toml")]
config: PathBuf,
/// Address to listen on (overrides config)
#[arg(short, long)]
addr: Option<String>,
/// Log level (overrides config)
#[arg(short, long)]
log_level: Option<String>,
/// Path to the Firecracker kernel image (overrides config)
#[arg(long)]
firecracker_kernel_path: Option<PathBuf>,
/// Path to the Firecracker rootfs image (overrides config)
#[arg(long)]
firecracker_rootfs_path: Option<PathBuf>,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Args::parse();
// Load configuration from file or use defaults
let mut config = if args.config.exists() {
let contents = tokio::fs::read_to_string(&args.config).await?;
toml::from_str(&contents)?
} else {
tracing::info!("Config file not found: {}, using defaults", args.config.display());
ServerConfig::default()
};
// Apply command line overrides
if let Some(addr_str) = args.addr {
config.addr = addr_str.parse()?;
}
if let Some(log_level) = args.log_level {
config.log_level = log_level;
}
if let Some(kernel_path) = args.firecracker_kernel_path {
config.firecracker.kernel_path = Some(kernel_path);
}
if let Some(rootfs_path) = args.firecracker_rootfs_path {
config.firecracker.rootfs_path = Some(rootfs_path);
}
// Initialize tracing
tracing_subscriber::fmt()
.with_env_filter(
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(&config.log_level)),
)
.init();
tracing::info!("Starting PlasmaVMC server on {}", config.addr);
// Create hypervisor registry and register backends
let registry = Arc::new(HypervisorRegistry::new());
// Register KVM backend (always available)
let kvm_backend = Arc::new(KvmBackend::with_defaults());
registry.register(kvm_backend);
// Register FireCracker backend if kernel/rootfs paths are configured
if let Some(firecracker_backend) = FireCrackerBackend::new_from_config(&config.firecracker) {
registry.register(Arc::new(firecracker_backend));
tracing::info!("Registered FireCracker backend");
} else {
tracing::debug!("FireCracker backend not available (missing kernel/rootfs paths)");
}
tracing::info!(
"Registered hypervisors: {:?}",
registry.available()
);
// Create services
let vm_service = VmServiceImpl::new(registry).await?;
// Setup health service
let (mut health_reporter, health_service) = health_reporter();
health_reporter
.set_serving::<VmServiceServer<VmServiceImpl>>()
.await;
// Parse address
let addr: SocketAddr = config.addr;
tracing::info!("PlasmaVMC server listening on {}", addr);
// Start server
Server::builder()
.add_service(health_service)
.add_service(VmServiceServer::new(vm_service))
.serve(addr)
.await?;
Ok(())
}