petri_artifacts_common/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! `petri` test artifact declarations used by all petri-based tests, no matter
5//! what VMM backend is being used.
6
7#![forbid(unsafe_code)]
8
9/// Artifact declarations
10pub mod artifacts {
11    use petri_artifacts_core::declare_artifacts;
12
13    declare_artifacts! {
14        /// Pipette windows x86_64 executable
15        PIPETTE_WINDOWS_X64,
16        /// Pipette linux x86_64 executable
17        PIPETTE_LINUX_X64,
18        /// Pipette windows aarch64 executable
19        PIPETTE_WINDOWS_AARCH64,
20        /// Pipette linux aarch64 executable
21        PIPETTE_LINUX_AARCH64,
22        /// Directory to put petri test logs in
23        TEST_LOG_DIRECTORY,
24    }
25}
26
27/// Artifact tag trait declarations
28pub mod tags {
29    use petri_artifacts_core::ArtifactId;
30
31    /// A coarse-grained label used to differentiate between different OS
32    /// environments.
33    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
34    #[expect(missing_docs)] // Self-describing names.
35    pub enum OsFlavor {
36        Windows,
37        Linux,
38        FreeBsd,
39        Uefi,
40    }
41
42    /// The machine architecture supported by the artifact or VM.
43    #[derive(Copy, Clone, Debug, PartialEq, Eq)]
44    #[expect(missing_docs)] // Self describing names
45    pub enum MachineArch {
46        X86_64,
47        Aarch64,
48    }
49
50    impl MachineArch {
51        /// Returns the host's architecture.
52        pub fn host() -> Self {
53            // xtask-fmt allow-target-arch oneoff-petri-host-arch
54            if cfg!(target_arch = "x86_64") {
55                Self::X86_64
56            }
57            // xtask-fmt allow-target-arch oneoff-petri-host-arch
58            else if cfg!(target_arch = "aarch64") {
59                Self::Aarch64
60            } else {
61                panic!("unsupported host architecture")
62            }
63        }
64    }
65
66    /// Quirks needed to boot a guest.
67    #[derive(Default, Clone, Debug)]
68    pub struct GuestQuirksInner {
69        /// How long to wait after the shutdown IC reports ready before sending
70        /// the shutdown command.
71        ///
72        /// This is necessary because some guests will ignore shutdown requests
73        /// that arrive too early in the boot process.
74        pub hyperv_shutdown_ic_sleep: Option<std::time::Duration>,
75        /// Some guests reboot automatically soon after first boot.
76        pub initial_reboot: Option<InitialRebootCondition>,
77    }
78
79    /// Some guests may automatically reboot only in certain configurations
80    #[derive(Clone, Copy, Debug)]
81    pub enum InitialRebootCondition {
82        /// This guest always reboots on this VMM.
83        Always,
84        /// This guest only reboots when the TPM is enabled.
85        WithTpm,
86    }
87
88    /// Quirks needed to boot a guest, allowing for differences based on backend
89    #[derive(Default, Clone, Debug)]
90    pub struct GuestQuirks {
91        /// Quirks when running in OpenVMM
92        pub openvmm: GuestQuirksInner,
93        /// Quirks when running in Hyper-V
94        pub hyperv: GuestQuirksInner,
95    }
96
97    impl GuestQuirks {
98        /// Use the same quirks for all backends
99        pub fn for_all_backends(quirks: GuestQuirksInner) -> GuestQuirks {
100            GuestQuirks {
101                openvmm: quirks.clone(),
102                hyperv: quirks,
103            }
104        }
105    }
106
107    /// Artifact is a OpenHCL IGVM file
108    pub trait IsOpenhclIgvm: IsLoadable + ArtifactId {}
109
110    /// Artifact is a bootable test VHD file
111    pub trait IsTestVhd: ArtifactId {
112        /// What [`OsFlavor`] this image boots into.
113        const OS_FLAVOR: OsFlavor;
114
115        /// What [`MachineArch`] this image supports.
116        const ARCH: MachineArch;
117
118        /// Declare any "quirks" needed to boot the image.
119        fn quirks() -> GuestQuirks {
120            GuestQuirks::default()
121        }
122    }
123
124    /// Artifact is a bootable test ISO file
125    pub trait IsTestIso: ArtifactId {
126        /// What [`OsFlavor`] this image boots into.
127        const OS_FLAVOR: OsFlavor;
128
129        /// What [`MachineArch`] this image supports.
130        const ARCH: MachineArch;
131
132        /// Declare any "quirks" needed to boot the image.
133        fn quirks() -> GuestQuirks {
134            GuestQuirks::default()
135        }
136    }
137
138    /// Artifact is a binary that can be loaded into a VM
139    pub trait IsLoadable: ArtifactId {
140        /// What [`MachineArch`] this artifact supports.
141        const ARCH: MachineArch;
142    }
143
144    /// Artifact is a test VMGS file
145    pub trait IsTestVmgs: ArtifactId {}
146
147    /// Artifact is a VmgsTool binary
148    pub trait IsVmgsTool: ArtifactId {}
149}