flowey_lib_hvlite/
build_openhcl_initrd.rs1use crate::download_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 pub custom_kernel_modules: Option<PathBuf>,
26}
27
28flowey_request! {
29 pub struct Request {
30 pub arch: CommonArch,
31 pub interactive: bool,
33 pub extra_params: Option<OpenhclInitrdExtraParams>,
35 pub rootfs_config: Vec<ReadVar<PathBuf>>,
37 pub extra_env: Option<ReadVar<BTreeMap<String, String>>>,
40 pub kernel_package_root: 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::download_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 | FlowPlatformLinuxDistro::Ubuntu => "python3",
66 FlowPlatformLinuxDistro::Arch => "python",
67 FlowPlatformLinuxDistro::Unknown => anyhow::bail!("Unknown Linux distribution"),
68 },
69 _ => anyhow::bail!("Unsupported platform"),
70 };
71 let pydeps =
72 ctx.reqv(
73 |side_effect| flowey_lib_common::install_dist_pkg::Request::Install {
74 package_names: [python_pkg].map(Into::into).into(),
75 done: side_effect,
76 },
77 );
78
79 let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir);
80
81 for Request {
82 arch,
83 extra_params,
84 rootfs_config,
85 kernel_package_root,
86 extra_env,
87 bin_openhcl,
88 initrd,
89 interactive,
90 } in requests
91 {
92 let OpenhclInitrdExtraParams {
93 extra_initrd_layers,
94 extra_initrd_directories,
95 custom_kernel_modules,
96 } = extra_params.unwrap_or_default();
97
98 let openvmm_deps_arch = match arch {
99 CommonArch::X86_64 => OpenvmmDepsArch::X86_64,
100 CommonArch::Aarch64 => OpenvmmDepsArch::Aarch64,
101 };
102
103 let interactive_dep = if interactive {
104 ctx.reqv(|v| {
105 crate::download_openvmm_deps::Request::GetOpenhclCpioDbgrd(openvmm_deps_arch, v)
106 })
107 } else {
108 ctx.reqv(|v| {
109 crate::download_openvmm_deps::Request::GetOpenhclCpioShell(openvmm_deps_arch, v)
110 })
111 };
112
113 if rootfs_config.is_empty() {
114 anyhow::bail!("no rootfs files provided");
115 }
116
117 ctx.emit_rust_step("building openhcl initrd", |ctx| {
118 pydeps.clone().claim(ctx);
119 let interactive_dep = interactive_dep.claim(ctx);
120 let rootfs_config = rootfs_config.claim(ctx);
121 let extra_env = extra_env.claim(ctx);
122 let bin_openhcl = bin_openhcl.claim(ctx);
123 let openvmm_repo_path = openvmm_repo_path.clone().claim(ctx);
124 let kernel_package_root = kernel_package_root.claim(ctx);
125 let initrd = initrd.claim(ctx);
126 move |rt| {
127 let interactive_dep = rt.read(interactive_dep);
128 let rootfs_config = rt.read(rootfs_config);
129 let extra_env = rt.read(extra_env);
130 let bin_openhcl = rt.read(bin_openhcl);
131 let openvmm_repo_path = rt.read(openvmm_repo_path);
132 let kernel_package_root = rt.read(kernel_package_root);
133
134 let sh = xshell::Shell::new()?;
135
136 let initrd_path = sh.current_dir().join("openhcl.cpio.gz");
137
138 let initrd_contents = {
139 let mut v = Vec::new();
140
141 if interactive {
142 v.push("--interactive".to_string());
144 } else {
145 v.push("--min-interactive".to_string());
147 }
148
149 for dir in extra_initrd_layers {
150 v.push("--layer".into());
151 v.push(dir.display().to_string());
152 }
153
154 for dir in extra_initrd_directories {
155 v.push("--add-dir".into());
156 v.push(dir.display().to_string());
157 }
158
159 v
160 };
161
162 let kernel_modules =
163 custom_kernel_modules.unwrap_or(kernel_package_root.join("."));
164
165 let rootfs_py_arch = match arch {
166 CommonArch::X86_64 => "x86_64",
167 CommonArch::Aarch64 => "aarch64",
168 };
169
170 match arch {
175 CommonArch::X86_64 => {
176 sh.set_var("OPENVMM_DEPS_X64", interactive_dep.parent().unwrap());
177 }
178 CommonArch::Aarch64 => {
179 sh.set_var("OPENVMM_DEPS_AARCH64", interactive_dep.parent().unwrap());
180 }
181 }
182
183 for (k, v) in extra_env.into_iter().flatten() {
184 sh.set_var(k, v);
185 }
186
187 sh.change_dir(openvmm_repo_path);
190
191 let rootfs_config = rootfs_config
192 .iter()
193 .flat_map(|x| ["--rootfs-config".as_ref(), x.as_os_str()]);
194
195 xshell::cmd!(
196 sh,
197 "python3 openhcl/update-rootfs.py
198 {bin_openhcl}
199 {initrd_path}
200 --arch {rootfs_py_arch}
201 --package-root {kernel_package_root}
202 --kernel-modules {kernel_modules}
203 {rootfs_config...}
204 {initrd_contents...}
205 "
206 )
207 .run()?;
208
209 rt.write(
210 initrd,
211 &OpenhclInitrdOutput {
212 initrd: initrd_path,
213 },
214 );
215
216 Ok(())
217 }
218 });
219 }
220
221 Ok(())
222 }
223}