diff --git a/crates/kit/src/qemu.rs b/crates/kit/src/qemu.rs index 96d0813..a057ebe 100644 --- a/crates/kit/src/qemu.rs +++ b/crates/kit/src/qemu.rs @@ -907,6 +907,8 @@ pub struct VirtiofsConfig { pub debug: bool, /// Mount as read-only pub readonly: bool, + /// Optional log file path for virtiofsd output + pub log_file: Option, } impl Default for VirtiofsConfig { @@ -917,6 +919,7 @@ impl Default for VirtiofsConfig { debug: false, // We don't need to write to this, there's a transient overlay readonly: true, + log_file: None, } } } @@ -998,8 +1001,31 @@ pub async fn spawn_virtiofsd_async(config: &VirtiofsConfig) -> Result Result Result<()> { shared_dir: source_path, debug: false, readonly: is_readonly, + log_file: Some(format!("/run/virtiofsd-{}.log", mount_name_str).into()), }; additional_mounts.push((virtiofsd_config, tag.clone())); @@ -892,6 +893,35 @@ WantedBy=local-fs.target let default_wantsdir = format!("{target_unitdir}/default.target.wants"); fs::create_dir_all(&default_wantsdir)?; + // Create systemd unit to stream journal to virtio-serial device + let journal_stream_unit = r#"[Unit] +Description=Stream systemd journal to host via virtio-serial +DefaultDependencies=no +After=systemd-journald.service dev-virtio\x2dports-org.bcvk.journal.device +Requires=systemd-journald.service dev-virtio\x2dports-org.bcvk.journal.device + +[Service] +Type=simple +ExecStart=/usr/bin/journalctl -f -o short-precise --no-pager +StandardOutput=file:/dev/virtio-ports/org.bcvk.journal +StandardError=file:/dev/virtio-ports/org.bcvk.journal +Restart=always +RestartSec=1s + +[Install] +WantedBy=sysinit.target +"#; + let journal_unit_path = format!("{target_unitdir}/bcvk-journal-stream.service"); + tokio::fs::write(&journal_unit_path, journal_stream_unit).await?; + debug!("Created journal streaming unit at {journal_unit_path}"); + + // Enable the journal streaming unit + let sysinit_wantsdir = format!("{target_unitdir}/sysinit.target.wants"); + tokio::fs::create_dir_all(&sysinit_wantsdir).await?; + let journal_wants_link = format!("{sysinit_wantsdir}/bcvk-journal-stream.service"); + tokio::fs::symlink("../bcvk-journal-stream.service", &journal_wants_link).await?; + debug!("Enabled journal streaming unit in sysinit.target.wants"); + match opts.common.execute.as_slice() { [] => {} elts => { @@ -945,6 +975,8 @@ StandardOutput=file:/dev/virtio-ports/executestatus // Prepare main virtiofsd config for the source image (will be spawned by QEMU) let mut main_virtiofsd_config = qemu::VirtiofsConfig::default(); main_virtiofsd_config.debug = std::env::var("DEBUG_MODE").is_ok(); + // Always log virtiofsd output for debugging + main_virtiofsd_config.log_file = Some("/run/virtiofsd.log".into()); std::fs::create_dir_all(CONTAINER_STATEDIR)?; @@ -1092,6 +1124,10 @@ Options= .set_kernel_cmdline(kernel_cmdline) .set_console(opts.common.console); + // Add virtio-serial device for journal streaming + qemu_config.add_virtio_serial_out("org.bcvk.journal", "/run/journal.log".to_string(), false); + debug!("Added virtio-serial device for journal streaming to /run/journal.log"); + if opts.common.ssh_keygen { qemu_config.enable_ssh_access(None); // Use default port 2222 debug!("Enabled SSH port forwarding: host port 2222 -> guest port 22"); diff --git a/docs/src/man/bcvk-ephemeral-run.md b/docs/src/man/bcvk-ephemeral-run.md index a92b033..0393a4a 100644 --- a/docs/src/man/bcvk-ephemeral-run.md +++ b/docs/src/man/bcvk-ephemeral-run.md @@ -173,6 +173,48 @@ Development workflow example: # VM automatically cleans up when stopped due to --rm flag +# DEBUGGING + +When troubleshooting ephemeral VM issues, bcvk provides several debugging logs that can be accessed from within the container. + +## Guest Journal Log + +The systemd journal from the guest VM is automatically streamed to `/run/journal.log` inside the container. This log captures all boot messages, service startup events, and system errors from the VM's perspective. + +To view the journal log: + + # For a running detached VM + podman exec tail -f /run/journal.log + + # View specific systemd service messages + podman exec grep "dbus-broker" /run/journal.log + + # Save journal for offline analysis + podman exec cat /run/journal.log > guest-journal.log + +The journal log is particularly useful for: +- Diagnosing boot failures and systemd service issues +- Investigating permission denied errors +- Understanding VM initialization problems +- Debugging network and device configuration + +## Virtiofsd Logs + +The virtiofsd daemon logs are written to `/run/virtiofsd.log` and `/run/virtiofsd-.log` for each filesystem mount. These logs show filesystem sharing operations between the container and VM. + +To view virtiofsd logs: + + # Main virtiofsd log + podman exec cat /run/virtiofsd.log + + # Logs for additional bind mounts + podman exec cat /run/virtiofsd-workspace.log + +Virtiofsd logs are helpful for: +- Debugging filesystem access issues +- Understanding file handle support warnings +- Investigating mount-related errors + # SEE ALSO **bcvk**(8)