Skip to content
Open
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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7395,6 +7395,7 @@ dependencies = [
"fs-err",
"gptman",
"guid",
"mesh",
"openvmm_defs",
"openvmm_helpers",
"pal_async",
Expand Down
1 change: 1 addition & 0 deletions vmm_tests/prep_steps/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition.workspace = true
rust-version.workspace = true

[dependencies]
mesh.workspace = true
openvmm_defs.workspace = true
openvmm_helpers.workspace = true
petri.workspace = true
Expand Down
74 changes: 55 additions & 19 deletions vmm_tests/prep_steps/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

#![forbid(unsafe_code)]

use anyhow::Context;
use mesh::rpc::RpcSend;
use pal_async::DefaultPool;
use petri::ArtifactResolver;
use petri::BootImageConfig;
Expand Down Expand Up @@ -323,18 +325,19 @@ async fn run_no_vmbus(
Ok(())
}

/// Boot a prep VM with a target disk attached as a second SCSI controller.
/// Boot the source Windows image, then attach the target on a second SCSI controller.
///
/// The target disk is exposed to the guest as drive E:. Returns the running
/// VM and pipette agent.
/// This prevents firmware from booting the target and lets Windows mount the
/// pipette disk at D: before the target arrives at E:.
Comment thread
maheeraeron marked this conversation as resolved.
Resolved
async fn boot_vm_with_target_disk(
driver: &pal_async::DefaultDriver,
name: &str,
logger: &PetriLogSource,
artifacts: PetriVmArtifacts<OpenVmmPetriBackend>,
target_disk: vm_resource::Resource<vm_resource::kind::DiskHandleKind>,
) -> anyhow::Result<(petri::PetriVm<OpenVmmPetriBackend>, PipetteClient)> {
PetriVmBuilder::new(
let (requests, recv) = mesh::channel();
let (vm, agent) = PetriVmBuilder::new(
PetriTestParams {
test_name: name,
log_source: logger,
Expand All @@ -353,28 +356,61 @@ async fn boot_vm_with_target_disk(
instance_id: guid::guid!("766e96f8-2ceb-437e-afe3-a93169e48aff"),
max_sub_channel_count: 1,
io_queue_depth: None,
devices: vec![storvsp_resources::ScsiDeviceAndPath {
path: storvsp_resources::ScsiPath {
path: 0,
target: 0,
lun: 0,
},
device: scsidisk_resources::SimpleScsiDiskHandle {
read_only: false,
parameters: Default::default(),
disk: target_disk,
}
.into_resource(),
}],
requests: None,
devices: Vec::new(),
requests: Some(recv),
poll_mode_queue_depth: None,
}
.into_resource(),
))
})
})
.run()
.await
.await?;
requests
.call_failable(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since we have the delayed mount, I don't think we need any of this other stuff. Windows should letter the drives in order of discovery.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Implemented, lets see if that works in CI

storvsp_resources::ScsiControllerRequest::AddDevice,
storvsp_resources::ScsiDeviceAndPath {
path: storvsp_resources::ScsiPath {
path: 0,
target: 0,
lun: 0,
},
device: scsidisk_resources::SimpleScsiDiskHandle {
read_only: false,
parameters: Default::default(),
disk: target_disk,
}
.into_resource(),
},
)
.await
.context("failed to attach the offline target disk")?;
tracing::info!("Attached target disk after the source Windows image booted");

let shell = agent.windows_shell();
for _ in 0..30 {
let output = cmd!(shell, "cmd.exe")
.args([
"/d",
"/c",
r"if exist E:\Windows\System32\config\SYSTEM (exit /b 0) else (exit /b 1)",
Comment thread
maheeraeron marked this conversation as resolved.
Resolved
])
.ignore_status()
.output()
.await?;
if output.status.success() {
return Ok((vm, agent));
}
anyhow::ensure!(
output.status.code() == Some(1),
"target-volume check failed: {}",
output.status
);
pal_async::timer::PolledTimer::new(driver)
.sleep(std::time::Duration::from_secs(1))
.await;
}
anyhow::bail!("target Windows volume did not appear at E: within 30 seconds")
}

/// Copy the IMC hive's pipette service registration into the target disk's
Expand Down
Loading