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/// Runtime capabilities that VMM tests can require.
10pub mod capabilities {
11 /// Software VPCI device emulation support.
12 pub const VPCI: &str = "vpci";
13
14 /// Support for resetting a partition running Windows.
15 pub const WINDOWS_PARTITION_RESET: &str = "windows_partition_reset";
16
17 /// All capability names known to petri, including those defined by
18 /// incubators. Incubator device capabilities are the device's profile
19 /// `name` with `-` replaced by `_` (e.g. `edu-initiator` → `edu_initiator`).
20 pub const KNOWN_CAPABILITIES: &[&str] = &[
21 VPCI,
22 WINDOWS_PARTITION_RESET,
23 "test_disk",
24 "edu_initiator",
25 "ivshmem_target",
26 ];
27
28 /// Returns `name` if it is a known capability name.
29 pub fn known(name: &str) -> Option<&'static str> {
30 KNOWN_CAPABILITIES
31 .iter()
32 .copied()
33 .find(|capability| *capability == name)
34 }
35
36 /// Returns whether `name` is a known capability name.
37 pub fn is_known_name(name: &str) -> bool {
38 known(name).is_some()
39 }
40}
41
42/// Artifact declarations
43pub mod artifacts {
44 use petri_artifacts_core::declare_artifacts;
45
46 declare_artifacts! {
47 /// Pipette windows x86_64 executable
48 PIPETTE_WINDOWS_X64,
49 /// Pipette linux x86_64 executable
50 PIPETTE_LINUX_X64,
51 /// Pipette windows aarch64 executable
52 PIPETTE_WINDOWS_AARCH64,
53 /// Pipette linux aarch64 executable
54 PIPETTE_LINUX_AARCH64,
55 /// Directory to put petri test logs in
56 TEST_LOG_DIRECTORY,
57 }
58}
59
60/// Artifact tag trait declarations
61pub mod tags {
62 use petri_artifacts_core::ArtifactId;
63
64 /// A coarse-grained label used to differentiate between different OS
65 /// environments.
66 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
67 #[expect(missing_docs)] // Self-describing names.
68 pub enum OsFlavor {
69 Windows,
70 Linux,
71 FreeBsd,
72 Uefi,
73 }
74
75 /// The machine architecture supported by the artifact or VM.
76 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
77 #[expect(missing_docs)] // Self describing names
78 pub enum MachineArch {
79 X86_64,
80 Aarch64,
81 }
82
83 impl MachineArch {
84 /// Returns the host's architecture.
85 pub fn host() -> Self {
86 // xtask-fmt allow-target-arch oneoff-petri-host-arch
87 if cfg!(target_arch = "x86_64") {
88 Self::X86_64
89 }
90 // xtask-fmt allow-target-arch oneoff-petri-host-arch
91 else if cfg!(target_arch = "aarch64") {
92 Self::Aarch64
93 } else {
94 panic!("unsupported host architecture")
95 }
96 }
97 }
98
99 /// Quirks needed to boot a guest.
100 #[derive(Default, Clone, Debug)]
101 pub struct GuestQuirksInner {
102 /// How long to wait after the shutdown IC reports ready before sending
103 /// the shutdown command.
104 ///
105 /// This is necessary because some guests will ignore shutdown requests
106 /// that arrive too early in the boot process.
107 pub hyperv_shutdown_ic_sleep: Option<std::time::Duration>,
108 /// Some guests reboot automatically soon after first boot.
109 pub initial_reboot: Option<InitialRebootCondition>,
110 }
111
112 /// Some guests may automatically reboot only in certain configurations
113 #[derive(Clone, Copy, Debug)]
114 pub enum InitialRebootCondition {
115 /// This guest always reboots on this VMM.
116 Always,
117 /// This guest only reboots when the TPM is enabled.
118 WithTpm,
119 }
120
121 /// Quirks needed to boot a guest, allowing for differences based on backend
122 #[derive(Default, Clone, Debug)]
123 pub struct GuestQuirks {
124 /// Quirks when running in OpenVMM
125 pub openvmm: GuestQuirksInner,
126 /// Quirks when running in Hyper-V
127 pub hyperv: GuestQuirksInner,
128 }
129
130 impl GuestQuirks {
131 /// Use the same quirks for all backends
132 pub fn for_all_backends(quirks: GuestQuirksInner) -> GuestQuirks {
133 GuestQuirks {
134 openvmm: quirks.clone(),
135 hyperv: quirks,
136 }
137 }
138 }
139
140 /// Artifact is a OpenHCL IGVM file
141 pub trait IsOpenhclIgvm: IsLoadable + ArtifactId {}
142
143 /// Artifact is a bootable test VHD file
144 pub trait IsTestVhd: ArtifactId {
145 /// What [`OsFlavor`] this image boots into.
146 const OS_FLAVOR: OsFlavor;
147
148 /// What [`MachineArch`] this image supports.
149 const ARCH: MachineArch;
150
151 /// Declare any "quirks" needed to boot the image.
152 fn quirks() -> GuestQuirks {
153 GuestQuirks::default()
154 }
155 }
156
157 /// Artifact is a bootable test ISO file
158 pub trait IsTestIso: ArtifactId {
159 /// What [`OsFlavor`] this image boots into.
160 const OS_FLAVOR: OsFlavor;
161
162 /// What [`MachineArch`] this image supports.
163 const ARCH: MachineArch;
164
165 /// Declare any "quirks" needed to boot the image.
166 fn quirks() -> GuestQuirks {
167 GuestQuirks::default()
168 }
169 }
170
171 /// Artifact is a binary that can be loaded into a VM
172 pub trait IsLoadable: ArtifactId {
173 /// What [`MachineArch`] this artifact supports.
174 const ARCH: MachineArch;
175 }
176
177 /// Artifact is a test VMGS file
178 pub trait IsTestVmgs: ArtifactId {}
179
180 /// Artifact is a VmgsTool binary
181 pub trait IsVmgsTool: ArtifactId {}
182}