flowey_lib_hvlite/
resolve_openvmm_deps.rs1use crate::common::CommonArch;
7use flowey::node::prelude::*;
8use std::collections::BTreeMap;
9
10#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
12pub enum OpenvmmDepFile {
13 LinuxTestKernel,
14 LinuxTestInitrd,
15 OpenhclCpioDbgrd,
16 OpenhclCpioShell,
17 OpenhclSysroot,
18 PetritoolsErofs,
19}
20
21impl OpenvmmDepFile {
22 pub fn filename(self, arch: CommonArch) -> &'static str {
23 match self {
24 Self::LinuxTestKernel => match arch {
25 CommonArch::X86_64 => "vmlinux",
26 CommonArch::Aarch64 => "Image",
27 },
28 Self::LinuxTestInitrd => "initrd",
29 Self::OpenhclCpioDbgrd => "dbgrd.cpio.gz",
30 Self::OpenhclCpioShell => "shell.cpio.gz",
31 Self::OpenhclSysroot => "sysroot.tar.gz",
32 Self::PetritoolsErofs => "petritools.erofs",
33 }
34 }
35}
36
37flowey_config! {
38 pub struct Config {
40 pub version: Option<String>,
42 pub local_paths: BTreeMap<CommonArch, ConfigVar<PathBuf>>,
44 }
45}
46
47flowey_request! {
48 pub enum Request {
49 Get(OpenvmmDepFile, CommonArch, WriteVar<PathBuf>),
51 }
52}
53
54new_flow_node_with_config!(struct Node);
55
56impl FlowNodeWithConfig for Node {
57 type Request = Request;
58 type Config = Config;
59
60 fn imports(ctx: &mut ImportCtx<'_>) {
61 ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
62 ctx.import::<flowey_lib_common::download_gh_release::Node>();
63 }
64
65 fn emit(
66 config: Config,
67 requests: Vec<Self::Request>,
68 ctx: &mut NodeCtx<'_>,
69 ) -> anyhow::Result<()> {
70 let version = config.version;
71 let local_paths = config.local_paths;
72 let mut deps: BTreeMap<(OpenvmmDepFile, CommonArch), Vec<WriteVar<PathBuf>>> =
73 BTreeMap::new();
74
75 for req in requests {
76 match req {
77 Request::Get(dep, arch, var) => {
78 deps.entry((dep, arch)).or_default().push(var);
79 }
80 }
81 }
82
83 if version.is_some() && !local_paths.is_empty() {
84 anyhow::bail!("Cannot specify both Version and LocalPath requests");
85 }
86
87 if version.is_none() && local_paths.is_empty() {
88 anyhow::bail!("Must specify a Version or LocalPath request");
89 }
90
91 if deps.is_empty() {
94 return Ok(());
95 }
96
97 let needs_arch = |arch: CommonArch| deps.keys().any(|(_, a)| *a == arch);
99
100 if !local_paths.is_empty() {
101 ctx.emit_rust_step("use local openvmm-deps", |ctx| {
102 let deps = deps.claim(ctx);
103 let local_paths: BTreeMap<_, _> = local_paths
104 .into_iter()
105 .map(|(arch, var)| (arch, var.claim(ctx)))
106 .collect();
107 move |rt| {
108 let resolved_paths: BTreeMap<CommonArch, PathBuf> = local_paths
109 .into_iter()
110 .map(|(arch, var)| (arch, rt.read(var)))
111 .collect();
112
113 for ((dep, arch), vars) in deps {
114 let base_dir = resolved_paths.get(&arch).ok_or_else(|| {
115 anyhow::anyhow!("No local path specified for architecture {:?}", arch)
116 })?;
117 let path = base_dir.join(dep.filename(arch));
118 rt.write_all(vars, &path)
119 }
120
121 Ok(())
122 }
123 });
124
125 return Ok(());
126 }
127
128 let extract_tar_bz2_deps =
129 flowey_lib_common::_util::extract::extract_tar_bz2_if_new_deps(ctx);
130
131 let download_archive = |arch: CommonArch, ctx: &mut NodeCtx<'_>| {
132 let version = version.clone().expect("local requests handled above");
133 let arch_str = match arch {
134 CommonArch::X86_64 => "x86_64",
135 CommonArch::Aarch64 => "aarch64",
136 };
137 ctx.reqv(|v| flowey_lib_common::download_gh_release::Request {
138 repo_owner: "microsoft".into(),
139 repo_name: "openvmm-deps".into(),
140 needs_auth: false,
141 tag: version.clone(),
142 file_name: format!("openvmm-deps.{arch_str}.{version}.tar.bz2"),
143 path: v,
144 })
145 };
146
147 let openvmm_deps_tar_bz2_x64 =
148 needs_arch(CommonArch::X86_64).then(|| download_archive(CommonArch::X86_64, ctx));
149 let openvmm_deps_tar_bz2_aarch64 =
150 needs_arch(CommonArch::Aarch64).then(|| download_archive(CommonArch::Aarch64, ctx));
151
152 ctx.emit_rust_step("unpack openvmm-deps archive", |ctx| {
153 let extract_tar_bz2_deps = extract_tar_bz2_deps.claim(ctx);
154 let openvmm_deps_tar_bz2_x64 = openvmm_deps_tar_bz2_x64.claim(ctx);
155 let openvmm_deps_tar_bz2_aarch64 = openvmm_deps_tar_bz2_aarch64.claim(ctx);
156 let deps = deps.claim(ctx);
157 let version = version.clone().expect("local requests handled above");
158 move |rt| {
159 let extract_dir_x64 = openvmm_deps_tar_bz2_x64
160 .map(|file| {
161 let file = rt.read(file);
162 flowey_lib_common::_util::extract::extract_tar_bz2_if_new(
163 rt,
164 extract_tar_bz2_deps.clone(),
165 &file,
166 &version,
167 )
168 })
169 .transpose()?;
170 let extract_dir_aarch64 = openvmm_deps_tar_bz2_aarch64
171 .map(|file| {
172 let file = rt.read(file);
173 flowey_lib_common::_util::extract::extract_tar_bz2_if_new(
174 rt,
175 extract_tar_bz2_deps.clone(),
176 &file,
177 &version,
178 )
179 })
180 .transpose()?;
181
182 let base_dir = |arch| match arch {
183 CommonArch::X86_64 => extract_dir_x64.clone().unwrap(),
184 CommonArch::Aarch64 => extract_dir_aarch64.clone().unwrap(),
185 };
186
187 for ((dep, arch), vars) in deps {
188 let path = base_dir(arch).join(dep.filename(arch));
189 rt.write_all(vars, &path)
190 }
191
192 Ok(())
193 }
194 });
195
196 Ok(())
197 }
198}