microsoft/openvmm

Public

mirrored fromhttps://github.com/microsoft/openvmmAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
9fa0c3ee87af75e07fa974b6005348ae6b9349ff

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

flowey/flowey_hvlite/src/pipelines/build_igvm.rs

346lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! See [`BuildIgvmCli`]
5
6use flowey::node::prelude::ReadVar;
7use flowey::pipeline::prelude::*;
8use flowey_lib_hvlite::build_openhcl_igvm_from_recipe::OpenhclIgvmRecipe;
9use flowey_lib_hvlite::build_openhcl_igvm_from_recipe::OpenhclKernelPackage;
10use flowey_lib_hvlite::run_cargo_build::common::CommonArch;
11use std::path::PathBuf;
12
13#[derive(clap::ValueEnum, Copy, Clone)]
14pub enum OpenhclRecipeCli {
15 /// Aarch64 OpenHCL
16 Aarch64,
17 /// Aarch64 OpenHCL, using the dev kernel in VTL2
18 Aarch64Devkern,
19 /// X64 OpenHCL, with CVM support.
20 X64Cvm,
21 /// X64 OpenHCL, with CVM support using the dev kernel in VTL2
22 X64CvmDevkern,
23 /// X64 OpenHCL booting VTL0 using a test linux-direct kernel + initrd (no
24 /// UEFI).
25 X64TestLinuxDirect,
26 /// X64 OpenHCL booting VTL0 using a test linux-direct kernel + initrd (no
27 /// UEFI), using the dev kernel in VTL2.
28 X64TestLinuxDirectDevkern,
29 /// X64 OpenHCL
30 X64,
31 /// X64 OpenHCL, using the dev kernel in VTL2
32 X64Devkern,
33}
34
35/// Build OpenHCL IGVM files for local development. DO NOT USE IN CI.
36#[derive(clap::Args)]
37pub struct BuildIgvmCli<Recipe = OpenhclRecipeCli>
38where
39 // Make the recipe generic so that out-of-tree flowey implementations can
40 // slot in a custom set of recipes to build with.
41 Recipe: clap::ValueEnum + Clone + Send + Sync + 'static,
42{
43 /// Specify which OpenHCL recipe to build / customize off-of.
44 ///
45 /// A "recipe" corresponds to the various standard IGVM SKUs that are
46 /// actively supported and tested in our build infrastructure.
47 ///
48 /// It encodes all the details of what goes into an individual IGVM file,
49 /// such as what build flags `openvmm_hcl` should be built with, what goes
50 /// into a VTL2 initrd, what `igvmfilegen` manifest is being used, etc...
51 pub recipe: Recipe,
52
53 /// Build using release variants of all constituent components.
54 ///
55 /// Uses --profile=boot-release for openhcl_boot, --profile=openhcl-ship
56 /// when building openvmm_hcl, `--min-interactive` vtl2 initrd
57 /// configuration, `-release.json` manifest variant, etc...
58 #[clap(long)]
59 pub release: bool,
60
61 /// pass `--verbose` to cargo
62 #[clap(long)]
63 pub verbose: bool,
64
65 /// pass `--locked` to cargo
66 #[clap(long)]
67 pub locked: bool,
68
69 /// Automatically install any missing required dependencies.
70 #[clap(long)]
71 pub install_missing_deps: bool,
72
73 #[clap(flatten)]
74 pub customizations: BuildIgvmCliCustomizations,
75}
76
77#[derive(clap::Args)]
78#[clap(next_help_heading = "Customizations")]
79pub struct BuildIgvmCliCustomizations {
80 /// Set a custom label for this `build-igvm` invocation. If no label is
81 /// provided, customized IGVM files will be output with the label
82 /// `{base_recipe_name}-custom`
83 #[clap(long, short = 'o')]
84 pub build_label: Option<String>,
85
86 /// Override which kernel package to use.
87 #[clap(long)]
88 pub override_kernel_pkg: Option<KernelPackageKindCli>,
89
90 /// Pass additional features when building openmm_hcl
91 #[clap(long)]
92 pub override_openvmm_hcl_feature: Vec<String>,
93
94 /// Override architecture used when building. You probably don't want this -
95 /// prefer changing the base recipe to something more appropriate.
96 #[clap(long)]
97 pub override_arch: Option<BuildIgvmArch>,
98
99 /// Override the json manifest passed to igvmfilegen, none means the
100 /// debug/release manifest from the base recipe will be used.
101 #[clap(long)]
102 pub override_manifest: Option<PathBuf>,
103
104 /// Ensure perf tools are included in the release initrd.
105 ///
106 /// Ensures that openvmm_hcl is not stripped, so that perf tools work
107 /// correctly, and requires that the file be built in `--release` mode, so
108 /// that perf numbers are more representative of production binaries.
109 #[clap(long, requires = "release")]
110 pub with_perf_tools: bool,
111
112 /// Preserve debuginfo in the openvmm_hcl binary in the IGVM file.
113 ///
114 /// This increases the VTL2 memory requirements significantly, and will
115 /// likely require passing a `--override-manifest` to compensate.
116 #[clap(long)]
117 pub with_debuginfo: bool,
118
119 /// Path to custom openvmm_hcl binary, none means openhcl will be built.
120 #[clap(long)]
121 pub custom_openvmm_hcl: Option<PathBuf>,
122
123 /// Path to custom openhcl_boot, none means the boot loader will be built.
124 #[clap(long)]
125 pub custom_openhcl_boot: Option<PathBuf>,
126
127 /// Path to custom uefi MSVM.fd, none means the packaged uefi will be used.
128 #[clap(long)]
129 pub custom_uefi: Option<PathBuf>,
130
131 /// Path to custom kernel vmlinux / Image, none means the packaged kernel
132 /// will be used.
133 #[clap(long)]
134 pub custom_kernel: Option<PathBuf>,
135
136 /// Path to kernel modules, none means the packaged kernel modules will be
137 /// used.
138 #[clap(long)]
139 pub custom_kernel_modules: Option<PathBuf>,
140
141 /// Path to custom vtl0 linux kernel to use if the manifest includes a
142 /// direct-boot linux VM.
143 ///
144 /// If not specified, the packaged openvmm test linux direct kernel is used.
145 #[clap(long)]
146 pub custom_vtl0_kernel: Option<PathBuf>,
147
148 /// Additional layers to be included in the initrd
149 #[clap(long)]
150 pub custom_layer: Vec<PathBuf>,
151
152 /// Additional directories to be included in the initrd
153 #[clap(long)]
154 pub custom_directory: Vec<PathBuf>,
155
156 /// Additional rootfs.config files to use to generate the initrd
157 #[clap(long)]
158 pub custom_extra_rootfs: Vec<PathBuf>,
159
160 /// (experimental) Include the AP kernel in the IGVM file
161 #[clap(long)]
162 pub with_sidecar: bool,
163
164 /// (experimental) Path to custom sidecar kernel binary, none means sidecar
165 /// will be built.
166 #[clap(long, requires = "with_sidecar")]
167 pub custom_sidecar: Option<PathBuf>,
168}
169
170#[derive(clap::ValueEnum, Copy, Clone, PartialEq, Eq, Debug)]
171pub enum KernelPackageKindCli {
172 /// Kernel from the hcl-main branch
173 Main,
174 /// CVM kernel from the hcl-main branch
175 Cvm,
176 /// Kernel from the hcl-dev branch
177 Dev,
178 /// CVM kernel from the hcl-dev brnach
179 CvmDev,
180}
181
182#[derive(clap::ValueEnum, Copy, Clone, PartialEq, Eq, Debug)]
183pub enum BuildIgvmArch {
184 X86_64,
185 Aarch64,
186}
187
188pub fn bail_if_running_in_ci() -> anyhow::Result<()> {
189 const OVERRIDE_ENV: &str = "I_HAVE_A_GOOD_REASON_TO_RUN_BUILD_IGVM_IN_CI";
190
191 if std::env::var(OVERRIDE_ENV).is_ok() {
192 return Ok(());
193 }
194
195 for ci_env in ["TF_BUILD", "GITHUB_ACTIONS"] {
196 if std::env::var(ci_env).is_ok() {
197 log::warn!("Detected that {ci_env} is set");
198 log::warn!("");
199 log::warn!("Do not use `build-igvm` in CI scripts!");
200 log::warn!(
201 "This is a local-only, inner-dev-loop tool to build IGVM files, with an UNSTABLE CLI."
202 );
203 log::warn!("");
204 log::warn!(
205 "Automated pipelines should use the underlying `flowey` nodes that power build-igvm directly, _without_ relying on its CLI!"
206 );
207 log::warn!("");
208 log::warn!(
209 "If you _really_ know what you're doing, you can set {OVERRIDE_ENV} to disable this error."
210 );
211 anyhow::bail!("attempted to run `build-igvm` in CI")
212 }
213 }
214
215 Ok(())
216}
217
218impl IntoPipeline for BuildIgvmCli {
219 fn into_pipeline(self, backend_hint: PipelineBackendHint) -> anyhow::Result<Pipeline> {
220 if !matches!(backend_hint, PipelineBackendHint::Local) {
221 anyhow::bail!("build-igvm is for local use only")
222 }
223
224 bail_if_running_in_ci()?;
225
226 let openvmm_repo = flowey_lib_common::git_checkout::RepoSource::ExistingClone(
227 ReadVar::from_static(crate::repo_root()),
228 );
229
230 let Self {
231 recipe,
232 release,
233 verbose,
234 locked,
235 install_missing_deps,
236 customizations:
237 BuildIgvmCliCustomizations {
238 build_label,
239 override_kernel_pkg,
240 override_openvmm_hcl_feature,
241 override_arch,
242 override_manifest,
243 with_perf_tools,
244 with_debuginfo,
245 custom_openvmm_hcl,
246 custom_openhcl_boot,
247 custom_uefi,
248 custom_kernel,
249 custom_kernel_modules,
250 custom_vtl0_kernel,
251 custom_layer,
252 custom_directory,
253 with_sidecar,
254 custom_sidecar,
255 mut custom_extra_rootfs,
256 },
257 } = self;
258
259 if with_perf_tools {
260 custom_extra_rootfs.push(
261 crate::repo_root()
262 .join("openhcl/perftoolsfs.config")
263 .clone(),
264 );
265 }
266
267 let mut pipeline = Pipeline::new();
268
269 let (pub_out_dir, _) = pipeline.new_artifact("build-igvm");
270
271 pipeline
272 .new_job(
273 FlowPlatform::host(backend_hint),
274 FlowArch::host(backend_hint),
275 "build-igvm",
276 )
277 .dep_on(|_| flowey_lib_hvlite::_jobs::cfg_versions::Request {})
278 .dep_on(
279 |_| flowey_lib_hvlite::_jobs::cfg_hvlite_reposource::Params {
280 hvlite_repo_source: openvmm_repo,
281 },
282 )
283 .dep_on(|_| flowey_lib_hvlite::_jobs::cfg_common::Params {
284 local_only: Some(flowey_lib_hvlite::_jobs::cfg_common::LocalOnlyParams {
285 interactive: true,
286 auto_install: install_missing_deps,
287 force_nuget_mono: false, // no oss nuget packages
288 external_nuget_auth: false,
289 ignore_rust_version: true,
290 }),
291 verbose: ReadVar::from_static(verbose),
292 locked,
293 deny_warnings: false,
294 })
295 .dep_on(|ctx| flowey_lib_hvlite::_jobs::local_build_igvm::Params {
296 artifact_dir: ctx.publish_artifact(pub_out_dir),
297 done: ctx.new_done_handle(),
298
299 base_recipe: match recipe {
300 OpenhclRecipeCli::X64 => OpenhclIgvmRecipe::X64,
301 OpenhclRecipeCli::X64Devkern => OpenhclIgvmRecipe::X64Devkern,
302 OpenhclRecipeCli::X64TestLinuxDirect => OpenhclIgvmRecipe::X64TestLinuxDirect,
303 OpenhclRecipeCli::X64TestLinuxDirectDevkern => {
304 OpenhclIgvmRecipe::X64TestLinuxDirectDevkern
305 }
306 OpenhclRecipeCli::X64Cvm => OpenhclIgvmRecipe::X64Cvm,
307 OpenhclRecipeCli::X64CvmDevkern => OpenhclIgvmRecipe::X64CvmDevkern,
308 OpenhclRecipeCli::Aarch64 => OpenhclIgvmRecipe::Aarch64,
309 OpenhclRecipeCli::Aarch64Devkern => OpenhclIgvmRecipe::Aarch64Devkern,
310 },
311 release,
312
313 customizations: flowey_lib_hvlite::_jobs::local_build_igvm::Customizations {
314 build_label,
315 override_arch: override_arch.map(|a| match a {
316 BuildIgvmArch::X86_64 => CommonArch::X86_64,
317 BuildIgvmArch::Aarch64 => CommonArch::Aarch64,
318 }),
319 with_perf_tools,
320 with_debuginfo,
321 override_kernel_pkg: override_kernel_pkg.map(|p| match p {
322 KernelPackageKindCli::Main => OpenhclKernelPackage::Main,
323 KernelPackageKindCli::Cvm => OpenhclKernelPackage::Cvm,
324 KernelPackageKindCli::Dev => OpenhclKernelPackage::Dev,
325 KernelPackageKindCli::CvmDev => OpenhclKernelPackage::CvmDev,
326 }),
327 with_sidecar,
328 custom_extra_rootfs,
329 override_openvmm_hcl_feature,
330 custom_sidecar,
331 override_manifest,
332 custom_openvmm_hcl,
333 custom_openhcl_boot,
334 custom_uefi,
335 custom_kernel,
336 custom_kernel_modules,
337 custom_vtl0_kernel,
338 custom_layer,
339 custom_directory,
340 },
341 })
342 .finish();
343
344 Ok(pipeline)
345 }
346}
347