1use flowey::node::prelude::*;
7use std::collections::BTreeMap;
8
9#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
10pub enum OpenvmmDepsArch {
11 X86_64,
12 Aarch64,
13}
14
15flowey_request! {
16 pub enum Request {
17 LocalPath(OpenvmmDepsArch, PathBuf),
19 Version(String),
21 GetLinuxTestKernel(OpenvmmDepsArch, WriteVar<PathBuf>),
22 GetLinuxTestInitrd(OpenvmmDepsArch, WriteVar<PathBuf>),
23 GetOpenhclCpioDbgrd(OpenvmmDepsArch, WriteVar<PathBuf>),
24 GetOpenhclCpioShell(OpenvmmDepsArch, WriteVar<PathBuf>),
25 GetOpenhclSysroot(OpenvmmDepsArch, WriteVar<PathBuf>),
26 }
27}
28
29new_flow_node!(struct Node);
30
31impl FlowNode for Node {
32 type Request = Request;
33
34 fn imports(ctx: &mut ImportCtx<'_>) {
35 ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
36 ctx.import::<flowey_lib_common::download_gh_release::Node>();
37 }
38
39 fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
40 let mut version = None;
41 let mut local_paths: BTreeMap<OpenvmmDepsArch, PathBuf> = BTreeMap::new();
42 let mut linux_test_kernel: BTreeMap<_, Vec<_>> = BTreeMap::new();
43 let mut linux_test_initrd: BTreeMap<_, Vec<_>> = BTreeMap::new();
44 let mut openhcl_cpio_dbgrd: BTreeMap<_, Vec<_>> = BTreeMap::new();
45 let mut openhcl_cpio_shell: BTreeMap<_, Vec<_>> = BTreeMap::new();
46 let mut openhcl_sysroot: BTreeMap<_, Vec<_>> = BTreeMap::new();
47
48 for req in requests {
49 match req {
50 Request::Version(v) => same_across_all_reqs("Version", &mut version, v)?,
51 Request::LocalPath(arch, path) => {
52 if let Some(existing) = local_paths.get(&arch) {
53 if existing != &path {
54 anyhow::bail!(
55 "Conflicting LocalPath requests for {:?}: {:?} vs {:?}",
56 arch,
57 existing,
58 path
59 );
60 }
61 } else {
62 local_paths.insert(arch, path);
63 }
64 }
65 Request::GetLinuxTestKernel(arch, var) => {
66 linux_test_kernel.entry(arch).or_default().push(var)
67 }
68 Request::GetLinuxTestInitrd(arch, var) => {
69 linux_test_initrd.entry(arch).or_default().push(var)
70 }
71 Request::GetOpenhclCpioDbgrd(arch, var) => {
72 openhcl_cpio_dbgrd.entry(arch).or_default().push(var)
73 }
74 Request::GetOpenhclCpioShell(arch, var) => {
75 openhcl_cpio_shell.entry(arch).or_default().push(var)
76 }
77 Request::GetOpenhclSysroot(arch, var) => {
78 openhcl_sysroot.entry(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 linux_test_kernel.is_empty()
94 && linux_test_initrd.is_empty()
95 && openhcl_cpio_dbgrd.is_empty()
96 && openhcl_cpio_shell.is_empty()
97 && openhcl_sysroot.is_empty()
98 {
99 return Ok(());
100 }
101
102 if !local_paths.is_empty() {
103 ctx.emit_rust_step("use local openvmm-deps", |ctx| {
104 let linux_test_kernel = linux_test_kernel.claim(ctx);
105 let linux_test_initrd = linux_test_initrd.claim(ctx);
106 let openhcl_cpio_dbgrd = openhcl_cpio_dbgrd.claim(ctx);
107 let openhcl_cpio_shell = openhcl_cpio_shell.claim(ctx);
108 let openhcl_sysroot = openhcl_sysroot.claim(ctx);
109 let local_paths = local_paths.clone();
110 move |rt| {
111 let get_base_dir = |arch: OpenvmmDepsArch| {
112 local_paths.get(&arch).ok_or_else(|| {
113 anyhow::anyhow!("No local path specified for architecture {:?}", arch)
114 })
115 };
116
117 let kernel_file_name = |arch| match arch {
118 OpenvmmDepsArch::X86_64 => "vmlinux",
119 OpenvmmDepsArch::Aarch64 => "Image",
120 };
121
122 for (arch, vars) in linux_test_kernel {
123 let base_dir = get_base_dir(arch)?;
124 let path = base_dir.join(kernel_file_name(arch));
125 rt.write_all(vars, &path)
126 }
127
128 for (arch, vars) in linux_test_initrd {
129 let base_dir = get_base_dir(arch)?;
130 let path = base_dir.join("initrd");
131 rt.write_all(vars, &path)
132 }
133
134 for (arch, vars) in openhcl_cpio_dbgrd {
135 let base_dir = get_base_dir(arch)?;
136 let path = base_dir.join("dbgrd.cpio.gz");
137 rt.write_all(vars, &path)
138 }
139
140 for (arch, vars) in openhcl_cpio_shell {
141 let base_dir = get_base_dir(arch)?;
142 let path = base_dir.join("shell.cpio.gz");
143 rt.write_all(vars, &path)
144 }
145
146 for (arch, vars) in openhcl_sysroot {
147 let base_dir = get_base_dir(arch)?;
148 let path = base_dir.join("sysroot.tar.gz");
149 rt.write_all(vars, &path)
150 }
151
152 Ok(())
153 }
154 });
155
156 return Ok(());
157 }
158
159 let extract_tar_bz2_deps =
160 flowey_lib_common::_util::extract::extract_tar_bz2_if_new_deps(ctx);
161
162 let openvmm_deps_tar_bz2_x64 = if linux_test_initrd.contains_key(&OpenvmmDepsArch::X86_64)
163 || linux_test_kernel.contains_key(&OpenvmmDepsArch::X86_64)
164 || openhcl_cpio_dbgrd.contains_key(&OpenvmmDepsArch::X86_64)
165 || openhcl_cpio_shell.contains_key(&OpenvmmDepsArch::X86_64)
166 || openhcl_sysroot.contains_key(&OpenvmmDepsArch::X86_64)
167 {
168 let version = version.clone().expect("local requests handled above");
169 Some(
170 ctx.reqv(|v| flowey_lib_common::download_gh_release::Request {
171 repo_owner: "microsoft".into(),
172 repo_name: "openvmm-deps".into(),
173 needs_auth: false,
174 tag: version.clone(),
175 file_name: format!("openvmm-deps.x86_64.{version}.tar.bz2"),
176 path: v,
177 }),
178 )
179 } else {
180 None
181 };
182
183 let openvmm_deps_tar_bz2_aarch64 = if linux_test_initrd
184 .contains_key(&OpenvmmDepsArch::Aarch64)
185 || linux_test_kernel.contains_key(&OpenvmmDepsArch::Aarch64)
186 || openhcl_cpio_dbgrd.contains_key(&OpenvmmDepsArch::Aarch64)
187 || openhcl_cpio_shell.contains_key(&OpenvmmDepsArch::Aarch64)
188 || openhcl_sysroot.contains_key(&OpenvmmDepsArch::Aarch64)
189 {
190 let version = version.clone().expect("local requests handled above");
191 Some(
192 ctx.reqv(|v| flowey_lib_common::download_gh_release::Request {
193 repo_owner: "microsoft".into(),
194 repo_name: "openvmm-deps".into(),
195 needs_auth: false,
196 tag: version.clone(),
197 file_name: format!("openvmm-deps.aarch64.{version}.tar.bz2"),
198 path: v,
199 }),
200 )
201 } else {
202 None
203 };
204
205 ctx.emit_rust_step("unpack openvmm-deps archive", |ctx| {
206 let extract_tar_bz2_deps = extract_tar_bz2_deps.claim(ctx);
207 let openvmm_deps_tar_bz2_x64 = openvmm_deps_tar_bz2_x64.claim(ctx);
208 let openvmm_deps_tar_bz2_aarch64 = openvmm_deps_tar_bz2_aarch64.claim(ctx);
209
210 let linux_test_kernel = linux_test_kernel.claim(ctx);
211 let linux_test_initrd = linux_test_initrd.claim(ctx);
212 let openhcl_cpio_dbgrd = openhcl_cpio_dbgrd.claim(ctx);
213 let openhcl_cpio_shell = openhcl_cpio_shell.claim(ctx);
214 let openhcl_sysroot = openhcl_sysroot.claim(ctx);
215 let version = version.clone().expect("local requests handled above");
216 move |rt| {
217 let extract_dir_x64 = openvmm_deps_tar_bz2_x64
218 .map(|file| {
219 let file = rt.read(file);
220 flowey_lib_common::_util::extract::extract_tar_bz2_if_new(
221 rt,
222 extract_tar_bz2_deps.clone(),
223 &file,
224 &version,
225 )
226 })
227 .transpose()?;
228 let extract_dir_aarch64 = openvmm_deps_tar_bz2_aarch64
229 .map(|file| {
230 let file = rt.read(file);
231 flowey_lib_common::_util::extract::extract_tar_bz2_if_new(
232 rt,
233 extract_tar_bz2_deps.clone(),
234 &file,
235 &version,
236 )
237 })
238 .transpose()?;
239
240 let base_dir = move |arch| match arch {
241 OpenvmmDepsArch::X86_64 => extract_dir_x64.clone().unwrap(),
242 OpenvmmDepsArch::Aarch64 => extract_dir_aarch64.clone().unwrap(),
243 };
244
245 let kernel_file_name = |arch| match arch {
246 OpenvmmDepsArch::X86_64 => "vmlinux",
247 OpenvmmDepsArch::Aarch64 => "Image",
248 };
249
250 for (arch, vars) in linux_test_kernel {
251 let path = base_dir(arch).join(kernel_file_name(arch));
252 rt.write_all(vars, &path)
253 }
254
255 for (arch, vars) in linux_test_initrd {
256 let path = base_dir(arch).join("initrd");
257 rt.write_all(vars, &path)
258 }
259
260 for (arch, vars) in openhcl_cpio_dbgrd {
261 let path = base_dir(arch).join("dbgrd.cpio.gz");
262 rt.write_all(vars, &path)
263 }
264
265 for (arch, vars) in openhcl_cpio_shell {
266 let path = base_dir(arch).join("shell.cpio.gz");
267 rt.write_all(vars, &path)
268 }
269
270 for (arch, vars) in openhcl_sysroot {
271 let path = base_dir(arch).join("sysroot.tar.gz");
272 rt.write_all(vars, &path)
273 }
274
275 Ok(())
276 }
277 });
278
279 Ok(())
280 }
281}