Skip to content

Commit 94ce1f1

Browse files
committed
Check libvirt readonly support before using readonly bind mounts
The project command was unconditionally creating readonly bind mounts, which caused failures on libvirt versions < 11.0 that don't support readonly virtiofs. This was breaking the project_upgrade_workflow test in CI (libvirt 10.0). Assisted-by: Claude Code (Sonnet 4.5) Signed-off-by: Colin Walters <[email protected]>
1 parent d4b0843 commit 94ce1f1

File tree

2 files changed

+35
-42
lines changed

2 files changed

+35
-42
lines changed

crates/kit/src/libvirt/run.rs

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -818,30 +818,6 @@ fn process_bind_mounts(
818818
Ok(domain_builder)
819819
}
820820

821-
/// Check if the libvirt version supports readonly virtiofs filesystems
822-
/// Requires libvirt 11.0+ and modern QEMU with rust-based virtiofsd
823-
fn check_libvirt_readonly_support() -> Result<()> {
824-
let version = crate::libvirt::status::parse_libvirt_version()
825-
.with_context(|| "Failed to check libvirt version")?;
826-
827-
if crate::libvirt::status::supports_readonly_virtiofs(&version) {
828-
Ok(())
829-
} else {
830-
match version {
831-
Some(v) => Err(color_eyre::eyre::eyre!(
832-
"The --bind-storage-ro flag requires libvirt 11.0 or later for readonly virtiofs support. \
833-
Current version: {}",
834-
v.full_version
835-
)),
836-
None => Err(color_eyre::eyre::eyre!(
837-
"Could not parse libvirt version. \
838-
The --bind-storage-ro flag requires libvirt 11.0+ with rust-based virtiofsd support. \
839-
Please ensure you have a compatible libvirt version installed."
840-
))
841-
}
842-
}
843-
}
844-
845821
#[cfg(test)]
846822
mod tests {
847823
use super::*;
@@ -1086,6 +1062,16 @@ fn create_libvirt_domain_from_disk(
10861062
let mut mount_unit_smbios_creds = Vec::new();
10871063
let mut mount_unit_names = Vec::new();
10881064

1065+
// Check if libvirt supports readonly virtiofs
1066+
let version = crate::libvirt::status::parse_libvirt_version()
1067+
.with_context(|| "Failed to check libvirt version")?;
1068+
let supports_readonly = crate::libvirt::status::supports_readonly_virtiofs(&version);
1069+
1070+
// Log once if we're falling back readonly mounts to read-write
1071+
if !supports_readonly && (!opts.bind_mounts_ro.is_empty() || opts.bind_storage_ro) {
1072+
info!("Libvirt version does not support readonly virtiofs; using read-write bind mounts");
1073+
}
1074+
10891075
// Process bind mounts (read-write and read-only)
10901076
domain_builder = process_bind_mounts(
10911077
&opts.bind_mounts,
@@ -1096,20 +1082,30 @@ fn create_libvirt_domain_from_disk(
10961082
&mut mount_unit_names,
10971083
)?;
10981084

1099-
domain_builder = process_bind_mounts(
1100-
&opts.bind_mounts_ro,
1101-
"bcvk-bind-ro-",
1102-
true,
1103-
domain_builder,
1104-
&mut mount_unit_smbios_creds,
1105-
&mut mount_unit_names,
1106-
)?;
1085+
// Process readonly bind mounts - fall back to read-write if not supported
1086+
if supports_readonly {
1087+
domain_builder = process_bind_mounts(
1088+
&opts.bind_mounts_ro,
1089+
"bcvk-bind-ro-",
1090+
true,
1091+
domain_builder,
1092+
&mut mount_unit_smbios_creds,
1093+
&mut mount_unit_names,
1094+
)?;
1095+
} else {
1096+
// Fall back to read-write mounts
1097+
domain_builder = process_bind_mounts(
1098+
&opts.bind_mounts_ro,
1099+
"bcvk-bind-",
1100+
false,
1101+
domain_builder,
1102+
&mut mount_unit_smbios_creds,
1103+
&mut mount_unit_names,
1104+
)?;
1105+
}
11071106

11081107
// Add container storage mount if requested
11091108
if opts.bind_storage_ro {
1110-
// Check libvirt version compatibility for readonly virtiofs
1111-
check_libvirt_readonly_support().context("libvirt version compatibility check failed")?;
1112-
11131109
let storage_path = crate::utils::detect_container_storage_path()
11141110
.context("Failed to detect container storage path.")?;
11151111
crate::utils::validate_container_storage_path(&storage_path)
@@ -1120,10 +1116,11 @@ fn create_libvirt_domain_from_disk(
11201116
storage_path
11211117
);
11221118

1119+
// Use readonly if supported, otherwise fall back to read-write
11231120
let virtiofs_fs = VirtiofsFilesystem {
11241121
source_dir: storage_path.to_string(),
11251122
tag: "hoststorage".to_string(),
1126-
readonly: true,
1123+
readonly: supports_readonly,
11271124
};
11281125

11291126
domain_builder = domain_builder

crates/kit/src/project/up.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,6 @@ fn create_vm(
190190
// We know vm exists because load_from_dir validates it
191191
let vm = config.vm.as_ref().unwrap();
192192

193-
// Check if libvirt supports readonly virtiofs for bind_storage_ro
194-
let version = crate::libvirt::status::parse_libvirt_version()
195-
.with_context(|| "Failed to check libvirt version")?;
196-
let supports_readonly = crate::libvirt::status::supports_readonly_virtiofs(&version);
197-
198193
let mut run_opts = LibvirtRunOpts {
199194
image: vm.image.clone(),
200195
name: Some(name.to_string()),
@@ -209,7 +204,7 @@ fn create_vm(
209204
network: vm.net.network.clone(),
210205
detach: !ssh, // Don't detach if we're going to SSH
211206
ssh,
212-
bind_storage_ro: supports_readonly,
207+
bind_storage_ro: true,
213208
firmware: FirmwareType::UefiSecure,
214209
disable_tpm: false,
215210
secure_boot_keys: None,
@@ -229,6 +224,7 @@ fn create_vm(
229224
}
230225

231226
// Bind project directory to /run/src read-only with auto-mount
227+
// (will fall back to read-write if libvirt doesn't support readonly virtiofs)
232228
run_opts.bind_mounts_ro.push(
233229
format!("{}:/run/src", project_dir.as_str())
234230
.parse()

0 commit comments

Comments
 (0)