Skip to content

Commit bfd8714

Browse files
fix: add /dev/kvm and /dev/net/tun to OCI spec, remove devices config field
Move device provisioning from CLI-side exec hack to the OCI runtime spec. The bundle builder now always includes /dev/kvm (10,232) and /dev/net/tun (10,200) as linux.devices entries, so youki creates them during container setup. No user configuration needed. Remove the "devices" field from vz.json — these devices are always created when the kernel supports them. Bump vz-cli to v0.3.5. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 17e3d46 commit bfd8714

4 files changed

Lines changed: 41 additions & 37 deletions

File tree

crates/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/vz-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "vz-cli"
3-
version = "0.3.4"
3+
version = "0.3.5"
44
description = "CLI for managing containers and macOS VM sandboxes"
55
edition.workspace = true
66
rust-version.workspace = true

crates/vz-cli/src/commands/dev.rs

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,6 @@ struct VzConfig {
9797
/// Resource limits.
9898
#[serde(default)]
9999
resources: ResourceConfig,
100-
101-
/// Device nodes to create inside the container (e.g., "/dev/kvm", "/dev/net/tun").
102-
/// These are created via mknod at container start using the host VM's device metadata.
103-
#[serde(default)]
104-
devices: Vec<String>,
105100
}
106101

107102
fn default_image() -> String {
@@ -664,7 +659,7 @@ fn ensure_project_disk(sandbox_id: &str) -> anyhow::Result<PathBuf> {
664659

665660
/// Compute a setup hash over the full vz.json config.
666661
///
667-
/// Includes image, setup commands, devices, and resources so that
662+
/// Includes image, setup commands, and resources so that
668663
/// changes to any of these trigger re-execution of setup.
669664
fn compute_setup_hash(config: &VzConfig) -> String {
670665
let mut hasher = Sha256::new();
@@ -674,11 +669,6 @@ fn compute_setup_hash(config: &VzConfig) -> String {
674669
hasher.update(cmd.as_bytes());
675670
hasher.update(b"\n");
676671
}
677-
for dev in &config.devices {
678-
hasher.update(b"dev:");
679-
hasher.update(dev.as_bytes());
680-
hasher.update(b"\n");
681-
}
682672
if let Some(cpus) = config.resources.cpus {
683673
hasher.update(format!("cpus:{cpus}\n").as_bytes());
684674
}
@@ -758,27 +748,6 @@ async fn run_setup_if_needed(
758748
return Ok(());
759749
}
760750

761-
// Create requested device nodes before running user setup commands.
762-
if !config.devices.is_empty() {
763-
let device_cmds: Vec<String> = config
764-
.devices
765-
.iter()
766-
.map(|dev| {
767-
// Read major:minor from /proc/misc or /sys for well-known devices.
768-
// For now, handle the common cases directly.
769-
match dev.as_str() {
770-
"/dev/kvm" => "mknod /dev/kvm c 10 232 2>/dev/null || true".to_string(),
771-
"/dev/net/tun" => "mkdir -p /dev/net && mknod /dev/net/tun c 10 200 2>/dev/null || true".to_string(),
772-
_ => format!("echo 'unsupported device: {dev}'"),
773-
}
774-
})
775-
.collect();
776-
777-
for cmd in &device_cmds {
778-
let _ = exec_quiet(client, &container_id, cmd).await;
779-
}
780-
}
781-
782751
eprintln!("Running setup commands...");
783752
for (i, cmd) in config.setup.iter().enumerate() {
784753
eprintln!(" [{}/{}] {}", i + 1, config.setup.len(), cmd);

crates/vz-oci/src/bundle.rs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ use std::io;
44
use std::path::{Path, PathBuf};
55

66
use oci_spec::runtime::{
7-
Capability, LinuxCapabilities, LinuxCapabilitiesBuilder, LinuxCpuBuilder, LinuxNamespaceType,
8-
LinuxPidsBuilder, LinuxResourcesBuilder, Mount, MountBuilder, PosixRlimit, PosixRlimitBuilder,
9-
PosixRlimitType, ProcessBuilder, RootBuilder, Spec, SpecBuilder, User, UserBuilder, VERSION,
7+
Capability, LinuxCapabilities, LinuxCapabilitiesBuilder, LinuxCpuBuilder, LinuxDeviceBuilder,
8+
LinuxDeviceType, LinuxNamespaceType, LinuxPidsBuilder, LinuxResourcesBuilder, Mount,
9+
MountBuilder, PosixRlimit, PosixRlimitBuilder, PosixRlimitType, ProcessBuilder, RootBuilder,
10+
Spec, SpecBuilder, User, UserBuilder, VERSION,
1011
};
1112

1213
use crate::error::OciError;
@@ -319,6 +320,10 @@ fn build_runtime_spec(spec: BundleSpec, rootfs_path: &str) -> Result<Spec, OciEr
319320
set_sysctls(&mut spec, sysctls);
320321
}
321322

323+
// Always expose /dev/kvm and /dev/net/tun when available in the host VM kernel.
324+
// These are needed for nested virtualization (Firecracker) and tap networking.
325+
set_default_devices(&mut spec);
326+
322327
Ok(spec)
323328
}
324329

@@ -766,6 +771,36 @@ fn parse_capability_name(name: &str) -> Option<Capability> {
766771
}
767772
}
768773

774+
/// Add /dev/kvm and /dev/net/tun to the OCI spec so youki creates them
775+
/// during container setup. These are always useful when the host VM kernel
776+
/// supports them — no user configuration needed.
777+
fn set_default_devices(spec: &mut Spec) {
778+
let Some(linux) = spec.linux_mut() else {
779+
return;
780+
};
781+
782+
let devices = vec![
783+
LinuxDeviceBuilder::default()
784+
.path("/dev/kvm")
785+
.typ(LinuxDeviceType::C)
786+
.major(10)
787+
.minor(232)
788+
.file_mode(0o666u32)
789+
.build()
790+
.expect("valid /dev/kvm device spec"),
791+
LinuxDeviceBuilder::default()
792+
.path("/dev/net/tun")
793+
.typ(LinuxDeviceType::C)
794+
.major(10)
795+
.minor(200)
796+
.file_mode(0o666u32)
797+
.build()
798+
.expect("valid /dev/net/tun device spec"),
799+
];
800+
801+
linux.set_devices(Some(devices));
802+
}
803+
769804
/// Set sysctl parameters on the OCI spec's linux section.
770805
fn set_sysctls(spec: &mut Spec, sysctls: HashMap<String, String>) {
771806
if let Some(linux) = spec.linux_mut() {

0 commit comments

Comments
 (0)