Skip to content

Conversation

@cgwalters
Copy link
Collaborator

Previously, STORAGE_OPTS environment configuration was unconditionally injected into VMs via both tmpfiles.d and a systemd service unit. This caused VMs created without --bind-storage-ro to reference a non-existent /run/host-container-storage path in their environment.

Change things to only inject when opts.bind_storage_ro is set.

Additionally, refactor to use a single smbios_creds vector instead of separate mount_unit_smbios_creds and storage_opts_creds vectors, making the code cleaner and easier to follow.

Assisted-by: Claude Code (Sonnet 4.5)

Previously, STORAGE_OPTS environment configuration was unconditionally
injected into VMs via both tmpfiles.d and a systemd service unit. This
caused VMs created without `--bind-storage-ro` to reference a non-existent
`/run/host-container-storage` path in their environment.

Change things to only inject when opts.bind_storage_ro is set.

Additionally, refactor to use a single smbios_creds vector instead of
separate mount_unit_smbios_creds and storage_opts_creds vectors, making
the code cleaner and easier to follow.

Assisted-by: Claude Code (Sonnet 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly fixes an issue where STORAGE_OPTS were unconditionally injected into VMs, even when not required. The change correctly scopes the injection to only occur when the --bind-storage-ro flag is used. A comprehensive integration test has been added to verify this fix, ensuring that VMs created without the flag do not contain the unnecessary configuration. Additionally, the code has been refactored to use a single smbios_creds vector, which improves clarity and maintainability by consolidating SMBIOS credential handling. The changes are well-implemented and improve both the correctness and readability of the code. I have one suggestion to make the code even more idiomatic.

Comment on lines +1153 to 1156
for cred in smbios_creds {
qemu_args.push("-smbios".to_string());
qemu_args.push(format!("type=11,value={}", mount_cred));
qemu_args.push(format!("type=11,value={}", cred));
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better performance and more idiomatic Rust, you can replace this loop with a combination of flat_map and extend. This avoids repeated push calls which might cause reallocations and is generally more expressive.

Suggested change
for cred in smbios_creds {
qemu_args.push("-smbios".to_string());
qemu_args.push(format!("type=11,value={}", mount_cred));
qemu_args.push(format!("type=11,value={}", cred));
}
qemu_args.extend(smbios_creds.into_iter().flat_map(|cred| {
[
"-smbios".to_string(),
format!("type=11,value={}", cred),
]
}));

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly addresses the issue of unconditionally injecting STORAGE_OPTS by making the injection conditional on the --bind-storage-ro flag. The addition of the test_libvirt_run_no_storage_opts_without_bind_storage integration test is excellent, as it thoroughly verifies the fix by checking for the absence of the related configurations in the domain XML. The refactoring to use a single smbios_creds vector and consolidating the QEMU argument construction significantly improves code clarity and maintainability. I have one minor suggestion to further simplify the QEMU argument building logic.

Comment on lines +1142 to 1156
// Build QEMU args with all SMBIOS credentials
{
let encoded = data_encoding::BASE64.encode(tmpfiles_content.as_bytes());
let smbios_cred = format!("io.systemd.credential.binary:tmpfiles.extra={encoded}");
qemu_args.extend([
"-smbios".to_string(),
format!("type=11,value={}", smbios_cred),
]);
}

// Add SMBIOS credentials for mount units
for mount_cred in mount_unit_smbios_creds {
// Add all SMBIOS credentials (mount units, storage opts, etc.)
for cred in smbios_creds {
qemu_args.push("-smbios".to_string());
qemu_args.push(format!("type=11,value={}", mount_cred));
qemu_args.push(format!("type=11,value={}", cred));
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for adding SMBIOS credentials to qemu_args is split into two parts (one for tmpfiles.extra and another for other credentials), which leads to some repetition. You could simplify this by combining all credentials into a single collection first and then iterating over it once to build the arguments. This would make the code more concise and easier to maintain.

For example:

// Collect all credentials into one vector
let mut all_creds = smbios_creds;
let encoded = data_encoding::BASE64.encode(tmpfiles_content.as_bytes());
all_creds.push(format!(
    "io.systemd.credential.binary:tmpfiles.extra={}",
    encoded
));

// Build QEMU args from the consolidated list
for cred in all_creds {
    qemu_args.push("-smbios".to_string());
    qemu_args.push(format!("type=11,value={}", cred));
}

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly fixes an issue where STORAGE_OPTS were unconditionally injected into VMs, and adds a new integration test to verify the behavior. The refactoring to consolidate SMBIOS credentials into a single vector is a great improvement for code clarity. I've added a couple of suggestions: one to further improve the credential handling logic for better maintainability, and another to make the new integration test more robust against potential name collisions.

Comment on lines +972 to +975
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using the current time in seconds for unique names can lead to collisions if tests run in the same second. Using nanoseconds provides higher resolution and significantly reduces the chance of creating duplicate domain names, making the tests more robust.

Suggested change
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs()
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'll try to get back to #78

@cgwalters cgwalters mentioned this pull request Nov 4, 2025
@cgwalters cgwalters enabled auto-merge (rebase) November 4, 2025 18:34
Copy link
Collaborator

@jmarrero jmarrero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@cgwalters cgwalters merged commit 99354ee into bootc-dev:main Nov 4, 2025
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants