Skip to main content

flowey_lib_hvlite/
init_vmm_tests_content_dir.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Setup directory structure that the VMM tests require to run.
5
6use crate::build_flowey_hvlite::FloweyHvliteOutput;
7use crate::build_guest_test_uefi::GuestTestUefiOutput;
8use crate::build_incubator::IncubatorOutput;
9use crate::build_incubator::incubator_profile_dir;
10use crate::build_nextest_vmm_tests::NextestVmmTestsArchive;
11use crate::build_openhcl_igvm_from_recipe::OpenhclIgvmOutput;
12use crate::build_openvmm::OpenvmmOutput;
13use crate::build_openvmm_vhost::OpenvmmVhostOutput;
14use crate::build_pipette::PipetteOutput;
15use crate::build_prep_steps::PrepStepsOutput;
16use crate::build_test_igvm_agent_rpc_server::TestIgvmAgentRpcServerOutput;
17use crate::build_tmk_vmm::TmkVmmOutput;
18use crate::build_tmks::TmksOutput;
19use crate::build_tpm_guest_tests::TpmGuestTestsOutput;
20use crate::build_vmgstool::VmgstoolOutput;
21use crate::common::CommonArch;
22use crate::download_release_igvm_files_from_gh::OpenhclReleaseVersion;
23use flowey::node::prelude::*;
24
25#[macro_export]
26macro_rules! define_vmm_tests_built_artifacts {
27    (
28        $($artifact:ident => $output:ty),* $(,)?
29    ) => {
30        ::paste::paste! {
31            #[derive(Serialize, Deserialize, Default)]
32            pub struct VmmTestsBuiltArtifacts {
33                $(pub $artifact: Option<::flowey::node::prelude::ReadVar<$output>>,)*
34            }
35
36            #[derive(Serialize, Deserialize, Default)]
37            pub struct VmmTestsBuiltArtifactsWrite {
38                $(pub $artifact: Option<::flowey::node::prelude::WriteVar<$output>>,)*
39            }
40        }
41    };
42}
43
44define_vmm_tests_built_artifacts!(
45    // artifacts used at the pipeline level
46    flowey_hvlite => FloweyHvliteOutput,
47    nextest_vmm_tests_archive => NextestVmmTestsArchive,
48    incubator => IncubatorOutput,
49    prep_steps => PrepStepsOutput,
50    test_igvm_agent_rpc_server => TestIgvmAgentRpcServerOutput,
51    // artifacts used internally in petri
52    openvmm => OpenvmmOutput,
53    openvmm_vhost => OpenvmmVhostOutput,
54    pipette_windows => PipetteOutput,
55    pipette_linux_musl => PipetteOutput,
56    guest_test_uefi => GuestTestUefiOutput,
57    openhcl_standard => OpenhclIgvmOutput,
58    openhcl_standard_dev => OpenhclIgvmOutput,
59    openhcl_cvm => OpenhclIgvmOutput,
60    openhcl_linux_direct => OpenhclIgvmOutput,
61    tmks => TmksOutput,
62    tmk_vmm => TmkVmmOutput,
63    tmk_vmm_linux_musl => TmkVmmOutput,
64    vmgstool => VmgstoolOutput,
65    vmgstool_dev => VmgstoolOutput,
66    tpm_guest_tests_windows => TpmGuestTestsOutput,
67    tpm_guest_tests_linux => TpmGuestTestsOutput,
68);
69
70pub type ResolveVmmTestsBuiltArtifacts =
71    Box<dyn Fn(&mut flowey::pipeline::prelude::PipelineJobCtx<'_>) -> VmmTestsBuiltArtifacts>;
72
73#[macro_export]
74macro_rules! vmm_tests_built_artifacts_builder {
75    (
76        $name:ty,
77        (
78            $($artifact:ident => $output:ty),* $(,)?
79        )
80    ) => {
81        ::paste::paste! {
82            #[derive(Default, Clone)]
83            pub struct $name {
84                $(pub [<use_ $artifact>]: Option<::flowey::pipeline::prelude::UseTypedArtifact<$output>>,)*
85            }
86
87            impl $name {
88                pub fn finish(self) -> Result<$crate::init_vmm_tests_content_dir::ResolveVmmTestsBuiltArtifacts, &'static str> {
89                    let $name {
90                        $([<use_ $artifact>],)*
91                    } = self;
92
93                    $(let [<use_ $artifact>] = [<use_ $artifact>].ok_or(stringify!($artifact))?;)*
94
95                    Ok(Box::new(move |ctx| $crate::init_vmm_tests_content_dir::VmmTestsBuiltArtifacts {
96                        $($artifact: Some(ctx.use_typed_artifact(&[<use_ $artifact>])),)*
97                        .. Default::default()
98                    }))
99                }
100
101                pub fn pair(ctx: &mut ::flowey::node::prelude::NodeCtx<'_>) -> (
102                    $crate::init_vmm_tests_content_dir::VmmTestsBuiltArtifacts,
103                    $crate::init_vmm_tests_content_dir::VmmTestsBuiltArtifactsWrite,
104                ) {
105
106                    $(let ([<$artifact _read>], [<$artifact _write>]) = ctx.new_var();)*
107
108                    let built_artifacts_read = $crate::init_vmm_tests_content_dir::VmmTestsBuiltArtifacts {
109                        $($artifact: Some([<$artifact _read>]),)*
110                        .. Default::default()
111                    };
112
113                    let built_artifacts_write = $crate::init_vmm_tests_content_dir::VmmTestsBuiltArtifactsWrite {
114                        $($artifact: Some([<$artifact _write>]),)*
115                        .. Default::default()
116                    };
117
118                    (built_artifacts_read, built_artifacts_write)
119                }
120            }
121        }
122    };
123}
124
125flowey_request! {
126    pub struct Request {
127        /// Directory to symlink / copy test contents into. Does not need to be
128        /// empty.
129        pub test_content_dir: ReadVar<PathBuf>,
130        /// What triple VMM tests are built for.
131        ///
132        /// Used to detect cases of running Windows VMM tests via WSL2, and adjusting
133        /// reported paths appropriately.
134        pub vmm_tests_target: target_lexicon::Triple,
135        /// Artifacts used by the tests that are built in the openvmm repo
136        pub built_artifacts: VmmTestsBuiltArtifacts,
137        /// Copy files necessary to use the test content dir as a minimal repo root.
138        ///
139        /// This is useful for running tests on machines without a local clone.
140        pub is_repo_root: bool,
141        /// Whether the tests require that release igvm files are downloaded
142        pub needs_release_igvm: bool,
143        /// Whether to copy incubator profiles into the test content directory.
144        pub needs_incubator_profiles: bool,
145
146        pub done: WriteVar<SideEffect>
147    }
148}
149
150new_simple_flow_node!(struct Node);
151
152impl SimpleFlowNode for Node {
153    type Request = Request;
154
155    fn imports(ctx: &mut ImportCtx<'_>) {
156        ctx.import::<crate::resolve_openvmm_test_initrd::Node>();
157        ctx.import::<crate::resolve_openvmm_test_linux_kernel::Node>();
158        ctx.import::<crate::resolve_openvmm_test_virtio_win::Node>();
159        ctx.import::<crate::git_checkout_openvmm_repo::Node>();
160        ctx.import::<crate::download_uefi_mu_msvm::Node>();
161        ctx.import::<crate::download_release_igvm_files_from_gh::resolve::Node>();
162    }
163
164    fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
165        let Request {
166            test_content_dir,
167            vmm_tests_target,
168            built_artifacts,
169            is_repo_root,
170            needs_release_igvm,
171            needs_incubator_profiles,
172            done,
173        } = request;
174
175        let openvmm_repo_path =
176            is_repo_root.then(|| ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir));
177
178        let arch = CommonArch::from_architecture(vmm_tests_target.architecture)?;
179
180        let test_linux_initrd =
181            ctx.reqv(|v| crate::resolve_openvmm_test_initrd::Request::Get(arch, v));
182        let test_linux_kernel = ctx.reqv(|v| {
183            crate::resolve_openvmm_test_linux_kernel::Request::Get(
184                crate::resolve_openvmm_test_linux_kernel::OpenvmmTestKernelFile::Kernel,
185                arch,
186                crate::resolve_openvmm_test_linux_kernel::DEFAULT_LINUX_TEST_KERNEL_VERSION,
187                v,
188            )
189        });
190        let test_linux_bzimage =
191            crate::resolve_openvmm_test_linux_kernel::OpenvmmTestKernelFile::BzImage
192                .is_available_for(arch)
193                .then(|| {
194                    ctx.reqv(|v| {
195                        crate::resolve_openvmm_test_linux_kernel::Request::Get(
196                            crate::resolve_openvmm_test_linux_kernel::OpenvmmTestKernelFile::BzImage,
197                            arch,
198                            crate::resolve_openvmm_test_linux_kernel::DEFAULT_LINUX_TEST_KERNEL_VERSION,
199                            v,
200                        )
201                    })
202                });
203
204        let uefi =
205            ctx.reqv(|v| crate::download_uefi_mu_msvm::Request::GetMsvmFd { arch, msvm_fd: v });
206
207        let virtio_win_dir = ctx.reqv(crate::resolve_openvmm_test_virtio_win::Request::Get);
208
209        let release_igvm_files = if needs_release_igvm {
210            Some(ctx.reqv(
211                |v| crate::download_release_igvm_files_from_gh::resolve::Request {
212                    arch,
213                    release_igvm_files: v,
214                    release_version: OpenhclReleaseVersion::latest(),
215                },
216            ))
217        } else {
218            None
219        };
220
221        let VmmTestsBuiltArtifacts {
222            flowey_hvlite,
223            nextest_vmm_tests_archive,
224            incubator,
225            prep_steps,
226            test_igvm_agent_rpc_server,
227            openvmm,
228            openvmm_vhost,
229            pipette_windows,
230            pipette_linux_musl,
231            guest_test_uefi,
232            openhcl_standard,
233            openhcl_standard_dev,
234            openhcl_cvm,
235            openhcl_linux_direct,
236            tmks,
237            tmk_vmm,
238            tmk_vmm_linux_musl,
239            vmgstool,
240            vmgstool_dev,
241            tpm_guest_tests_windows,
242            tpm_guest_tests_linux,
243        } = built_artifacts;
244
245        let openhcl_igvm_files = [
246            openhcl_standard,
247            openhcl_standard_dev,
248            openhcl_cvm,
249            openhcl_linux_direct,
250        ]
251        .into_iter()
252        .flatten()
253        .collect::<Vec<_>>();
254
255        ctx.emit_rust_step("setting up vmm_tests content dir", |ctx| {
256            claim_vars!(
257                ctx,
258                (
259                    test_content_dir,
260                    openvmm_repo_path,
261                    // built artifacts - pipeline
262                    flowey_hvlite,
263                    nextest_vmm_tests_archive,
264                    incubator,
265                    prep_steps,
266                    test_igvm_agent_rpc_server,
267                    // built artifacts - petri
268                    openvmm,
269                    openvmm_vhost,
270                    pipette_windows,
271                    pipette_linux_musl,
272                    guest_test_uefi,
273                    openhcl_igvm_files,
274                    tmks,
275                    tmk_vmm,
276                    tmk_vmm_linux_musl,
277                    vmgstool,
278                    vmgstool_dev,
279                    tpm_guest_tests_windows,
280                    tpm_guest_tests_linux,
281                    // downloaded artifacts
282                    test_linux_initrd,
283                    test_linux_kernel,
284                    test_linux_bzimage,
285                    uefi,
286                    virtio_win_dir,
287                    release_igvm_files,
288                )
289            );
290
291            done.claim(ctx);
292
293            move |rt| {
294                let test_linux_initrd = rt.read(test_linux_initrd);
295                let test_linux_kernel = rt.read(test_linux_kernel);
296                let test_linux_bzimage = test_linux_bzimage.map(|v| rt.read(v));
297                let uefi = rt.read(uefi);
298                let release_igvm_files_dir = rt.read(release_igvm_files);
299                let test_content_dir = rt.read(test_content_dir);
300
301                if !test_content_dir.exists() {
302                    fs_err::create_dir_all(&test_content_dir)?
303                };
304
305                if let Some(openvmm_repo_path) = openvmm_repo_path {
306                    let openvmm_repo_path = rt.read(openvmm_repo_path);
307
308                    let nextest_config_file = PathBuf::new().join(".config").join("nextest.toml");
309                    fs_err::create_dir_all(
310                        test_content_dir
311                            .join(&nextest_config_file)
312                            .parent()
313                            .context("no parent")?,
314                    )?;
315                    fs_err::copy(
316                        openvmm_repo_path.join(&nextest_config_file),
317                        test_content_dir.join(&nextest_config_file),
318                    )?;
319
320                    let repo_cargo_toml_file = Path::new("Cargo.toml");
321                    fs_err::copy(
322                        openvmm_repo_path.join(repo_cargo_toml_file),
323                        test_content_dir.join(repo_cargo_toml_file),
324                    )?;
325
326                    let crate_cargo_toml_file = PathBuf::new()
327                        .join("vmm_tests")
328                        .join("vmm_tests")
329                        .join("Cargo.toml");
330                    fs_err::create_dir_all(
331                        test_content_dir
332                            .join(&crate_cargo_toml_file)
333                            .parent()
334                            .context("no parent")?,
335                    )?;
336                    fs_err::copy(
337                        openvmm_repo_path.join(&crate_cargo_toml_file),
338                        test_content_dir.join(&crate_cargo_toml_file),
339                    )?;
340
341                    if needs_incubator_profiles {
342                        let incubator_profile_dir = incubator_profile_dir();
343                        fs_err::create_dir_all(test_content_dir.join(&incubator_profile_dir))?;
344                        for entry in
345                            fs_err::read_dir(openvmm_repo_path.join(&incubator_profile_dir))?
346                        {
347                            let profile = entry?.path();
348                            if profile.is_file()
349                                && profile.extension().is_some_and(|ext| ext == "toml")
350                            {
351                                let dst = test_content_dir
352                                    .join(&incubator_profile_dir)
353                                    .join(profile.file_name().context("no file name")?);
354                                fs_err::copy(profile, dst)?;
355                            }
356                        }
357                    }
358                }
359
360                if let Some(flowey_hvlite) = flowey_hvlite {
361                    match rt.read(flowey_hvlite) {
362                        FloweyHvliteOutput::WindowsBin { exe, .. } => {
363                            fs_err::copy(exe, test_content_dir.join("flowey_hvlite.exe"))?;
364                        }
365                        FloweyHvliteOutput::LinuxBin { bin, .. } => {
366                            let dst = test_content_dir.join("flowey_hvlite");
367                            fs_err::copy(bin, &dst)?;
368                            dst.make_executable()?;
369                        }
370                    }
371                }
372
373                if let Some(archive) = nextest_vmm_tests_archive {
374                    let NextestVmmTestsArchive { archive_file } = rt.read(archive);
375                    fs_err::copy(archive_file, test_content_dir.join("vmm_tests.tar.zst"))?;
376                }
377
378                if let Some(openvmm) = openvmm {
379                    match rt.read(openvmm) {
380                        OpenvmmOutput::WindowsBin { exe, pdb: _ } => {
381                            fs_err::copy(exe, test_content_dir.join("openvmm.exe"))?;
382                        }
383                        OpenvmmOutput::LinuxBin { bin, dbg: _ } => {
384                            let dst = test_content_dir.join("openvmm");
385                            fs_err::copy(bin, dst.clone())?;
386                            dst.make_executable()?;
387                        }
388                    }
389                }
390
391                if let Some(openvmm_vhost) = openvmm_vhost {
392                    let OpenvmmVhostOutput { bin, dbg: _ } = rt.read(openvmm_vhost);
393                    let dst = test_content_dir.join("openvmm_vhost");
394                    fs_err::copy(bin, &dst)?;
395                    dst.make_executable()?;
396                }
397
398                if let Some(pipette_win) = pipette_windows {
399                    match rt.read(pipette_win) {
400                        PipetteOutput::WindowsBin { exe, pdb: _ } => {
401                            fs_err::copy(exe, test_content_dir.join("pipette.exe"))?;
402                        }
403                        _ => anyhow::bail!("did not find `pipette.exe` in RegisterPipetteWindows"),
404                    }
405                }
406
407                if let Some(pipette_linux) = pipette_linux_musl {
408                    match rt.read(pipette_linux) {
409                        PipetteOutput::LinuxBin { bin, dbg: _ } => {
410                            let dst = test_content_dir.join("pipette");
411                            fs_err::copy(bin, &dst)?;
412                            dst.make_executable()?;
413                        }
414                        _ => {
415                            anyhow::bail!("did not find `pipette` in RegisterPipetteLinuxMusl")
416                        }
417                    }
418                }
419
420                if let Some(guest_test_uefi) = guest_test_uefi {
421                    let GuestTestUefiOutput {
422                        efi: _,
423                        pdb: _,
424                        img,
425                    } = rt.read(guest_test_uefi);
426                    fs_err::copy(img, test_content_dir.join("guest_test_uefi.img"))?;
427                }
428
429                if let Some(tmks) = tmks {
430                    let TmksOutput { bin, dbg: _ } = rt.read(tmks);
431                    fs_err::copy(bin, test_content_dir.join("simple_tmk"))?;
432                }
433
434                if let Some(tmk_vmm) = tmk_vmm {
435                    match rt.read(tmk_vmm) {
436                        TmkVmmOutput::WindowsBin { exe, .. } => {
437                            fs_err::copy(exe, test_content_dir.join("tmk_vmm.exe"))?;
438                        }
439                        TmkVmmOutput::LinuxBin { bin, .. } => {
440                            let dst = test_content_dir.join("tmk_vmm");
441                            fs_err::copy(bin, &dst)?;
442                            dst.make_executable()?;
443                        }
444                    }
445                }
446
447                if let Some(tmk_vmm_linux_musl) = tmk_vmm_linux_musl {
448                    let TmkVmmOutput::LinuxBin { bin, dbg: _ } = rt.read(tmk_vmm_linux_musl) else {
449                        anyhow::bail!("invalid tmk_vmm output")
450                    };
451                    // Note that this overwrites the previous tmk_vmm. That's
452                    // OK, they should be the same. Fix this when the resolver
453                    // can handle multiple different outputs with the same name.
454                    fs_err::copy(bin, test_content_dir.join("tmk_vmm"))?;
455                }
456
457                if let Some(vmgstool) = vmgstool {
458                    match rt.read(vmgstool) {
459                        VmgstoolOutput::WindowsBin { exe, .. } => {
460                            fs_err::copy(exe, test_content_dir.join("vmgstool.exe"))?;
461                        }
462                        VmgstoolOutput::LinuxBin { bin, .. } => {
463                            let dst = test_content_dir.join("vmgstool");
464                            fs_err::copy(bin, &dst)?;
465                            dst.make_executable()?;
466                        }
467                    }
468                }
469
470                if let Some(vmgstool_dev) = vmgstool_dev {
471                    match rt.read(vmgstool_dev) {
472                        VmgstoolOutput::WindowsBin { exe, .. } => {
473                            fs_err::copy(exe, test_content_dir.join("vmgstool-dev.exe"))?;
474                        }
475                        VmgstoolOutput::LinuxBin { bin, .. } => {
476                            let dst = test_content_dir.join("vmgstool-dev");
477                            fs_err::copy(bin, &dst)?;
478                            dst.make_executable()?;
479                        }
480                    }
481                }
482
483                if let Some(tpm_guest_tests_windows) = tpm_guest_tests_windows {
484                    let TpmGuestTestsOutput::WindowsBin { exe, .. } =
485                        rt.read(tpm_guest_tests_windows)
486                    else {
487                        anyhow::bail!("expected Windows tpm_guest_tests artifact")
488                    };
489                    fs_err::copy(exe, test_content_dir.join("tpm_guest_tests.exe"))?;
490                }
491
492                if let Some(tpm_guest_tests_linux) = tpm_guest_tests_linux {
493                    let TpmGuestTestsOutput::LinuxBin { bin, .. } = rt.read(tpm_guest_tests_linux)
494                    else {
495                        anyhow::bail!("expected Linux tpm_guest_tests artifact")
496                    };
497                    let dst = test_content_dir.join("tpm_guest_tests");
498                    fs_err::copy(bin, &dst)?;
499                    dst.make_executable()?;
500                }
501
502                if let Some(test_igvm_agent_rpc_server) = test_igvm_agent_rpc_server {
503                    let TestIgvmAgentRpcServerOutput { exe, .. } =
504                        rt.read(test_igvm_agent_rpc_server);
505                    fs_err::copy(exe, test_content_dir.join("test_igvm_agent_rpc_server.exe"))?;
506                }
507
508                if let Some(prep_steps) = prep_steps {
509                    match rt.read(prep_steps) {
510                        PrepStepsOutput::WindowsBin { exe, .. } => {
511                            fs_err::copy(exe, test_content_dir.join("prep_steps.exe"))?;
512                        }
513                        PrepStepsOutput::LinuxBin { bin, .. } => {
514                            let dst = test_content_dir.join("prep_steps");
515                            fs_err::copy(bin, &dst)?;
516                            dst.make_executable()?;
517                        }
518                    }
519                }
520
521                if let Some(incubator) = incubator {
522                    let IncubatorOutput { bin, .. } = rt.read(incubator);
523                    fs_err::copy(bin, test_content_dir.join("incubator"))?;
524                }
525
526                for openhcl_igvm in rt.read(openhcl_igvm_files) {
527                    let igvm_bin = openhcl_igvm.igvm_bin();
528                    if let Some(recipe) = openhcl_igvm.recipe() {
529                        fs_err::copy(
530                            igvm_bin,
531                            test_content_dir.join(format!("{}.bin", recipe.non_production_name())),
532                        )?;
533                    } else {
534                        log::warn!("petri doesn't support custom OpenHCL files");
535                    };
536                }
537
538                if let Some(release_igvm_files) = release_igvm_files_dir {
539                    let latest_release_version = OpenhclReleaseVersion::latest();
540
541                    if let Some(src) = &release_igvm_files.openhcl {
542                        let new_name = format!("{latest_release_version}-x64-openhcl.bin");
543                        fs_err::copy(src, test_content_dir.join(new_name))?;
544                    }
545
546                    if let Some(src) = &release_igvm_files.openhcl_aarch64 {
547                        let new_name = format!("{latest_release_version}-aarch64-openhcl.bin");
548                        fs_err::copy(src, test_content_dir.join(new_name))?;
549                    }
550
551                    if let Some(src) = &release_igvm_files.openhcl_direct {
552                        let new_name = format!("{latest_release_version}-x64-direct-openhcl.bin");
553                        fs_err::copy(src, test_content_dir.join(new_name))?;
554                    }
555                }
556
557                let (arch_dir, kernel_file_name) = match arch {
558                    CommonArch::X86_64 => ("x64", "vmlinux"),
559                    CommonArch::Aarch64 => ("aarch64", "Image"),
560                };
561                fs_err::create_dir_all(test_content_dir.join(arch_dir))?;
562                fs_err::copy(
563                    test_linux_initrd,
564                    test_content_dir.join(arch_dir).join("initrd"),
565                )?;
566                fs_err::copy(
567                    test_linux_kernel,
568                    test_content_dir.join(arch_dir).join(kernel_file_name),
569                )?;
570                if let Some(bzimage_path) = test_linux_bzimage {
571                    fs_err::copy(
572                        bzimage_path,
573                        test_content_dir.join(arch_dir).join("bzImage"),
574                    )?;
575                }
576
577                let uefi_dir = test_content_dir.join(match arch {
578                    CommonArch::Aarch64 => {
579                        "hyperv.uefi.mscoreuefi.AARCH64.RELEASE/MsvmAARCH64/RELEASE_CLANGPDB/FV"
580                    }
581                    CommonArch::X86_64 => {
582                        "hyperv.uefi.mscoreuefi.x64.RELEASE/MsvmX64/RELEASE_VS2022/FV"
583                    }
584                });
585                fs_err::create_dir_all(&uefi_dir)?;
586                fs_err::copy(uefi, uefi_dir.join("MSVM.fd"))?;
587
588                {
589                    let src = rt.read(virtio_win_dir);
590                    let dst = test_content_dir.join("virtio-win");
591                    let _ = fs_err::remove_dir_all(&dst);
592                    flowey_lib_common::_util::copy_dir_all(&src, &dst)?;
593                }
594
595                // debug log the current contents of the dir
596                log::debug!("final folder content: {}", test_content_dir.display());
597                for entry in test_content_dir.read_dir()? {
598                    let entry = entry?;
599                    log::debug!("contains: {:?}", entry.file_name());
600                }
601
602                Ok(())
603            }
604        });
605
606        Ok(())
607    }
608}
609
610/// Utility builders which make it easy to "skim off" artifacts required by VMM
611/// test execution from other pipeline jobs.
612//
613// DEVNOTE: this is pub so internal tests can reuse the same builders
614pub mod vmm_tests_artifact_builders {
615    use super::*;
616
617    vmm_tests_built_artifacts_builder!(
618        VmmTestsArtifactsBuilderLinuxX86,
619        (
620            // windows build machine
621            pipette_windows => PipetteOutput,
622            tmk_vmm => TmkVmmOutput,
623            // linux build machine
624            nextest_vmm_tests_archive => NextestVmmTestsArchive,
625            openvmm => OpenvmmOutput,
626            openvmm_vhost => OpenvmmVhostOutput,
627            pipette_linux_musl => PipetteOutput,
628            prep_steps => PrepStepsOutput,
629            // any machine
630            guest_test_uefi => GuestTestUefiOutput,
631            tmks => TmksOutput,
632        )
633    );
634
635    vmm_tests_built_artifacts_builder!(
636        VmmTestsArtifactsBuilderWindowsX86,
637        (
638            // windows build machine
639            nextest_vmm_tests_archive => NextestVmmTestsArchive,
640            openvmm => OpenvmmOutput,
641            pipette_windows => PipetteOutput,
642            tmk_vmm => TmkVmmOutput,
643            prep_steps => PrepStepsOutput,
644            vmgstool => VmgstoolOutput,
645            vmgstool_dev => VmgstoolOutput,
646            tpm_guest_tests_windows => TpmGuestTestsOutput,
647            tpm_guest_tests_linux => TpmGuestTestsOutput,
648            test_igvm_agent_rpc_server => TestIgvmAgentRpcServerOutput,
649            // linux build machine
650            openhcl_standard => OpenhclIgvmOutput,
651            openhcl_cvm => OpenhclIgvmOutput,
652            openhcl_linux_direct => OpenhclIgvmOutput,
653            pipette_linux_musl => PipetteOutput,
654            tmk_vmm_linux_musl => TmkVmmOutput,
655            // any machine
656            guest_test_uefi => GuestTestUefiOutput,
657            tmks => TmksOutput,
658        )
659    );
660
661    vmm_tests_built_artifacts_builder!(
662        VmmTestsArtifactsBuilderWindowsAarch64,
663        (
664            // windows build machine
665            nextest_vmm_tests_archive => NextestVmmTestsArchive,
666            openvmm => OpenvmmOutput,
667            pipette_windows => PipetteOutput,
668            tmk_vmm => TmkVmmOutput,
669            vmgstool => VmgstoolOutput,
670            vmgstool_dev => VmgstoolOutput,
671            // linux build machine
672            openhcl_standard => OpenhclIgvmOutput,
673            pipette_linux_musl => PipetteOutput,
674            tmk_vmm_linux_musl => TmkVmmOutput,
675            // any machine
676            guest_test_uefi => GuestTestUefiOutput,
677            tmks => TmksOutput,
678        )
679    );
680
681    // Artifact builder for aarch64 Linux VMM tests running via QEMU TCG.
682    //
683    // The test binaries are aarch64-linux-musl (run inside QEMU), but the
684    // incubator binary is x86_64-linux-gnu (runs on the CI host).
685    vmm_tests_built_artifacts_builder!(
686        VmmTestsArtifactsBuilderLinuxAarch64Tcg,
687        (
688            // x86_64 CI host binary
689            incubator => IncubatorOutput,
690            // aarch64 guest binaries
691            nextest_vmm_tests_archive => NextestVmmTestsArchive,
692            openvmm => OpenvmmOutput,
693            pipette_linux_musl => PipetteOutput,
694            guest_test_uefi => GuestTestUefiOutput,
695            tmks => TmksOutput,
696            tmk_vmm => TmkVmmOutput,
697        )
698    );
699}