flowey_lib_hvlite/
build_openhcl_initrd.rs1use crate::common::CommonArch;
7use flowey::node::prelude::*;
8use std::collections::BTreeMap;
9
10#[derive(Serialize, Deserialize)]
11pub struct OpenhclInitrdOutput {
12 pub initrd: PathBuf,
13}
14
15#[derive(Default, Clone, Serialize, Deserialize, Debug)]
17pub struct OpenhclInitrdExtraParams {
18 pub extra_initrd_layers: Vec<PathBuf>,
20 pub extra_initrd_directories: Vec<PathBuf>,
22}
23
24flowey_request! {
25 pub struct Request {
26 pub arch: CommonArch,
27 pub interactive: bool,
29 pub extra_params: Option<OpenhclInitrdExtraParams>,
31 pub rootfs_config: Vec<ReadVar<PathBuf>>,
33 pub extra_env: Option<ReadVar<BTreeMap<String, String>>>,
36 pub kernel_package_root: ReadVar<PathBuf>,
38 pub kernel_modules: ReadVar<PathBuf>,
40 pub kernel_metadata: ReadVar<PathBuf>,
42 pub bin_openhcl: ReadVar<PathBuf>,
44 pub initrd: WriteVar<OpenhclInitrdOutput>,
46 }
47}
48
49new_flow_node!(struct Node);
50
51impl FlowNode for Node {
52 type Request = Request;
53
54 fn imports(ctx: &mut ImportCtx<'_>) {
55 ctx.import::<crate::resolve_openvmm_deps::Node>();
56 ctx.import::<crate::git_checkout_openvmm_repo::Node>();
57 ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
58 }
59
60 fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
61 let platform = ctx.platform();
63 let python_pkg = match platform {
64 FlowPlatform::Linux(linux_distribution) => match linux_distribution {
65 FlowPlatformLinuxDistro::Fedora
66 | FlowPlatformLinuxDistro::Ubuntu
67 | FlowPlatformLinuxDistro::AzureLinux
68 | FlowPlatformLinuxDistro::OpenSuse
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 interactive_dep = if interactive {
109 ctx.reqv(|v| {
110 crate::resolve_openvmm_deps::Request::Get(
111 crate::resolve_openvmm_deps::OpenvmmDepFile::OpenhclCpioDbgrd,
112 arch,
113 v,
114 )
115 })
116 } else {
117 ctx.reqv(|v| {
118 crate::resolve_openvmm_deps::Request::Get(
119 crate::resolve_openvmm_deps::OpenvmmDepFile::OpenhclCpioShell,
120 arch,
121 v,
122 )
123 })
124 };
125
126 if rootfs_config.is_empty() {
127 anyhow::bail!("no rootfs files provided");
128 }
129
130 ctx.emit_rust_step("building openhcl initrd", |ctx| {
131 pydeps.clone().claim(ctx);
132 let interactive_dep = interactive_dep.claim(ctx);
133 let rootfs_config = rootfs_config.claim(ctx);
134 let extra_env = extra_env.claim(ctx);
135 let bin_openhcl = bin_openhcl.claim(ctx);
136 let openvmm_repo_path = openvmm_repo_path.clone().claim(ctx);
137 let kernel_package_root = kernel_package_root.claim(ctx);
138 let kernel_modules = kernel_modules.claim(ctx);
139 let kernel_metadata = kernel_metadata.claim(ctx);
140 let initrd = initrd.claim(ctx);
141 move |rt| {
142 let interactive_dep = rt.read(interactive_dep);
143 let rootfs_config = rt.read(rootfs_config);
144 let extra_env = rt.read(extra_env);
145 let bin_openhcl = rt.read(bin_openhcl);
146 let openvmm_repo_path = rt.read(openvmm_repo_path);
147 let kernel_package_root = rt.read(kernel_package_root);
148 let kernel_metadata = rt.read(kernel_metadata);
149
150 let initrd_path = rt.sh.current_dir().join("openhcl.cpio.gz");
151
152 let initrd_contents = {
153 let mut v = Vec::new();
154
155 if interactive {
156 v.push("--interactive".to_string());
158 } else {
159 v.push("--min-interactive".to_string());
161 }
162
163 for dir in extra_initrd_layers {
164 v.push("--layer".into());
165 v.push(dir.display().to_string());
166 }
167
168 for dir in extra_initrd_directories {
169 v.push("--add-dir".into());
170 v.push(dir.display().to_string());
171 }
172
173 v
174 };
175
176 let rootfs_py_arch = match arch {
177 CommonArch::X86_64 => "x86_64",
178 CommonArch::Aarch64 => "aarch64",
179 };
180
181 let kernel_modules = rt.read(kernel_modules);
182
183 match arch {
188 CommonArch::X86_64 => {
189 rt.sh
190 .set_var("OPENVMM_DEPS_X64", interactive_dep.parent().unwrap());
191 }
192 CommonArch::Aarch64 => {
193 rt.sh
194 .set_var("OPENVMM_DEPS_AARCH64", interactive_dep.parent().unwrap());
195 }
196 }
197
198 for (k, v) in extra_env.into_iter().flatten() {
199 rt.sh.set_var(k, v);
200 }
201
202 rt.sh.change_dir(openvmm_repo_path);
205
206 let rootfs_config = rootfs_config
207 .iter()
208 .flat_map(|x| ["--rootfs-config".as_ref(), x.as_os_str()]);
209
210 flowey::shell_cmd!(
211 rt,
212 "python3 openhcl/update-rootfs.py
213 {bin_openhcl}
214 {initrd_path}
215 --arch {rootfs_py_arch}
216 --package-root {kernel_package_root}
217 --kernel-modules {kernel_modules}
218 --kernel-metadata {kernel_metadata}
219 {rootfs_config...}
220 {initrd_contents...}
221 "
222 )
223 .run()?;
224
225 rt.write(
226 initrd,
227 &OpenhclInitrdOutput {
228 initrd: initrd_path,
229 },
230 );
231
232 Ok(())
233 }
234 });
235 }
236
237 Ok(())
238 }
239}