flowey_lib_hvlite/
build_openhcl_initrd.rs1use crate::resolve_openvmm_deps::OpenvmmDepsArch;
7use crate::run_cargo_build::common::CommonArch;
8use flowey::node::prelude::*;
9use std::collections::BTreeMap;
10
11#[derive(Serialize, Deserialize)]
12pub struct OpenhclInitrdOutput {
13 pub initrd: PathBuf,
14}
15
16#[derive(Default, Clone, Serialize, Deserialize, Debug)]
18pub struct OpenhclInitrdExtraParams {
19 pub extra_initrd_layers: Vec<PathBuf>,
21 pub extra_initrd_directories: Vec<PathBuf>,
23}
24
25flowey_request! {
26 pub struct Request {
27 pub arch: CommonArch,
28 pub interactive: bool,
30 pub extra_params: Option<OpenhclInitrdExtraParams>,
32 pub rootfs_config: Vec<ReadVar<PathBuf>>,
34 pub extra_env: Option<ReadVar<BTreeMap<String, String>>>,
37 pub kernel_package_root: ReadVar<PathBuf>,
39 pub kernel_modules: ReadVar<PathBuf>,
41 pub kernel_metadata: ReadVar<PathBuf>,
43 pub bin_openhcl: ReadVar<PathBuf>,
45 pub initrd: WriteVar<OpenhclInitrdOutput>,
47 }
48}
49
50new_flow_node!(struct Node);
51
52impl FlowNode for Node {
53 type Request = Request;
54
55 fn imports(ctx: &mut ImportCtx<'_>) {
56 ctx.import::<crate::resolve_openvmm_deps::Node>();
57 ctx.import::<crate::git_checkout_openvmm_repo::Node>();
58 ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
59 }
60
61 fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
62 let platform = ctx.platform();
64 let python_pkg = match platform {
65 FlowPlatform::Linux(linux_distribution) => match linux_distribution {
66 FlowPlatformLinuxDistro::Fedora
67 | FlowPlatformLinuxDistro::Ubuntu
68 | FlowPlatformLinuxDistro::AzureLinux
69 | FlowPlatformLinuxDistro::Nix => "python3",
70 FlowPlatformLinuxDistro::Arch => "python",
71 FlowPlatformLinuxDistro::Unknown => anyhow::bail!("Unknown Linux distribution"),
72 },
73 _ => anyhow::bail!("Unsupported platform"),
74 };
75
76 let pydeps = if !matches!(platform, FlowPlatform::Linux(FlowPlatformLinuxDistro::Nix)) {
78 Some(ctx.reqv(
79 |side_effect| flowey_lib_common::install_dist_pkg::Request::Install {
80 package_names: [python_pkg].map(Into::into).into(),
81 done: side_effect,
82 },
83 ))
84 } else {
85 None
86 };
87
88 let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir);
89
90 for Request {
91 arch,
92 extra_params,
93 rootfs_config,
94 kernel_package_root,
95 kernel_modules,
96 kernel_metadata,
97 extra_env,
98 bin_openhcl,
99 initrd,
100 interactive,
101 } in requests
102 {
103 let OpenhclInitrdExtraParams {
104 extra_initrd_layers,
105 extra_initrd_directories,
106 } = extra_params.unwrap_or_default();
107
108 let openvmm_deps_arch = match arch {
109 CommonArch::X86_64 => OpenvmmDepsArch::X86_64,
110 CommonArch::Aarch64 => OpenvmmDepsArch::Aarch64,
111 };
112
113 let interactive_dep = if interactive {
114 ctx.reqv(|v| {
115 crate::resolve_openvmm_deps::Request::GetOpenhclCpioDbgrd(openvmm_deps_arch, v)
116 })
117 } else {
118 ctx.reqv(|v| {
119 crate::resolve_openvmm_deps::Request::GetOpenhclCpioShell(openvmm_deps_arch, v)
120 })
121 };
122
123 if rootfs_config.is_empty() {
124 anyhow::bail!("no rootfs files provided");
125 }
126
127 ctx.emit_rust_step("building openhcl initrd", |ctx| {
128 pydeps.clone().claim(ctx);
129 let interactive_dep = interactive_dep.claim(ctx);
130 let rootfs_config = rootfs_config.claim(ctx);
131 let extra_env = extra_env.claim(ctx);
132 let bin_openhcl = bin_openhcl.claim(ctx);
133 let openvmm_repo_path = openvmm_repo_path.clone().claim(ctx);
134 let kernel_package_root = kernel_package_root.claim(ctx);
135 let kernel_modules = kernel_modules.claim(ctx);
136 let kernel_metadata = kernel_metadata.claim(ctx);
137 let initrd = initrd.claim(ctx);
138 move |rt| {
139 let interactive_dep = rt.read(interactive_dep);
140 let rootfs_config = rt.read(rootfs_config);
141 let extra_env = rt.read(extra_env);
142 let bin_openhcl = rt.read(bin_openhcl);
143 let openvmm_repo_path = rt.read(openvmm_repo_path);
144 let kernel_package_root = rt.read(kernel_package_root);
145 let kernel_metadata = rt.read(kernel_metadata);
146
147 let initrd_path = rt.sh.current_dir().join("openhcl.cpio.gz");
148
149 let initrd_contents = {
150 let mut v = Vec::new();
151
152 if interactive {
153 v.push("--interactive".to_string());
155 } else {
156 v.push("--min-interactive".to_string());
158 }
159
160 for dir in extra_initrd_layers {
161 v.push("--layer".into());
162 v.push(dir.display().to_string());
163 }
164
165 for dir in extra_initrd_directories {
166 v.push("--add-dir".into());
167 v.push(dir.display().to_string());
168 }
169
170 v
171 };
172
173 let rootfs_py_arch = match arch {
174 CommonArch::X86_64 => "x86_64",
175 CommonArch::Aarch64 => "aarch64",
176 };
177
178 let kernel_modules = rt.read(kernel_modules);
179
180 match arch {
185 CommonArch::X86_64 => {
186 rt.sh
187 .set_var("OPENVMM_DEPS_X64", interactive_dep.parent().unwrap());
188 }
189 CommonArch::Aarch64 => {
190 rt.sh
191 .set_var("OPENVMM_DEPS_AARCH64", interactive_dep.parent().unwrap());
192 }
193 }
194
195 for (k, v) in extra_env.into_iter().flatten() {
196 rt.sh.set_var(k, v);
197 }
198
199 rt.sh.change_dir(openvmm_repo_path);
202
203 let rootfs_config = rootfs_config
204 .iter()
205 .flat_map(|x| ["--rootfs-config".as_ref(), x.as_os_str()]);
206
207 flowey::shell_cmd!(
208 rt,
209 "python3 openhcl/update-rootfs.py
210 {bin_openhcl}
211 {initrd_path}
212 --arch {rootfs_py_arch}
213 --package-root {kernel_package_root}
214 --kernel-modules {kernel_modules}
215 --kernel-metadata {kernel_metadata}
216 {rootfs_config...}
217 {initrd_contents...}
218 "
219 )
220 .run()?;
221
222 rt.write(
223 initrd,
224 &OpenhclInitrdOutput {
225 initrd: initrd_path,
226 },
227 );
228
229 Ok(())
230 }
231 });
232 }
233
234 Ok(())
235 }
236}