diff --git a/crates/integration-tests/src/tests/libvirt_verb.rs b/crates/integration-tests/src/tests/libvirt_verb.rs index 048a0af..55d7fee 100644 --- a/crates/integration-tests/src/tests/libvirt_verb.rs +++ b/crates/integration-tests/src/tests/libvirt_verb.rs @@ -363,6 +363,97 @@ fn test_libvirt_ssh_integration() -> Result<()> { Ok(()) } +#[distributed_slice(INTEGRATION_TESTS)] +static TEST_LIBVIRT_RUN_WITH_INSTANCETYPE: IntegrationTest = IntegrationTest::new( + "test_libvirt_run_with_instancetype", + test_libvirt_run_with_instancetype, +); + +/// Test libvirt run with instancetype +fn test_libvirt_run_with_instancetype() -> Result<()> { + let test_image = get_test_image(); + + // Generate unique domain name for this test + let domain_name = format!( + "test-itype-{}", + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs() + ); + + println!( + "Testing libvirt run with instancetype for domain: {}", + domain_name + ); + + // Cleanup any existing domain with this name + cleanup_domain(&domain_name); + + // Create domain with instancetype + println!("Creating libvirt domain with instancetype u1.small..."); + let create_output = run_bcvk(&[ + "libvirt", + "run", + "--name", + &domain_name, + "--label", + LIBVIRT_INTEGRATION_TEST_LABEL, + "--itype", + "u1.small", + "--filesystem", + "ext4", + &test_image, + ]) + .expect("Failed to run libvirt run"); + + println!("Create stdout: {}", create_output.stdout); + println!("Create stderr: {}", create_output.stderr); + + if !create_output.success() { + cleanup_domain(&domain_name); + panic!( + "Failed to create domain with instancetype: {}", + create_output.stderr + ); + } + + println!("Successfully created domain: {}", domain_name); + + // Inspect the domain to verify instancetype was set + let inspect_output = run_bcvk(&["libvirt", "inspect", "--format", "xml", &domain_name]) + .expect("Failed to run libvirt inspect"); + + let inspect_stdout = inspect_output.stdout; + println!("Inspect output: {}", inspect_stdout); + + // Parse XML to verify memory and vcpus match u1.small (1 vcpu, 2048 MB) + let dom = parse_xml_dom(&inspect_stdout).expect("Failed to parse domain XML"); + + // Check vCPUs (should be 1 for u1.small) + let vcpu_node = dom.find("vcpu").expect("vcpu element not found"); + let vcpus: u32 = vcpu_node.text.parse().expect("Failed to parse vcpu count"); + assert_eq!(vcpus, 1, "u1.small should have 1 vCPU, got {}", vcpus); + println!("✓ vCPUs correctly set to: {}", vcpus); + + // Check memory (should be 2048 MB = 2097152 KB for u1.small) + let memory_node = dom.find("memory").expect("memory element not found"); + let memory_kb: u64 = memory_node.text.parse().expect("Failed to parse memory"); + let memory_mb = memory_kb / 1024; + assert_eq!( + memory_mb, 2048, + "u1.small should have 2048 MB, got {} MB", + memory_mb + ); + println!("✓ Memory correctly set to: {} MB", memory_mb); + + // Cleanup domain + cleanup_domain(&domain_name); + + println!("✓ libvirt run with instancetype test passed"); + Ok(()) +} + /// Helper function to cleanup domain fn cleanup_domain(domain_name: &str) { println!("Cleaning up domain: {}", domain_name); diff --git a/crates/integration-tests/src/tests/run_ephemeral.rs b/crates/integration-tests/src/tests/run_ephemeral.rs index b08b93b..bdff147 100644 --- a/crates/integration-tests/src/tests/run_ephemeral.rs +++ b/crates/integration-tests/src/tests/run_ephemeral.rs @@ -228,3 +228,107 @@ fn test_run_ephemeral_container_ssh_access() -> Result<()> { assert!(ssh_output.stdout.contains("SSH_TEST_SUCCESS")); Ok(()) } + +#[distributed_slice(INTEGRATION_TESTS)] +static TEST_RUN_EPHEMERAL_WITH_INSTANCETYPE: IntegrationTest = IntegrationTest::new( + "run_ephemeral_with_instancetype", + test_run_ephemeral_with_instancetype, +); + +fn test_run_ephemeral_with_instancetype() -> Result<()> { + // Test u1.nano: 1 vCPU, 512 MiB memory + // Calculate physical memory from /sys/firmware/memmap (System RAM regions) + let script = "/bin/sh -c 'echo CPUs:$(grep -c ^processor /proc/cpuinfo); total=0; for dir in /sys/firmware/memmap/*; do type=$(cat \"$dir/type\" 2>/dev/null); if [ \"$type\" = \"System RAM\" ]; then start=$(cat \"$dir/start\"); end=$(cat \"$dir/end\"); start_dec=$((start)); end_dec=$((end)); size=$((end_dec - start_dec + 1)); total=$((total + size)); fi; done; total_kb=$((total / 1024)); echo PhysicalMemKB:$total_kb'"; + + let output = run_bcvk(&[ + "ephemeral", + "run", + "--rm", + "--label", + INTEGRATION_TEST_LABEL, + "--itype", + "u1.nano", + "--execute", + script, + &get_test_image(), + ])?; + + output.assert_success("ephemeral run with instance type u1.nano"); + + // Verify vCPUs (should be 1) + assert!( + output.stdout.contains("CPUs:1"), + "Expected 1 vCPU for u1.nano, output: {}", + output.stdout + ); + + // Verify physical memory (should be exactly 512 MiB = 524288 kB) + let mem_line = output + .stdout + .lines() + .find(|line| line.contains("PhysicalMemKB:")) + .expect("PhysicalMemKB line not found in output"); + + let mem_kb: u32 = mem_line + .split(':') + .nth(1) + .expect("Could not parse PhysicalMemKB") + .trim() + .parse() + .expect("Could not parse PhysicalMemKB as number"); + + // Physical memory should be close to 512 MiB = 524288 kB + // QEMU reserves small memory regions (BIOS, VGA, ACPI, etc.) so actual may be slightly less + // Allow 1% tolerance to account for hypervisor overhead + let expected_kb = 512 * 1024; + let tolerance_kb = expected_kb / 100; // 1% tolerance + let diff = if mem_kb > expected_kb { + mem_kb - expected_kb + } else { + expected_kb - mem_kb + }; + + assert!( + diff <= tolerance_kb, + "Expected physical memory ~{} kB for u1.nano, got {} kB (diff: {} kB, max allowed: {} kB [1%])", + expected_kb, mem_kb, diff, tolerance_kb + ); + + Ok(()) +} + +#[distributed_slice(INTEGRATION_TESTS)] +static TEST_RUN_EPHEMERAL_INSTANCETYPE_INVALID: IntegrationTest = IntegrationTest::new( + "run_ephemeral_instancetype_invalid", + test_run_ephemeral_instancetype_invalid, +); + +fn test_run_ephemeral_instancetype_invalid() -> Result<()> { + let output = run_bcvk(&[ + "ephemeral", + "run", + "--rm", + "--label", + INTEGRATION_TEST_LABEL, + "--itype", + "invalid.type", + "--karg", + "systemd.unit=poweroff.target", + &get_test_image(), + ])?; + + // Should fail with invalid instance type + assert!( + !output.success(), + "Expected failure with invalid instance type, but succeeded" + ); + + // Error message should mention the invalid type + assert!( + output.stderr.contains("invalid.type") || output.stderr.contains("Unknown instance type"), + "Error message should mention invalid instance type: {}", + output.stderr + ); + + Ok(()) +} diff --git a/crates/kit/src/instancetypes.rs b/crates/kit/src/instancetypes.rs new file mode 100644 index 0000000..edaaf3d --- /dev/null +++ b/crates/kit/src/instancetypes.rs @@ -0,0 +1,146 @@ +//! KubeVirt common-instancetypes support +//! +//! This module vendors the KubeVirt common-instancetypes definitions, +//! specifically the U series (Universal/General Purpose) instance types. +//! These provide standardized VM sizing with predefined vCPU and memory +//! configurations. +//! +//! Instance types follow the format: u1.{size} +//! Examples: u1.nano, u1.micro, u1.small, u1.medium, u1.large, etc. +//! +//! Source: https://github.com/kubevirt/common-instancetypes + +/// Instance type variants with associated vCPU and memory specifications +/// +/// Source: https://github.com/kubevirt/common-instancetypes/blob/main/instancetypes/u/1/sizes.yaml +#[derive( + Debug, + Clone, + Copy, + PartialEq, + Eq, + serde::Serialize, + serde::Deserialize, + strum::Display, + strum::EnumString, + strum::EnumIter, +)] +#[non_exhaustive] +pub enum InstanceType { + /// u1.nano - 1 vCPU, 512 MiB memory + #[strum(serialize = "u1.nano")] + U1Nano, + /// u1.micro - 1 vCPU, 1 GiB memory + #[strum(serialize = "u1.micro")] + U1Micro, + /// u1.small - 1 vCPU, 2 GiB memory + #[strum(serialize = "u1.small")] + U1Small, + /// u1.medium - 1 vCPU, 4 GiB memory + #[strum(serialize = "u1.medium")] + U1Medium, + /// u1.2xmedium - 2 vCPU, 4 GiB memory + #[strum(serialize = "u1.2xmedium")] + U1TwoXMedium, + /// u1.large - 2 vCPU, 8 GiB memory + #[strum(serialize = "u1.large")] + U1Large, + /// u1.xlarge - 4 vCPU, 16 GiB memory + #[strum(serialize = "u1.xlarge")] + U1XLarge, + /// u1.2xlarge - 8 vCPU, 32 GiB memory + #[strum(serialize = "u1.2xlarge")] + U1TwoXLarge, + /// u1.4xlarge - 16 vCPU, 64 GiB memory + #[strum(serialize = "u1.4xlarge")] + U1FourXLarge, + /// u1.8xlarge - 32 vCPU, 128 GiB memory + #[strum(serialize = "u1.8xlarge")] + U1EightXLarge, +} + +impl InstanceType { + /// Get the number of vCPUs for this instance type + pub const fn vcpus(self) -> u32 { + match self { + Self::U1Nano => 1, + Self::U1Micro => 1, + Self::U1Small => 1, + Self::U1Medium => 1, + Self::U1TwoXMedium => 2, + Self::U1Large => 2, + Self::U1XLarge => 4, + Self::U1TwoXLarge => 8, + Self::U1FourXLarge => 16, + Self::U1EightXLarge => 32, + } + } + + /// Get the memory in megabytes for this instance type + pub const fn memory_mb(self) -> u32 { + match self { + Self::U1Nano => 512, + Self::U1Micro => 1024, + Self::U1Small => 2048, + Self::U1Medium => 4096, + Self::U1TwoXMedium => 4096, + Self::U1Large => 8192, + Self::U1XLarge => 16384, + Self::U1TwoXLarge => 32768, + Self::U1FourXLarge => 65536, + Self::U1EightXLarge => 131072, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::str::FromStr; + use strum::IntoEnumIterator; + + #[test] + fn test_properties() { + for variant in InstanceType::iter() { + let (expected_vcpus, expected_memory_mb) = match variant { + InstanceType::U1Nano => (1, 512), + InstanceType::U1Micro => (1, 1024), + InstanceType::U1Small => (1, 2048), + InstanceType::U1Medium => (1, 4096), + InstanceType::U1TwoXMedium => (2, 4096), + InstanceType::U1Large => (2, 8192), + InstanceType::U1XLarge => (4, 16384), + InstanceType::U1TwoXLarge => (8, 32768), + InstanceType::U1FourXLarge => (16, 65536), + InstanceType::U1EightXLarge => (32, 131072), + }; + assert_eq!( + variant.vcpus(), + expected_vcpus, + "Mismatch in vcpus for {:?}", + variant + ); + assert_eq!( + variant.memory_mb(), + expected_memory_mb, + "Mismatch in memory_mb for {:?}", + variant + ); + } + } + + #[test] + fn test_parse_invalid_instancetype() { + let result = InstanceType::from_str("invalid"); + assert!(result.is_err()); + } + + #[test] + fn test_roundtrip() { + for variant in InstanceType::iter() { + let s = variant.to_string(); + let parsed = InstanceType::from_str(&s).unwrap(); + assert_eq!(parsed, variant); + } + } +} diff --git a/crates/kit/src/libvirt/base_disks_cli.rs b/crates/kit/src/libvirt/base_disks_cli.rs index 35a2a48..1771d2f 100644 --- a/crates/kit/src/libvirt/base_disks_cli.rs +++ b/crates/kit/src/libvirt/base_disks_cli.rs @@ -116,6 +116,11 @@ fn run_list(connect_uri: Option<&str>, opts: ListOpts) -> Result<()> { "YAML format is not supported for base-disks list command" )) } + OutputFormat::Xml => { + return Err(color_eyre::eyre::eyre!( + "XML format is not supported for base-disks list command" + )) + } } Ok(()) diff --git a/crates/kit/src/libvirt/inspect.rs b/crates/kit/src/libvirt/inspect.rs index 7f6187c..a96dfb7 100644 --- a/crates/kit/src/libvirt/inspect.rs +++ b/crates/kit/src/libvirt/inspect.rs @@ -59,6 +59,23 @@ pub fn run(global_opts: &crate::libvirt::LibvirtOptions, opts: LibvirtInspectOpt .with_context(|| "Failed to serialize VM as JSON")? ); } + OutputFormat::Xml => { + // Output raw domain XML using virsh dumpxml + let mut cmd = global_opts.virsh_command(); + cmd.args(["dumpxml", &opts.name]); + let output = cmd + .output() + .with_context(|| format!("Failed to run virsh dumpxml for {}", opts.name))?; + + if !output.status.success() { + return Err(color_eyre::eyre::eyre!( + "Failed to get domain XML: {}", + String::from_utf8_lossy(&output.stderr) + )); + } + + print!("{}", String::from_utf8_lossy(&output.stdout)); + } OutputFormat::Table => { return Err(color_eyre::eyre::eyre!( "Table format is not supported for inspect command" diff --git a/crates/kit/src/libvirt/list.rs b/crates/kit/src/libvirt/list.rs index 30033c5..6ecb00c 100644 --- a/crates/kit/src/libvirt/list.rs +++ b/crates/kit/src/libvirt/list.rs @@ -143,6 +143,11 @@ pub fn run(global_opts: &crate::libvirt::LibvirtOptions, opts: LibvirtListOpts) "YAML format is not supported for list command" )) } + OutputFormat::Xml => { + return Err(color_eyre::eyre::eyre!( + "XML format is not supported for list command" + )) + } } Ok(()) } diff --git a/crates/kit/src/libvirt/mod.rs b/crates/kit/src/libvirt/mod.rs index df89e49..ce27b0e 100644 --- a/crates/kit/src/libvirt/mod.rs +++ b/crates/kit/src/libvirt/mod.rs @@ -15,6 +15,7 @@ pub enum OutputFormat { Table, Json, Yaml, + Xml, } /// Default memory allocation for libvirt VMs diff --git a/crates/kit/src/libvirt/run.rs b/crates/kit/src/libvirt/run.rs index 28edb4f..8fa1cf0 100644 --- a/crates/kit/src/libvirt/run.rs +++ b/crates/kit/src/libvirt/run.rs @@ -174,10 +174,16 @@ pub struct LibvirtRunOpts { #[clap(long)] pub name: Option, + #[clap( + long, + help = "Instance type (e.g., u1.nano, u1.small, u1.medium). Overrides cpus/memory if specified." + )] + pub itype: Option, + #[clap(flatten)] pub memory: MemoryOpts, - /// Number of virtual CPUs for the VM + /// Number of virtual CPUs for the VM (overridden by --itype if specified) #[clap(long, default_value = "2")] pub cpus: u32, @@ -263,6 +269,24 @@ impl LibvirtRunOpts { } Ok(()) } + + /// Get resolved memory in MB, using instancetype if specified + pub fn resolved_memory_mb(&self) -> Result { + if let Some(itype) = self.itype { + Ok(itype.memory_mb()) + } else { + parse_memory_to_mb(&self.memory.memory) + } + } + + /// Get resolved CPU count, using instancetype if specified + pub fn resolved_cpus(&self) -> Result { + if let Some(itype) = self.itype { + Ok(itype.vcpus()) + } else { + Ok(self.cpus) + } + } } /// Execute the libvirt run command @@ -334,11 +358,17 @@ pub fn run(global_opts: &crate::libvirt::LibvirtOptions, opts: LibvirtRunOpts) - // VM is now managed by libvirt, no need to track separately + let resolved_memory = opts.resolved_memory_mb()?; + let resolved_cpus = opts.resolved_cpus()?; + println!("VM '{}' created successfully!", vm_name); println!(" Image: {}", opts.image); println!(" Disk: {}", disk_path); - println!(" Memory: {}", opts.memory.memory); - println!(" CPUs: {}", opts.cpus); + if let Some(ref itype) = opts.itype { + println!(" Instance Type: {}", itype); + } + println!(" Memory: {} MiB", resolved_memory); + println!(" CPUs: {}", resolved_cpus); // Display volume mount information if any if !opts.raw_volumes.is_empty() { @@ -924,7 +954,8 @@ fn create_libvirt_domain_from_disk( // Generate SMBIOS credentials for storage opts unit (handles /etc/environment for PAM/SSH) let storage_opts_creds = crate::sshcred::smbios_creds_for_storage_opts()?; - let memory = parse_memory_to_mb(&opts.memory.memory)?; + let memory = opts.resolved_memory_mb()?; + let cpus = opts.resolved_cpus()?; // Setup secure boot if requested let secure_boot_config = if let Some(keys) = opts.secure_boot_keys.as_deref() { @@ -943,15 +974,15 @@ fn create_libvirt_domain_from_disk( let mut domain_builder = DomainBuilder::new() .with_name(domain_name) .with_memory(memory.into()) - .with_vcpus(opts.cpus) + .with_vcpus(cpus) .with_disk(disk_path.as_str()) .with_transient_disk(opts.transient) .with_network("none") // Use QEMU args for SSH networking instead .with_firmware(opts.firmware) .with_tpm(!opts.disable_tpm) .with_metadata("bootc:source-image", &opts.image) - .with_metadata("bootc:memory-mb", &opts.memory.to_string()) - .with_metadata("bootc:vcpus", &opts.cpus.to_string()) + .with_metadata("bootc:memory-mb", &memory.to_string()) + .with_metadata("bootc:vcpus", &cpus.to_string()) .with_metadata("bootc:disk-size-gb", &opts.disk_size.to_string()) .with_metadata( "bootc:filesystem", @@ -966,6 +997,11 @@ fn create_libvirt_domain_from_disk( .with_metadata("bootc:ssh-port", &ssh_port.to_string()) .with_metadata("bootc:image-digest", image_digest); + // Add instance type metadata if specified + if let Some(itype) = opts.itype { + domain_builder = domain_builder.with_metadata("bootc:instance-type", &itype.to_string()); + } + // Add labels if specified if !opts.label.is_empty() { let labels = opts.label.join(","); diff --git a/crates/kit/src/main.rs b/crates/kit/src/main.rs index 815f092..a3fefbc 100644 --- a/crates/kit/src/main.rs +++ b/crates/kit/src/main.rs @@ -19,6 +19,7 @@ mod ephemeral; mod hostexec; mod images; mod install_options; +mod instancetypes; mod libvirt; mod libvirt_upload_disk; #[allow(dead_code)] diff --git a/crates/kit/src/run_ephemeral.rs b/crates/kit/src/run_ephemeral.rs index f1d1578..9c8dba5 100644 --- a/crates/kit/src/run_ephemeral.rs +++ b/crates/kit/src/run_ephemeral.rs @@ -166,10 +166,16 @@ pub struct CommonPodmanOptions { /// Common VM configuration options for hardware, networking, and features. #[derive(Parser, Debug, Clone, Default, Serialize, Deserialize)] pub struct CommonVmOpts { + #[clap( + long, + help = "Instance type (e.g., u1.nano, u1.small, u1.medium). Overrides vcpus/memory if specified." + )] + pub itype: Option, + #[clap(flatten)] pub memory: MemoryOpts, - #[clap(long, help = "Number of vCPUs")] + #[clap(long, help = "Number of vCPUs (overridden by --itype if specified)")] pub vcpus: Option, #[clap(long, help = "Enable console output to terminal for debugging")] @@ -203,14 +209,22 @@ pub struct CommonVmOpts { } impl CommonVmOpts { - /// Parse memory specification to MB + /// Parse memory specification to MB, using instancetype if specified pub fn memory_mb(&self) -> color_eyre::Result { - crate::utils::parse_memory_to_mb(&self.memory.memory) + if let Some(itype) = self.itype { + Ok(itype.memory_mb()) + } else { + crate::utils::parse_memory_to_mb(&self.memory.memory) + } } - /// Get vCPU count - pub fn vcpus(&self) -> u32 { - self.vcpus.unwrap_or_else(default_vcpus) + /// Get vCPU count, using instancetype if specified + pub fn vcpus(&self) -> color_eyre::Result { + if let Some(itype) = self.itype { + Ok(itype.vcpus()) + } else { + Ok(self.vcpus.unwrap_or_else(default_vcpus)) + } } } @@ -988,7 +1002,7 @@ StandardOutput=file:/dev/virtio-ports/executestatus // Configure qemu let mut qemu_config = crate::qemu::QemuConfig::new_direct_boot( opts.common.memory_mb()?, - opts.common.vcpus(), + opts.common.vcpus()?, "/run/qemu/kernel".to_string(), "/run/qemu/initramfs".to_string(), main_virtiofsd_config.socket_path.clone(), diff --git a/docs/src/man/bcvk-ephemeral-run-ssh.md b/docs/src/man/bcvk-ephemeral-run-ssh.md index f9e22db..0a4cee1 100644 --- a/docs/src/man/bcvk-ephemeral-run-ssh.md +++ b/docs/src/man/bcvk-ephemeral-run-ssh.md @@ -23,6 +23,10 @@ Run ephemeral VM and SSH into it SSH command to execute (optional, defaults to interactive shell) +**--itype**=*ITYPE* + + Instance type (e.g., u1.nano, u1.small, u1.medium). Overrides vcpus/memory if specified. + **--memory**=*MEMORY* Memory size (e.g. 4G, 2048M, or plain number for MB) @@ -31,7 +35,7 @@ Run ephemeral VM and SSH into it **--vcpus**=*VCPUS* - Number of vCPUs + Number of vCPUs (overridden by --itype if specified) **--console** diff --git a/docs/src/man/bcvk-ephemeral-run.md b/docs/src/man/bcvk-ephemeral-run.md index 4134843..91b29a9 100644 --- a/docs/src/man/bcvk-ephemeral-run.md +++ b/docs/src/man/bcvk-ephemeral-run.md @@ -49,6 +49,10 @@ This design allows bcvk to provide VM-like isolation and boot behavior while lev This argument is required. +**--itype**=*ITYPE* + + Instance type (e.g., u1.nano, u1.small, u1.medium). Overrides vcpus/memory if specified. + **--memory**=*MEMORY* Memory size (e.g. 4G, 2048M, or plain number for MB) @@ -57,7 +61,7 @@ This design allows bcvk to provide VM-like isolation and boot behavior while lev **--vcpus**=*VCPUS* - Number of vCPUs + Number of vCPUs (overridden by --itype if specified) **--console** diff --git a/docs/src/man/bcvk-libvirt-inspect.md b/docs/src/man/bcvk-libvirt-inspect.md index d38ac67..94178b4 100644 --- a/docs/src/man/bcvk-libvirt-inspect.md +++ b/docs/src/man/bcvk-libvirt-inspect.md @@ -27,6 +27,7 @@ Show detailed information about a libvirt domain - table - json - yaml + - xml Default: yaml diff --git a/docs/src/man/bcvk-libvirt-list.md b/docs/src/man/bcvk-libvirt-list.md index 4db5ad5..33827ee 100644 --- a/docs/src/man/bcvk-libvirt-list.md +++ b/docs/src/man/bcvk-libvirt-list.md @@ -33,6 +33,7 @@ When using `--format=json` with a specific domain name, the output is a single J - table - json - yaml + - xml Default: table diff --git a/docs/src/man/bcvk-libvirt-run.md b/docs/src/man/bcvk-libvirt-run.md index 1db781f..e364aca 100644 --- a/docs/src/man/bcvk-libvirt-run.md +++ b/docs/src/man/bcvk-libvirt-run.md @@ -23,6 +23,10 @@ Run a bootable container as a persistent VM Name for the VM (auto-generated if not specified) +**--itype**=*ITYPE* + + Instance type (e.g., u1.nano, u1.small, u1.medium). Overrides cpus/memory if specified. + **--memory**=*MEMORY* Memory size (e.g. 4G, 2048M, or plain number for MB) @@ -31,7 +35,7 @@ Run a bootable container as a persistent VM **--cpus**=*CPUS* - Number of virtual CPUs for the VM + Number of virtual CPUs for the VM (overridden by --itype if specified) Default: 2 diff --git a/docs/src/man/bcvk-to-disk.md b/docs/src/man/bcvk-to-disk.md index c6209f5..069b44f 100644 --- a/docs/src/man/bcvk-to-disk.md +++ b/docs/src/man/bcvk-to-disk.md @@ -69,6 +69,10 @@ The installation process: Default: raw +**--itype**=*ITYPE* + + Instance type (e.g., u1.nano, u1.small, u1.medium). Overrides vcpus/memory if specified. + **--memory**=*MEMORY* Memory size (e.g. 4G, 2048M, or plain number for MB) @@ -77,7 +81,7 @@ The installation process: **--vcpus**=*VCPUS* - Number of vCPUs + Number of vCPUs (overridden by --itype if specified) **--console**