flowey_lib_hvlite/_jobs/
setup_and_run_vmm_perf.rs1use crate::build_openvmm::OpenvmmOutput;
7use crate::build_vmm_perf::VmmPerfOutput;
8use crate::common::CommonTriple;
9use crate::install_vmm_tests_external_deps::VmmTestsExternalDeps;
10use crate::install_vmm_tests_external_deps::VmmTestsExternalDepsLinux;
11use crate::install_vmm_tests_external_deps::VmmTestsExternalDepsWindows;
12use flowey::node::prelude::*;
13use std::collections::BTreeMap;
14
15flowey_request! {
16 pub struct Params {
17 pub label: String,
18 pub target: CommonTriple,
19 pub runner: ReadVar<VmmPerfOutput>,
20 pub openvmm: ReadVar<OpenvmmOutput>,
21 pub profiles: Vec<String>,
22 pub vm_sizes_json: Option<String>,
23 pub parameters_json: Option<String>,
24 pub runtime_archive: Option<ReadVar<PathBuf>>,
26 pub root_dir: Option<ReadVar<PathBuf>>,
28 pub hugetlb_2mb_overcommit_pages: Option<u64>,
29 pub done: WriteVar<SideEffect>,
30 }
31}
32
33new_simple_flow_node!(struct Node);
34
35impl SimpleFlowNode for Node {
36 type Request = Params;
37
38 fn imports(ctx: &mut ImportCtx<'_>) {
39 ctx.import::<crate::download_uefi_mu_msvm::Node>();
40 ctx.import::<crate::download_vmm_perf_runtime::Node>();
41 ctx.import::<crate::install_vmm_tests_external_deps::Node>();
42 ctx.import::<crate::run_vmm_perf::Node>();
43 ctx.import::<flowey_lib_common::publish_test_results::Node>();
44 }
45
46 fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
47 let Params {
48 label,
49 target,
50 runner,
51 openvmm,
52 profiles,
53 vm_sizes_json,
54 parameters_json,
55 runtime_archive,
56 root_dir,
57 hugetlb_2mb_overcommit_pages,
58 done,
59 } = request;
60
61 if root_dir.is_some() && !matches!(ctx.backend(), FlowBackend::Local) {
62 anyhow::bail!("custom VMM.Perf root directories are local-only");
63 }
64 if runtime_archive.is_some() && !matches!(ctx.backend(), FlowBackend::Local) {
65 anyhow::bail!("custom VMM.Perf runtime archives are local-only");
66 }
67
68 let external_deps = match ctx.platform() {
69 FlowPlatform::Windows => VmmTestsExternalDeps::Windows(VmmTestsExternalDepsWindows {
70 hyperv: true,
71 whp: true,
72 hardware_isolation: false,
73 }),
74 FlowPlatform::Linux(_) => VmmTestsExternalDeps::Linux(VmmTestsExternalDepsLinux {
75 hugetlb_2mb_overcommit_pages,
76 prepare_vhost_vsock: false,
77 }),
78 _ => anyhow::bail!("VMM.Perf is unsupported on this platform"),
79 };
80 ctx.config(crate::install_vmm_tests_external_deps::Config {
81 selections: Some(external_deps),
82 auto_install: None,
83 });
84 let pre_run_deps = vec![ctx.reqv(crate::install_vmm_tests_external_deps::Request::Install)];
85
86 let target_is_windows = matches!(
87 target.as_triple().operating_system,
88 target_lexicon::OperatingSystem::Windows
89 );
90 anyhow::ensure!(
91 target_is_windows == matches!(ctx.platform(), FlowPlatform::Windows),
92 "VMM.Perf target {target} does not match job platform {:?}",
93 ctx.platform()
94 );
95 let arch = target.common_arch()?;
96 let firmware = ctx.reqv(|v| crate::download_uefi_mu_msvm::Request::GetMsvmFd {
97 arch,
98 flavor: None,
99 msvm_fd: v,
100 });
101 let runtime_archive = match runtime_archive {
102 Some(runtime_archive) => runtime_archive,
103 None => ctx.reqv(|v| crate::download_vmm_perf_runtime::Request::Get {
104 arch,
105 runtime_archive: v,
106 }),
107 };
108 let job_root = match ctx.backend() {
109 FlowBackend::Local => root_dir
110 .ok_or_else(|| anyhow::anyhow!("local VMM.Perf runs require a root directory"))?,
111 FlowBackend::Ado => ctx
112 .get_ado_variable(AdoRuntimeVar::PIPELINE_WORKSPACE)
113 .map(ctx, |root| PathBuf::from(root).join("vp")),
114 FlowBackend::Github => ctx
115 .get_gh_context_var()
116 .global()
117 .runner_temp()
118 .map(ctx, |root| PathBuf::from(root).join("vp")),
119 };
120 let output_dir = job_root.clone().map(ctx, |root| root.join("results"));
121 let temp_dir = Some(job_root.map(ctx, |root| root.join("t")));
122
123 let result = ctx.reqv(|v| crate::run_vmm_perf::Request {
124 runner,
125 openvmm,
126 firmware,
127 runtime_archive,
128 output_dir,
129 temp_dir,
130 profiles,
131 vm_sizes_json,
132 parameters_json,
133 pre_run_deps,
134 output: v,
135 });
136
137 let publish_done = if matches!(ctx.backend(), FlowBackend::Local) {
138 result.clone().into_side_effect()
139 } else {
140 let results_dir = result.clone().map(ctx, |result| result.results_dir);
141 let test_results = result.clone().map(ctx, |result| {
142 flowey_lib_common::run_cargo_nextest_run::TestResults {
143 all_tests_passed: result.success,
144 junit_xml: None,
145 }
146 });
147 ctx.reqv(|v| flowey_lib_common::publish_test_results::Request {
148 test_results,
149 test_label: label,
150 attachments: BTreeMap::from([("results".into(), (results_dir, false))]),
151 output_dir: None,
152 upload_logs_on_success: true,
153 done: v,
154 })
155 };
156
157 ctx.emit_rust_step("report VMM.Perf result", |ctx| {
158 let result = result.claim(ctx);
159 publish_done.claim(ctx);
160 done.claim(ctx);
161 move |rt| {
162 let result = rt.read(result);
163 anyhow::ensure!(
164 result.success,
165 "VMM.Perf failed with exit code {}",
166 result
167 .exit_code
168 .map_or_else(|| "unknown".into(), |code| code.to_string())
169 );
170 Ok(())
171 }
172 });
173
174 Ok(())
175 }
176}