Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ test-integration *ARGS: build pull-test-images
#!/usr/bin/env bash
set -euo pipefail
export BCVK_PATH=$(pwd)/target/release/bcvk

# Clean up any leftover containers before starting
cargo run --release --bin test-cleanup -p integration-tests 2>/dev/null || true

# Run the tests
if command -v cargo-nextest &> /dev/null; then
cargo nextest run --release -P integration -p integration-tests {{ ARGS }}
Expand All @@ -37,12 +37,16 @@ test-integration *ARGS: build pull-test-images
cargo test --release -p integration-tests -- {{ ARGS }}
TEST_EXIT_CODE=$?
fi

# Clean up containers after tests complete
cargo run --release --bin test-cleanup -p integration-tests 2>/dev/null || true

exit $TEST_EXIT_CODE

# Run integration tests with qemu:///system (tests rootless podman + system libvirt)
test-integration-system *ARGS: build pull-test-images
env LIBVIRT_DEFAULT_URI=qemu:///system just test-integration {{ARGS}}

# Clean up integration test containers
test-cleanup:
cargo run --release --bin test-cleanup -p integration-tests
Expand Down
12 changes: 12 additions & 0 deletions crates/integration-tests/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ pub(crate) fn get_alternative_test_image() -> String {
}
}

/// Get libvirt connection arguments for CLI commands
///
/// Returns ["--connect", "URI"] if LIBVIRT_DEFAULT_URI is set, otherwise empty vec.
/// This uses the standard libvirt environment variable.
pub(crate) fn get_libvirt_connect_args() -> Vec<String> {
if let Some(uri) = std::env::var("LIBVIRT_DEFAULT_URI").ok() {
vec!["--connect".to_string(), uri]
} else {
vec![]
}
}

/// Captured output from a command with decoded stdout/stderr strings
pub(crate) struct CapturedOutput {
pub output: Output,
Expand Down
110 changes: 51 additions & 59 deletions crates/integration-tests/src/tests/libvirt_base_disks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@

use std::process::Command;

use crate::{get_bck_command, get_test_image};
use crate::{get_bck_command, get_libvirt_connect_args, get_test_image};

/// Test that base disk is created and reused for multiple VMs
pub fn test_base_disk_creation_and_reuse() {
let bck = get_bck_command().unwrap();
let test_image = get_test_image();
let connect_args = get_libvirt_connect_args();

// Generate unique names for test VMs
let timestamp = std::time::SystemTime::now()
Expand All @@ -33,20 +34,12 @@ pub fn test_base_disk_creation_and_reuse() {

// Create first VM - this should create a new base disk
println!("Creating first VM (should create base disk)...");
let vm1_output = Command::new("timeout")
.args([
"300s",
&bck,
"libvirt",
"run",
"--name",
&vm1_name,
"--filesystem",
"ext4",
&test_image,
])
.output()
.expect("Failed to create first VM");
let mut vm1_cmd = Command::new("timeout");
vm1_cmd.args(["300s", &bck, "libvirt"]);
vm1_cmd.args(&connect_args);
vm1_cmd.arg("run");
vm1_cmd.args(["--name", &vm1_name, "--filesystem", "ext4", &test_image]);
let vm1_output = vm1_cmd.output().expect("Failed to create first VM");

let vm1_stdout = String::from_utf8_lossy(&vm1_output.stdout);
let vm1_stderr = String::from_utf8_lossy(&vm1_output.stderr);
Expand All @@ -69,20 +62,12 @@ pub fn test_base_disk_creation_and_reuse() {

// Create second VM - this should reuse the base disk
println!("Creating second VM (should reuse base disk)...");
let vm2_output = Command::new("timeout")
.args([
"300s",
&bck,
"libvirt",
"run",
"--name",
&vm2_name,
"--filesystem",
"ext4",
&test_image,
])
.output()
.expect("Failed to create second VM");
let mut vm2_cmd = Command::new("timeout");
vm2_cmd.args(["300s", &bck, "libvirt"]);
vm2_cmd.args(&connect_args);
vm2_cmd.arg("run");
vm2_cmd.args(["--name", &vm2_name, "--filesystem", "ext4", &test_image]);
let vm2_output = vm2_cmd.output().expect("Failed to create second VM");

let vm2_stdout = String::from_utf8_lossy(&vm2_output.stdout);
let vm2_stderr = String::from_utf8_lossy(&vm2_output.stderr);
Expand Down Expand Up @@ -110,13 +95,15 @@ pub fn test_base_disk_creation_and_reuse() {
/// Test base-disks list command
pub fn test_base_disks_list_command() {
let bck = get_bck_command().unwrap();
let connect_args = get_libvirt_connect_args();

println!("Testing base-disks list command");

let output = Command::new(&bck)
.args(["libvirt", "base-disks", "list"])
.output()
.expect("Failed to run base-disks list");
let mut cmd = Command::new(&bck);
cmd.arg("libvirt");
cmd.args(&connect_args);
cmd.args(["base-disks", "list"]);
let output = cmd.output().expect("Failed to run base-disks list");

let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);
Expand Down Expand Up @@ -149,11 +136,15 @@ pub fn test_base_disks_list_command() {
/// Test base-disks prune command with dry-run
pub fn test_base_disks_prune_dry_run() {
let bck = get_bck_command().unwrap();
let connect_args = get_libvirt_connect_args();

println!("Testing base-disks prune --dry-run command");

let output = Command::new(&bck)
.args(["libvirt", "base-disks", "prune", "--dry-run"])
let mut cmd = Command::new(&bck);
cmd.arg("libvirt");
cmd.args(&connect_args);
cmd.args(["base-disks", "prune", "--dry-run"]);
let output = cmd
.output()
.expect("Failed to run base-disks prune --dry-run");

Expand Down Expand Up @@ -185,6 +176,7 @@ pub fn test_base_disks_prune_dry_run() {
pub fn test_vm_disk_references_base() {
let bck = get_bck_command().unwrap();
let test_image = get_test_image();
let connect_args = get_libvirt_connect_args();

let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
Expand All @@ -197,20 +189,12 @@ pub fn test_vm_disk_references_base() {
cleanup_domain(&vm_name);

// Create VM
let output = Command::new("timeout")
.args([
"300s",
&bck,
"libvirt",
"run",
"--name",
&vm_name,
"--filesystem",
"ext4",
&test_image,
])
.output()
.expect("Failed to create VM");
let mut vm_cmd = Command::new("timeout");
vm_cmd.args(["300s", &bck, "libvirt"]);
vm_cmd.args(&connect_args);
vm_cmd.arg("run");
vm_cmd.args(["--name", &vm_name, "--filesystem", "ext4", &test_image]);
let output = vm_cmd.output().expect("Failed to create VM");

if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
Expand All @@ -220,10 +204,12 @@ pub fn test_vm_disk_references_base() {
}

// Get VM disk path from domain XML
let dumpxml_output = Command::new("virsh")
.args(&["dumpxml", &vm_name])
.output()
.expect("Failed to dump domain XML");
let mut dumpxml_cmd = Command::new("virsh");
for arg in &connect_args {
dumpxml_cmd.arg(arg);
}
dumpxml_cmd.args(&["dumpxml", &vm_name]);
let dumpxml_output = dumpxml_cmd.output().expect("Failed to dump domain XML");

if !dumpxml_output.status.success() {
cleanup_domain(&vm_name);
Expand Down Expand Up @@ -261,18 +247,24 @@ pub fn test_vm_disk_references_base() {

/// Helper function to cleanup domain and its disk
fn cleanup_domain(domain_name: &str) {
let connect_args = get_libvirt_connect_args();
println!("Cleaning up domain: {}", domain_name);

// Stop domain if running
let _ = Command::new("virsh")
.args(&["destroy", domain_name])
.output();
let mut destroy_cmd = Command::new("virsh");
for arg in &connect_args {
destroy_cmd.arg(arg);
}
destroy_cmd.args(&["destroy", domain_name]);
let _ = destroy_cmd.output();

// Use bcvk libvirt rm for proper cleanup
let bck = get_bck_command().unwrap();
let cleanup_output = Command::new(&bck)
.args(&["libvirt", "rm", domain_name, "--force", "--stop"])
.output();
let mut cleanup_cmd = Command::new(&bck);
cleanup_cmd.arg("libvirt");
cleanup_cmd.args(&connect_args);
cleanup_cmd.args(&["rm", domain_name, "--force", "--stop"]);
let cleanup_output = cleanup_cmd.output();

if let Ok(output) = cleanup_output {
if output.status.success() {
Expand Down
20 changes: 2 additions & 18 deletions crates/kit/src/domain_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,24 +135,8 @@ impl DomainLister {

/// Get domain XML metadata as parsed DOM
pub fn get_domain_xml(&self, domain_name: &str) -> Result<xml_utils::XmlNode> {
let output = self
.virsh_command()
.args(&["dumpxml", domain_name])
.output()
.with_context(|| format!("Failed to dump XML for domain '{}'", domain_name))?;

if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(color_eyre::eyre::eyre!(
"Failed to get XML for domain '{}': {}",
domain_name,
stderr
));
}

let xml = String::from_utf8(output.stdout)?;
xml_utils::parse_xml_dom(&xml)
.with_context(|| format!("Failed to parse XML for domain '{}'", domain_name))
crate::libvirt::run::run_virsh_xml(self.connect_uri.as_deref(), &["dumpxml", domain_name])
.context(format!("Failed to get XML for domain '{}'", domain_name))
}

/// Extract podman-bootc metadata from parsed domain XML
Expand Down
Loading
Loading