Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions microsandbox-cli/bin/msb/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub async fn add_subcommand(
names: Vec<String>,
image: String,
memory: Option<u32>,
cpus: Option<u32>,
cpus: Option<f32>,
volumes: Vec<String>,
ports: Vec<String>,
envs: Vec<String>,
Expand Down Expand Up @@ -219,7 +219,7 @@ pub async fn script_run_subcommand(
#[allow(clippy::too_many_arguments)]
pub async fn exe_subcommand(
name: String,
cpus: Option<u8>,
cpus: Option<f32>,
memory: Option<u32>,
volumes: Vec<String>,
ports: Vec<String>,
Expand Down Expand Up @@ -472,7 +472,7 @@ pub async fn self_subcommand(action: SelfAction) -> MicrosandboxCliResult<()> {
pub async fn install_subcommand(
name: String,
alias: Option<String>,
cpus: Option<u8>,
cpus: Option<f32>,
memory: Option<u32>,
volumes: Vec<String>,
ports: Vec<String>,
Expand Down
5 changes: 3 additions & 2 deletions microsandbox-cli/bin/msbrun.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//! --log-level=3 \
//! --native-rootfs=/path/to/rootfs \
//! --overlayfs-rootfs=/path/to/rootfs \
//! --num-vcpus=2 \
//! --num-vcpus=0.5 \
//! --memory-mib=1024 \
//! --workdir-path=/app \
//! --exec-path=/usr/bin/python3 \
Expand All @@ -41,7 +41,7 @@
//! --log-level=3 \
//! --native-rootfs=/path/to/rootfs \
//! --overlayfs-rootfs=/path/to/rootfs \
//! --num-vcpus=2 \
//! --num-vcpus=0.5 \
//! --memory-mib=1024 \
//! --workdir-path=/app \
//! --exec-path=/usr/bin/python3 \
Expand Down Expand Up @@ -256,6 +256,7 @@ async fn main() -> Result<()> {
log_dir.clone(),
rootfs.clone(),
forward_output,
num_vcpus,
)
.await?;

Expand Down
15 changes: 12 additions & 3 deletions microsandbox-cli/bin/msbserver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,20 @@ pub async fn main() -> MicrosandboxCliResult<()> {
args.dev_mode,
)?);

// Get namespace directory from config
// Get namespace directory and port range from config
let namespace_dir = config.get_namespace_dir().clone();
let port_range = (
config.get_port_range_min().as_ref().copied(),
config.get_port_range_max().as_ref().copied(),
);

// Initialize the port manager
let port_manager = PortManager::new(namespace_dir).await.map_err(|e| {
// Initialize the port manager with the configured port range
let port_manager = if let (Some(min), Some(max)) = port_range {
PortManager::new_with_range(namespace_dir, Some((min, max))).await
} else {
PortManager::new(namespace_dir).await
}
.map_err(|e| {
eprintln!("Error initializing port manager: {}", e);
e
})?;
Expand Down
6 changes: 3 additions & 3 deletions microsandbox-cli/lib/args/msb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub enum MicrosandboxSubcommand {

/// Number of CPUs
#[arg(long, alias = "cpu")]
cpus: Option<u32>,
cpus: Option<f32>,

/// Volume mappings, format: <host_path>:<container_path>
#[arg(short, long = "volume", name = "VOLUME")]
Expand Down Expand Up @@ -290,7 +290,7 @@ pub enum MicrosandboxSubcommand {

/// Number of CPUs
#[arg(long, alias = "cpu")]
cpus: Option<u8>,
cpus: Option<f32>,

/// Memory in MB
#[arg(long)]
Expand Down Expand Up @@ -342,7 +342,7 @@ pub enum MicrosandboxSubcommand {

/// Number of CPUs
#[arg(long, alias = "cpu")]
cpus: Option<u8>,
cpus: Option<f32>,

/// Memory in MB
#[arg(long)]
Expand Down
8 changes: 4 additions & 4 deletions microsandbox-cli/lib/args/msbrun.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ pub enum McrunSubcommand {
#[arg(long)]
overlayfs_layer: Vec<PathBuf>,

/// Number of virtual CPUs
/// Number of virtual CPUs (supports fractional values)
#[arg(long)]
num_vcpus: Option<u8>,
num_vcpus: Option<f32>,

/// Memory size in MiB
#[arg(long)]
Expand Down Expand Up @@ -119,9 +119,9 @@ pub enum McrunSubcommand {
#[arg(long)]
overlayfs_layer: Vec<PathBuf>,

/// Number of virtual CPUs
/// Number of virtual CPUs (supports fractional values)
#[arg(long)]
num_vcpus: Option<u8>,
num_vcpus: Option<f32>,

/// Memory size in MiB
#[arg(long)]
Expand Down
4 changes: 2 additions & 2 deletions microsandbox-core/lib/config/microsandbox/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub struct SandboxBuilder<I> {
meta: Option<Meta>,
image: I,
memory: Option<u32>,
cpus: Option<u8>,
cpus: Option<f32>,
volumes: Vec<PathPair>,
ports: Vec<PortPair>,
envs: Vec<EnvPair>,
Expand Down Expand Up @@ -163,7 +163,7 @@ impl<I> SandboxBuilder<I> {
}

/// Sets the maximum number of CPUs allowed for the sandbox
pub fn cpus(mut self, cpus: u8) -> SandboxBuilder<I> {
pub fn cpus(mut self, cpus: f32) -> SandboxBuilder<I> {
self.cpus = Some(cpus);
self
}
Expand Down
62 changes: 55 additions & 7 deletions microsandbox-core/lib/config/microsandbox/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,11 @@ pub struct Build {
#[builder(default, setter(strip_option))]
pub(crate) memory: Option<u32>,

/// The number of vCPUs to use.
/// The number of vCPUs to use (supports fractional values like 0.5, 0.25).
/// Valid range: 0.1 to 128.0
#[serde(skip_serializing_if = "Option::is_none", default)]
#[builder(default, setter(strip_option))]
pub(crate) cpus: Option<u8>,
pub(crate) cpus: Option<f32>,

/// The volumes to mount.
#[serde(skip_serializing_if = "Vec::is_empty", default)]
Expand Down Expand Up @@ -242,9 +243,10 @@ pub struct Sandbox {
#[serde(skip_serializing_if = "Option::is_none", default)]
pub(crate) memory: Option<u32>,

/// The number of vCPUs to use.
/// The number of vCPUs to use (supports fractional values like 0.5, 0.25).
/// Valid range: 0.1 to 128.0
#[serde(skip_serializing_if = "Option::is_none", default)]
pub(crate) cpus: Option<u8>,
pub(crate) cpus: Option<f32>,

/// The volumes to mount.
#[serde(skip_serializing_if = "Vec::is_empty", default)]
Expand Down Expand Up @@ -633,7 +635,7 @@ mod tests {
let sandbox = sandboxes.get("test_sandbox").unwrap();
assert_eq!(sandbox.version.as_ref().unwrap().to_string(), "1.0.0");
assert_eq!(sandbox.memory.unwrap(), 1024);
assert_eq!(sandbox.cpus.unwrap(), 2);
assert_eq!(sandbox.cpus.unwrap(), 2.0);
assert_eq!(sandbox.volumes[0].to_string(), "./src:/app/src");
assert_eq!(sandbox.ports[0].to_string(), "8080:80");
assert_eq!(sandbox.envs[0].to_string(), "DEBUG=true");
Expand Down Expand Up @@ -718,7 +720,7 @@ mod tests {
let builds = &config.builds;
let base_build = builds.get("base_build").unwrap();
assert_eq!(base_build.memory.unwrap(), 2048);
assert_eq!(base_build.cpus.unwrap(), 2);
assert_eq!(base_build.cpus.unwrap(), 2.0);
assert_eq!(
base_build.workdir.as_ref().unwrap(),
&Utf8UnixPathBuf::from("/build")
Expand All @@ -742,7 +744,7 @@ mod tests {
let api = sandboxes.get("api").unwrap();
assert_eq!(api.version.as_ref().unwrap().to_string(), "1.0.0");
assert_eq!(api.memory.unwrap(), 1024);
assert_eq!(api.cpus.unwrap(), 1);
assert_eq!(api.cpus.unwrap(), 1.0);
assert_eq!(api.depends_on, vec!["database", "cache"]);
assert_eq!(api.scope, NetworkScope::Public);
}
Expand Down Expand Up @@ -795,4 +797,50 @@ mod tests {
"#;
assert!(serde_yaml::from_str::<Microsandbox>(yaml).is_err());
}

#[test]
fn microsandbox_config_accepts_fractional_cpus_in_sandbox_and_build() {
let yaml = r#"
builds:
base:
image: "alpine:latest"
cpus: 0.5
sandboxes:
svc:
image: "alpine:latest"
shell: "/bin/sh"
cpus: 0.25
"#;

let config: Microsandbox = serde_yaml::from_str(yaml).unwrap();
let base = config.get_build("base").unwrap();
assert_eq!(base.cpus, Some(0.5));
let svc = config.get_sandbox("svc").unwrap();
assert_eq!(svc.cpus, Some(0.25));
}

#[test]
fn microsandbox_config_missing_cpus_is_none() {
let yaml = r#"
sandboxes:
a:
image: "alpine:latest"
shell: "/bin/sh"
"#;
let config: Microsandbox = serde_yaml::from_str(yaml).unwrap();
assert!(config.get_sandbox("a").unwrap().cpus.is_none());
}

#[test]
fn microsandbox_config_integer_cpus_still_supported() {
let yaml = r#"
sandboxes:
b:
image: "alpine:latest"
shell: "/bin/sh"
cpus: 2
"#;
let config: Microsandbox = serde_yaml::from_str(yaml).unwrap();
assert_eq!(config.get_sandbox("b").unwrap().cpus, Some(2.0));
}
}
4 changes: 2 additions & 2 deletions microsandbox-core/lib/management/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub struct SandboxConfig {
pub memory: Option<u32>,

/// The number of CPUs to use.
pub cpus: Option<u32>,
pub cpus: Option<f32>,

/// The volumes to mount.
pub volumes: Vec<String>,
Expand Down Expand Up @@ -168,7 +168,7 @@ pub async fn add(
}

if let Some(cpus_value) = config.cpus {
sandbox_mapping.insert_u32("cpus", cpus_value);
sandbox_mapping.insert_f32("cpus", cpus_value);
}

// Add shell (default if not provided)
Expand Down
4 changes: 2 additions & 2 deletions microsandbox-core/lib/management/home.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ pub async fn clean(force: bool) -> MicrosandboxResult<()> {
/// &image,
/// Some("shell"), // Run shell script
/// Some("ubuntu-shell"), // Custom alias
/// Some(2), // 2 CPUs
/// Some(2.0), // 2 CPUs
/// Some(1024), // 1GB RAM
/// vec![ // Mount host's /tmp to sandbox's /data
/// "/tmp:/data".to_string()
Expand All @@ -172,7 +172,7 @@ pub async fn install(
image: &Reference,
script: Option<&str>,
alias: Option<&str>,
cpus: Option<u8>,
cpus: Option<f32>,
memory: Option<u32>,
volumes: Vec<String>,
ports: Vec<String>,
Expand Down
4 changes: 2 additions & 2 deletions microsandbox-core/lib/management/sandbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ pub async fn prepare_run(
/// sandbox::run_temp(
/// &image,
/// Some("start"), // Script name
/// Some(2), // 2 CPUs
/// Some(2.0), // 2 CPUs
/// Some(1024), // 1GB RAM
/// vec![ // Mount host's /tmp to sandbox's /data
/// "/tmp:/data".to_string()
Expand All @@ -445,7 +445,7 @@ pub async fn prepare_run(
pub async fn run_temp(
image: &Reference,
script: Option<&str>,
cpus: Option<u8>,
cpus: Option<f32>,
memory: Option<u32>,
volumes: Vec<String>,
ports: Vec<String>,
Expand Down
Loading