diff --git a/cli/src/vm_commands.rs b/cli/src/vm_commands.rs index dc8453d..378dcf2 100644 --- a/cli/src/vm_commands.rs +++ b/cli/src/vm_commands.rs @@ -62,6 +62,9 @@ pub enum VmCommand { #[arg(long, help = "Enable hugepages for memory allocation")] hugepages: bool, + + #[arg(long, help = "Path to ignition file or the content itself")] + ignition: Option, }, /// Start an existing virtual machine Start { @@ -126,6 +129,9 @@ pub enum VmCommand { #[arg(long, help = "Enable hugepages for memory allocation")] hugepages: bool, + + #[arg(long, help = "Path to ignition file or the content itself")] + ignition: Option, }, /// Watch virtual machine state change events Events { @@ -188,6 +194,17 @@ pub enum VmCommand { }, } +#[derive(Debug, Clone)] +struct CreateVmOptions { + image_ref: String, + vcpus: u32, + memory: u64, + vm_id: Option, + pci_devices: Vec, + hugepages: bool, + ignition: Option, +} + pub async fn handle_vm_command(args: VmArgs) -> Result<()> { let mut client = VmServiceClient::connect(args.address) .await @@ -201,17 +218,18 @@ pub async fn handle_vm_command(args: VmArgs) -> Result<()> { vm_id, pci_device, hugepages, + ignition, } => { - create_vm( - &mut client, + let opts = CreateVmOptions { image_ref, vcpus, memory, vm_id, - pci_device, + pci_devices: pci_device, hugepages, - ) - .await? + ignition, + }; + create_vm(&mut client, opts).await? } VmCommand::Start { vm_id } => start_vm(&mut client, vm_id).await?, VmCommand::Info { vm_id } => get_vm_info(&mut client, vm_id).await?, @@ -228,17 +246,18 @@ pub async fn handle_vm_command(args: VmArgs) -> Result<()> { vm_id, pci_device, hugepages, + ignition, } => { - create_and_start_vm( - &mut client, + let opts = CreateVmOptions { image_ref, vcpus, memory, vm_id, - pci_device, + pci_devices: pci_device, hugepages, - ) - .await? + ignition, + }; + create_and_start_vm(&mut client, opts).await? } VmCommand::Events { vm_id } => watch_events(&mut client, vm_id).await?, VmCommand::Console { vm_id } => console_vm(&mut client, vm_id).await?, @@ -273,18 +292,33 @@ pub async fn handle_vm_command(args: VmArgs) -> Result<()> { async fn create_and_start_vm( client: &mut VmServiceClient, - image_ref: String, - vcpus: u32, - memory: u64, - vm_id: Option, - pci_devices: Vec, - hugepages: bool, + opts: CreateVmOptions, ) -> Result<()> { + let CreateVmOptions { + image_ref, + vcpus, + memory, + vm_id, + pci_devices, + hugepages, + ignition, + } = opts; + println!("� Starting create and start operation for VM with image: {image_ref}"); // Step 1: Create the VM println!("� Step 1: Creating VM..."); + let ignition_data = if let Some(ignition_str) = ignition { + if tokio::fs::metadata(&ignition_str).await.is_ok() { + Some(tokio::fs::read_to_string(ignition_str).await?) + } else { + Some(ignition_str) + } + } else { + None + }; + let net_configs = pci_devices .iter() .map(|bdf| { @@ -310,6 +344,7 @@ async fn create_and_start_vm( }), image_ref: image_ref.clone(), net: net_configs, + ignition: ignition_data, ..Default::default() }), vm_id: vm_id.clone(), @@ -405,17 +440,29 @@ async fn wait_for_vm_state( anyhow::bail!("Event stream ended before reaching target state: {target_state:?}") } -async fn create_vm( - client: &mut VmServiceClient, - image_ref: String, - vcpus: u32, - memory: u64, - vm_id: Option, - pci_devices: Vec, - hugepages: bool, -) -> Result<()> { +async fn create_vm(client: &mut VmServiceClient, opts: CreateVmOptions) -> Result<()> { + let CreateVmOptions { + image_ref, + vcpus, + memory, + vm_id, + pci_devices, + hugepages, + ignition, + } = opts; + println!("Requesting VM creation with image: {image_ref}..."); + let ignition_data = if let Some(ignition_str) = ignition { + if tokio::fs::metadata(&ignition_str).await.is_ok() { + Some(tokio::fs::read_to_string(ignition_str).await?) + } else { + Some(ignition_str) + } + } else { + None + }; + let net_configs = pci_devices .into_iter() .map(|bdf| { @@ -439,6 +486,7 @@ async fn create_vm( }), image_ref, net: net_configs, + ignition: ignition_data, ..Default::default() }), vm_id, diff --git a/feos/services/vm-service/src/vmm/ch_adapter.rs b/feos/services/vm-service/src/vmm/ch_adapter.rs index b24d572..61b849e 100644 --- a/feos/services/vm-service/src/vmm/ch_adapter.rs +++ b/feos/services/vm-service/src/vmm/ch_adapter.rs @@ -214,6 +214,7 @@ impl CloudHypervisorAdapter { if let Some(ignition_data) = config.ignition { if !ignition_data.is_empty() { ch_vm_config.platform = Some(models::PlatformConfig { + num_pci_segments: Some(1), oem_strings: Some(vec![ignition_data]), ..Default::default() });