flowey_lib_hvlite/
run_vmm_perf.rs1use flowey::node::prelude::*;
7
8pub fn all_profiles() -> Vec<String> {
9 vec![
10 "boot-time".into(),
11 "fio:vmbus".into(),
12 "fio:virtio".into(),
13 "iperf3:vmbus".into(),
14 "iperf3:virtio".into(),
15 ]
16}
17
18pub fn default_profiles() -> Vec<String> {
19 vec!["boot-time".into(), "fio".into(), "iperf3".into()]
20}
21
22#[derive(Clone, Debug, Serialize, Deserialize)]
23pub struct VmmPerfRunOutput {
24 pub results_dir: PathBuf,
25 pub success: bool,
26 pub exit_code: Option<i32>,
27}
28
29flowey_request! {
30 pub struct Request {
31 pub runner: ReadVar<crate::build_vmm_perf::VmmPerfOutput>,
32 pub openvmm: ReadVar<crate::build_openvmm::OpenvmmOutput>,
33 pub firmware: ReadVar<PathBuf>,
34 pub runtime_archive: ReadVar<PathBuf>,
35 pub output_dir: ReadVar<PathBuf>,
36 pub temp_dir: Option<ReadVar<PathBuf>>,
37 pub profiles: Vec<String>,
38 pub vm_sizes_json: Option<String>,
39 pub parameters_json: Option<String>,
40 pub pre_run_deps: Vec<ReadVar<SideEffect>>,
42 pub output: WriteVar<VmmPerfRunOutput>,
43 }
44}
45
46new_simple_flow_node!(struct Node);
47
48impl SimpleFlowNode for Node {
49 type Request = Request;
50
51 fn imports(_ctx: &mut ImportCtx<'_>) {}
52
53 fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
54 let Request {
55 runner,
56 openvmm,
57 firmware,
58 runtime_archive,
59 output_dir,
60 temp_dir,
61 profiles,
62 vm_sizes_json,
63 parameters_json,
64 pre_run_deps,
65 output,
66 } = request;
67
68 ctx.emit_rust_step("run VMM.Perf", |ctx| {
69 pre_run_deps.claim(ctx);
70 let runner = runner.claim(ctx);
71 let openvmm = openvmm.claim(ctx);
72 let firmware = firmware.claim(ctx);
73 let runtime_archive = runtime_archive.claim(ctx);
74 let output_dir = output_dir.claim(ctx);
75 let temp_dir = temp_dir.map(|temp_dir| temp_dir.claim(ctx));
76 let output = output.claim(ctx);
77
78 move |rt| {
79 let runner = match rt.read(runner) {
80 crate::build_vmm_perf::VmmPerfOutput::LinuxBin { bin, .. } => bin,
81 crate::build_vmm_perf::VmmPerfOutput::WindowsBin { exe, .. } => exe,
82 };
83 let openvmm = match rt.read(openvmm) {
84 crate::build_openvmm::OpenvmmOutput::LinuxBin { bin, .. } => bin,
85 crate::build_openvmm::OpenvmmOutput::WindowsBin { exe, .. } => exe,
86 };
87 let firmware = rt.read(firmware);
88 let runtime_archive = rt.read(runtime_archive);
89 let output_dir = rt.read(output_dir).absolute()?;
90 let temp_dir = temp_dir
91 .map(|temp_dir| rt.read(temp_dir).absolute())
92 .transpose()?;
93
94 runner.make_executable()?;
95 openvmm.make_executable()?;
96 fs_err::create_dir_all(&output_dir)?;
97 if let Some(temp_dir) = &temp_dir {
98 fs_err::create_dir_all(temp_dir)?;
99 }
100
101 let mut args = vec![
102 "--openvmm".to_string(),
103 openvmm.display().to_string(),
104 "--firmware".to_string(),
105 firmware.display().to_string(),
106 "--runtime-archive".to_string(),
107 runtime_archive.display().to_string(),
108 "--output-dir".to_string(),
109 output_dir.display().to_string(),
110 ];
111 if let Some(temp_dir) = &temp_dir {
112 args.push("--temp-dir".into());
113 args.push(temp_dir.display().to_string());
114 }
115 for profile in &profiles {
116 args.push("--profile".into());
117 args.push(profile.clone());
118 }
119 if let Some(vm_sizes_json) = &vm_sizes_json {
120 args.push("--vm-sizes-json".into());
121 args.push(vm_sizes_json.clone());
122 }
123 if let Some(parameters_json) = ¶meters_json {
124 args.push("--parameters-json".into());
125 args.push(parameters_json.clone());
126 }
127
128 let process = flowey::shell_cmd!(rt, "{runner} {args...}")
129 .ignore_status()
130 .output()?;
131 if !process.stdout.is_empty() {
132 log::info!("{}", String::from_utf8_lossy(&process.stdout));
133 }
134 if !process.stderr.is_empty() {
135 log::warn!("{}", String::from_utf8_lossy(&process.stderr));
136 }
137
138 rt.write(
139 output,
140 &VmmPerfRunOutput {
141 results_dir: output_dir,
142 success: process.status.success(),
143 exit_code: process.status.code(),
144 },
145 );
146 Ok(())
147 }
148 });
149
150 Ok(())
151 }
152}