Browse Source

feat: add functions to create domain

rust
Giovanni Torres 1 year ago
parent
commit
0b9c81065a
  1. 50
      src/main.rs
  2. 94
      src/vm.rs

50
src/main.rs

@ -1,30 +1,48 @@
use anyhow::Result;
use clap::Parser;
use kvm_install_vm::Cli;
use kvm_install_vm::{Cli, vm::VirtualMachine};
use std::process;
#[tokio::main]
async fn main() -> Result<()> {
fn main() {
// Initialize logger
env_logger::init();
// Parse command line arguments
let cli = Cli::parse();
let args = Cli::parse();
println!("Starting kvm-install-vm Rust implementation...");
println!("VM Name: {}", cli.name);
println!("Distribution: {}", cli.distro);
println!("VM Name: {}", args.name);
println!("Distribution: {}", args.distro);
println!("Configuration:");
println!(" vCPUs: {}", cli.vcpus);
println!(" Memory: {} MB", cli.memory_mb);
println!(" Disk Size: {} GB", cli.disk_size_gb);
println!(" vCPUs: {}", args.vcpus);
println!(" Memory: {} MB", args.memory_mb);
println!(" Disk Size: {} GB", args.disk_size_gb);
if cli.dry_run {
println!("Dry run mode - no VM will be created");
return Ok(());
}
let disk_path = format!("/home/giovanni/virt/images/{}.qcow2", args.name);
let vm_name = args.name.clone();
let mut vm = VirtualMachine::new(
args.name,
args.vcpus,
args.memory_mb,
args.disk_size_gb,
disk_path,
// args.distro,
);
println!("VM creation would start here...");
if let Err(e) = vm.connect(None) {
eprintln!("Failed to connect to libvirt: {}", e);
process::exit(1);
}
Ok(())
match vm.create() {
Ok(domain) => {
println!("Successfully created VM: {}", vm_name);
println!("Domain ID: {}", domain.get_id().unwrap_or(0));
},
Err(e) => {
eprintln!("Failed to create VM: {}", e);
process::exit(1);
}
}
}

94
src/vm.rs

@ -1,24 +1,102 @@
use anyhow::Result;
use anyhow::{Result, Context};
use std::path::Path;
use virt::connect::Connect;
use virt::domain::Domain;
pub struct VirtualMachine {
pub name: String,
pub vcpus: u32,
pub memory_mb: u32,
pub disk_size_gb: u32,
name: String,
vcpus: u32,
memory_mb: u32,
disk_size_gb: u32,
disk_path: String,
// distro: String,
connection: Option<Connect>,
}
impl VirtualMachine {
pub fn new(name: String, vcpus: u32, memory_mb: u32, disk_size_gb: u32) -> Self {
pub fn new(name: String, vcpus: u32, memory_mb: u32, disk_size_gb: u32, disk_path: String) -> Self {
VirtualMachine {
name,
vcpus,
memory_mb,
disk_path,
disk_size_gb,
// distro,
connection: None,
}
}
pub fn create(&self) -> Result<()> {
println!("Creating VM: {}", self.name);
pub fn connect(&mut self, uri: Option<&str>) -> Result<()> {
// Connect to libvirt daemon, default to "qemu:///system" if no URI provided
let uri = uri.or(Some("qemu:///system"));
self.connection = Some(Connect::open(uri).context("Failed to connect to libvirt")?);
Ok(())
}
pub fn create(&mut self) -> Result<Domain> {
// Ensure connection is established
let conn = match &self.connection {
Some(c) => c,
None => return Err(anyhow::anyhow!("Connection not established")),
};
if !Path::new(&self.disk_path).exists() {
self.create_disk_image()?;
}
let xml = self.generate_domain_xml()?;
let domain = Domain::define_xml(&conn, &xml).context("Failed to define domain from XML")?;
domain.create().context("Failed to start the domain")?;
Ok(domain)
}
fn create_disk_image(&self) -> Result<()> {
// Create disk image using qemu-img
let output = std::process::Command::new("qemu-img")
.args(&["create", "-f", "qcow2", &self.disk_path, &format!("{}G", self.disk_size_gb)])
.output()
.context("Failed to execute qemu-img command")?;
if !output.status.success() {
return Err(anyhow::anyhow!("Failed to create disk image: {:?}", output.stderr));
}
Ok(())
}
fn generate_domain_xml(&self) -> Result<String> {
// Generate domain XML
let xml = format!( r#"
<domain type='kvm'>
<name>{}</name>
<memory unit='MiB'>{}</memory>
<vcpu>{}</vcpu>
<os>
<type arch='x86_64'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<devices>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='{}'/>
<target dev='vda' bus='virtio'/>
</disk>
<interface type='network'>
<source network='default'/>
<model type='virtio'/>
</interface>
<console type='pty'/>
<graphics type='vnc' port='-1'/>
</devices>
</domain>
"#, self.name, self.memory_mb, self.vcpus, self.disk_path);
Ok(xml)
}
}

Loading…
Cancel
Save