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::Nix => "python3",
69 FlowPlatformLinuxDistro::Arch => "python",
70 FlowPlatformLinuxDistro::Unknown => anyhow::bail!("Unknown Linux distribution"),
71 },
72 _ => anyhow::bail!("Unsupported platform"),
73 };
74
75 let pydeps = if !matches!(platform, FlowPlatform::Linux(FlowPlatformLinuxDistro::Nix)) {
77 Some(ctx.reqv(
78 |side_effect| flowey_lib_common::install_dist_pkg::Request::Install {
79 package_names: [python_pkg].map(Into::into).into(),
80 done: side_effect,
81 },
82 ))
83 } else {
84 None
85 };
86
87 let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir);
88
89 for Request {
90 arch,
91 extra_params,
92 rootfs_config,
93 kernel_package_root,
94 kernel_modules,
95 kernel_metadata,
96 extra_env,
97 bin_openhcl,
98 initrd,
99 interactive,
100 } in requests
101 {
102 let OpenhclInitrdExtraParams {
103 extra_initrd_layers,
104 extra_initrd_directories,
105 } = extra_params.unwrap_or_default();
106
107 let interactive_dep = if interactive {
108 ctx.reqv(|v| {
109 crate::resolve_openvmm_deps::Request::Get(
110 crate::resolve_openvmm_deps::OpenvmmDepFile::OpenhclCpioDbgrd,
111 arch,
112 v,
113 )
114 })
115 } else {
116 ctx.reqv(|v| {
117 crate::resolve_openvmm_deps::Request::Get(
118 crate::resolve_openvmm_deps::OpenvmmDepFile::OpenhclCpioShell,
119 arch,
120 v,
121 )
122 })
123 };
124
125 if rootfs_config.is_empty() {
126 anyhow::bail!("no rootfs files provided");
127 }
128
129 ctx.emit_rust_step("building openhcl initrd", |ctx| {
130 pydeps.clone().claim(ctx);
131 let interactive_dep = interactive_dep.claim(ctx);
132 let rootfs_config = rootfs_config.claim(ctx);
133 let extra_env = extra_env.claim(ctx);
134 let bin_openhcl = bin_openhcl.claim(ctx);
135 let openvmm_repo_path = openvmm_repo_path.clone().claim(ctx);
136 let kernel_package_root = kernel_package_root.claim(ctx);
137 let kernel_modules = kernel_modules.claim(ctx);
138 let kernel_metadata = kernel_metadata.claim(ctx);
139 let initrd = initrd.claim(ctx);
140 move |rt| {
141 let interactive_dep = rt.read(interactive_dep);
142 let rootfs_config = rt.read(rootfs_config);
143 let extra_env = rt.read(extra_env);
144 let bin_openhcl = rt.read(bin_openhcl);
145 let openvmm_repo_path = rt.read(openvmm_repo_path);
146 let kernel_package_root = rt.read(kernel_package_root);
147 let kernel_metadata = rt.read(kernel_metadata);
148
149 let initrd_path = rt.sh.current_dir().join("openhcl.cpio.gz");
150
151 let initrd_contents = {
152 let mut v = Vec::new();
153
154 if interactive {
155 v.push("--interactive".to_string());
157 } else {
158 v.push("--min-interactive".to_string());
160 }
161
162 for dir in extra_initrd_layers {
163 v.push("--layer".into());
164 v.push(dir.display().to_string());
165 }
166
167 for dir in extra_initrd_directories {
168 v.push("--add-dir".into());
169 v.push(dir.display().to_string());
170 }
171
172 v
173 };
174
175 let rootfs_py_arch = match arch {
176 CommonArch::X86_64 => "x86_64",
177 CommonArch::Aarch64 => "aarch64",
178 };
179
180 let kernel_modules = rt.read(kernel_modules);
181
182 match arch {
187 CommonArch::X86_64 => {
188 rt.sh
189 .set_var("OPENVMM_DEPS_X64", interactive_dep.parent().unwrap());
190 }
191 CommonArch::Aarch64 => {
192 rt.sh
193 .set_var("OPENVMM_DEPS_AARCH64", interactive_dep.parent().unwrap());
194 }
195 }
196
197 for (k, v) in extra_env.into_iter().flatten() {
198 rt.sh.set_var(k, v);
199 }
200
201 rt.sh.change_dir(openvmm_repo_path);
204
205 let rootfs_config = rootfs_config
206 .iter()
207 .flat_map(|x| ["--rootfs-config".as_ref(), x.as_os_str()]);
208
209 flowey::shell_cmd!(
210 rt,
211 "python3 openhcl/update-rootfs.py
212 {bin_openhcl}
213 {initrd_path}
214 --arch {rootfs_py_arch}
215 --package-root {kernel_package_root}
216 --kernel-modules {kernel_modules}
217 --kernel-metadata {kernel_metadata}
218 {rootfs_config...}
219 {initrd_contents...}
220 "
221 )
222 .run()?;
223
224 rt.write(
225 initrd,
226 &OpenhclInitrdOutput {
227 initrd: initrd_path,
228 },
229 );
230
231 Ok(())
232 }
233 });
234 }
235
236 Ok(())
237 }
238}