flowey_hvlite/pipelines/
vmm_tests_run_target.rs1use crate::pipelines::vmm_tests_run::VmmTestTargetCli;
7use crate::pipelines::vmm_tests_run::resolve_incubator;
8use crate::pipelines::vmm_tests_run::resolve_target;
9use anyhow::Context;
10use flowey::node::prelude::ReadVar;
11use flowey::pipeline::prelude::*;
12use flowey_lib_hvlite::init_vmm_tests_env::PetriParams;
13use flowey_lib_hvlite::install_vmm_tests_external_deps::VmmTestsExternalDeps;
14use flowey_lib_hvlite::install_vmm_tests_external_deps::VmmTestsExternalDepsLinux;
15use flowey_lib_hvlite::install_vmm_tests_external_deps::VmmTestsExternalDepsWindows;
16use std::num::NonZeroU64;
17use std::path::PathBuf;
18use vmm_test_images::KnownTestArtifacts;
19
20#[derive(clap::Args)]
22pub struct VmmTestsRunTargetCli {
23 #[clap(long)]
27 target: Option<VmmTestTargetCli>,
28
29 #[clap(long)]
31 dir: PathBuf,
32
33 #[clap(long, default_value = "all()")]
35 filter: String,
36
37 #[clap(long, value_delimiter = ',')]
39 artifacts: Vec<KnownTestArtifacts>,
40
41 #[clap(long, value_delimiter = ',')]
43 prep_steps: Vec<String>,
44
45 #[clap(long)]
47 verbose: bool,
48
49 #[clap(long)]
51 install_missing_deps: bool,
52
53 #[clap(long)]
55 skip_vhd_prompt: bool,
56
57 #[clap(long)]
59 ci_profile: bool,
60
61 #[clap(long)]
64 no_reuse_prepped_vhds: bool,
65
66 #[clap(long)]
68 needs_hardware_isolation: bool,
69
70 #[clap(long)]
72 needs_igvm_agent: bool,
73
74 #[clap(long)]
76 repetitions: Option<u64>,
77
78 #[clap(long, num_args = 0..=1)]
80 #[expect(clippy::option_option)]
81 incubator: Option<Option<PathBuf>>,
82}
83
84impl IntoPipeline for VmmTestsRunTargetCli {
85 fn into_pipeline(self, backend_hint: PipelineBackendHint) -> anyhow::Result<Pipeline> {
86 if !matches!(backend_hint, PipelineBackendHint::Local) {
87 anyhow::bail!("vmm-tests-run-target is for local use only")
88 }
89
90 let Self {
91 target,
92 dir,
93 filter,
94 artifacts,
95 prep_steps,
96 verbose,
97 install_missing_deps,
98 skip_vhd_prompt,
99 ci_profile,
100 no_reuse_prepped_vhds,
101 needs_hardware_isolation,
102 needs_igvm_agent,
103 repetitions,
104 incubator,
105 } = self;
106
107 if incubator.is_some() && target.is_none() {
110 anyhow::bail!("--incubator requires --target (e.g., --target linux-aarch64-musl)");
111 }
112
113 let repetitions =
114 NonZeroU64::new(repetitions.unwrap_or(1)).context("repetitions must not be zero")?;
115
116 let target = resolve_target(target, backend_hint)?;
117
118 let incubator_profile = incubator
119 .map(|i| resolve_incubator(i, &target))
120 .transpose()?;
121
122 let external_deps = match target.as_triple().operating_system {
123 target_lexicon::OperatingSystem::Windows => {
124 VmmTestsExternalDeps::Windows(VmmTestsExternalDepsWindows {
125 hyperv: true, whp: true, hardware_isolation: needs_hardware_isolation,
128 })
129 }
130 target_lexicon::OperatingSystem::Linux => {
131 VmmTestsExternalDeps::Linux(VmmTestsExternalDepsLinux {
132 hugetlb_2mb_overcommit_pages: None, prepare_vhost_vsock: false, })
135 }
136 _ => unreachable!(),
137 };
138
139 let mut pipeline = Pipeline::new();
140
141 let mut job = pipeline.new_job(
142 FlowPlatform::host(backend_hint),
143 FlowArch::host(backend_hint),
144 "run vmm tests on target system",
145 );
146
147 job = job.dep_on(|_| flowey_lib_hvlite::_jobs::cfg_versions::Request::Init);
148
149 job = job
150 .dep_on(|_| flowey_lib_hvlite::_jobs::cfg_common::Params {
151 local_only: Some(flowey_lib_hvlite::_jobs::cfg_common::LocalOnlyParams {
152 interactive: true,
153 auto_install: install_missing_deps,
154 ignore_rust_version: true,
155 }),
156 verbose: ReadVar::from_static(verbose),
157 locked: false,
158 deny_warnings: false,
159 no_incremental: false,
160 })
161 .dep_on(
162 |ctx| flowey_lib_hvlite::_jobs::local_run_nextest_vmm_tests::Params {
163 target,
164 test_content_dir: dir,
165 filter,
166 downloaded_artifacts: artifacts,
167 external_deps,
168 prep_steps_variants: prep_steps,
169 needs_test_igvm_agent_rpc_server: needs_igvm_agent,
170 skip_vhd_prompt,
171 nextest_profile: if ci_profile {
172 flowey_lib_hvlite::run_cargo_nextest_run::NextestProfile::Ci
173 } else {
174 flowey_lib_hvlite::run_cargo_nextest_run::NextestProfile::Default
175 },
176 petri_params: PetriParams {
177 disable_remote_artifacts: false,
178 reuse_prepped_vhds: !no_reuse_prepped_vhds,
179 require_2mb_hugetlb: false, },
181 repetitions,
182 incubator_profile,
183 done: ctx.new_done_handle(),
184 },
185 );
186
187 job.finish();
188
189 Ok(pipeline)
190 }
191}