Skip to content

Commit bec34ca

Browse files
cgwaltersJohan-Liebert1
authored andcommitted
ci: Capture VM journal+console logs via bcvk --log-dir
When a VM fails to become SSH-reachable, all we get today is "SSH connectivity check failed after 60 attempts" with no insight into what went wrong inside the VM. bcvk libvirt run supports --log-dir to stream the systemd journal (as JSON) and virtio console to files while the VM is running. Wire this into run_tmt(): each VM now gets its own log subdirectory under /var/tmp/tmt/<vm-name>/ (the same base directory the CI workflow already collects as an artifact). The path is resolved as: - CLI --log-dir flag (new RunTmtArgs field) - $TMT_LOG_DIR environment variable - /var/tmp/tmt (default, matches CI artifact path) The flag is probed at runtime via `bcvk libvirt run --help` so older bcvk versions (pre-0.17) silently fall back to no log capture rather than hard-failing. When SSH verification fails, the error message now prints the log directory path so developers know where to look. No CI workflow changes needed: the existing "Archive TMT logs" steps already upload /var/tmp/tmt/** as artifacts. Assisted-by: OpenCode (Claude Sonnet 4.6) Signed-off-by: Colin Walters <walters@verbum.org>
1 parent 1f824fb commit bec34ca

2 files changed

Lines changed: 43 additions & 1 deletion

File tree

crates/xtask/src/tmt.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,25 @@ pub(crate) fn run_tmt(sh: &Shell, args: &RunTmtArgs) -> Result<()> {
419419

420420
println!("Found {} test plan(s): {:?}", plans.len(), plans);
421421

422+
// Determine base log directory: CLI flag > TMT_LOG_DIR env var > default.
423+
// Filter out empty TMT_LOG_DIR (e.g. TMT_LOG_DIR="") to avoid creating
424+
// log subdirectories in the current working directory.
425+
let base_log_dir: Utf8PathBuf = if let Some(ref d) = args.log_dir {
426+
d.clone()
427+
} else if let Some(env_dir) = std::env::var("TMT_LOG_DIR").ok().filter(|s| !s.is_empty()) {
428+
Utf8PathBuf::from(env_dir)
429+
} else {
430+
Utf8PathBuf::from("/var/tmp/tmt")
431+
};
432+
433+
// Probe whether this bcvk supports --log-dir (added in bcvk 0.17).
434+
// Older installs silently lack it; we skip the flag rather than hard-failing.
435+
let bcvk_has_log_dir = cmd!(sh, "bcvk libvirt run --help")
436+
.ignore_stderr()
437+
.read()
438+
.map(|help| help.contains("--log-dir"))
439+
.unwrap_or(false);
440+
422441
// Generate a random suffix for VM names
423442
let random_suffix = generate_random_suffix();
424443

@@ -483,11 +502,22 @@ pub(crate) fn run_tmt(sh: &Shell, args: &RunTmtArgs) -> Result<()> {
483502
opts
484503
};
485504

505+
// Set up per-VM log directory for journal + console capture (if bcvk supports it)
506+
let vm_log_dir = base_log_dir.join(&vm_name);
507+
let log_dir_args: Vec<String> = if bcvk_has_log_dir {
508+
std::fs::create_dir_all(&vm_log_dir)
509+
.with_context(|| format!("Creating VM log directory {}", vm_log_dir))?;
510+
println!("VM logs will be written to: {}", vm_log_dir);
511+
vec![format!("--log-dir=journal,console={}", vm_log_dir)]
512+
} else {
513+
vec![]
514+
};
515+
486516
// Launch VM with bcvk
487517
let firmware_args_slice = firmware_args.as_slice();
488518
let launch_result = cmd!(
489519
sh,
490-
"bcvk libvirt run --name {vm_name} --detach {firmware_args_slice...} {COMMON_INST_ARGS...} {plan_bcvk_opts...} {image}"
520+
"bcvk libvirt run --name {vm_name} --detach {firmware_args_slice...} {COMMON_INST_ARGS...} {plan_bcvk_opts...} {log_dir_args...} {image}"
491521
)
492522
.run()
493523
.context("Launching VM with bcvk");
@@ -581,6 +611,12 @@ pub(crate) fn run_tmt(sh: &Shell, args: &RunTmtArgs) -> Result<()> {
581611
println!("Verifying SSH connectivity...");
582612
if let Err(e) = verify_ssh_connectivity(sh, ssh_port, &key_path) {
583613
eprintln!("SSH verification failed for plan {}: {:#}", plan, e);
614+
if bcvk_has_log_dir {
615+
eprintln!(
616+
"VM logs (journal + console) may be available at: {}",
617+
vm_log_dir
618+
);
619+
}
584620
cleanup_vm();
585621
all_passed = false;
586622
test_results.push((plan.to_string(), false, None));

crates/xtask/src/xtask.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,12 @@ pub(crate) struct RunTmtArgs {
253253
/// Additional kernel arguments to pass to bcvk
254254
#[arg(long)]
255255
pub(crate) karg: Vec<String>,
256+
257+
/// Base directory for VM log files (journal + console).
258+
/// Defaults to $TMT_LOG_DIR if set, otherwise /var/tmp/tmt.
259+
/// Each VM gets its own subdirectory: `<log-dir>/<vm-name>/`
260+
#[arg(long)]
261+
pub(crate) log_dir: Option<camino::Utf8PathBuf>,
256262
}
257263

258264
impl RunTmtArgs {

0 commit comments

Comments
 (0)