flowey_lib_hvlite/
run_test_igvm_agent_rpc_server.rs1use crate::build_test_igvm_agent_rpc_server::TestIgvmAgentRpcServerOutput;
18use flowey::node::prelude::*;
19use std::collections::BTreeMap;
20
21flowey_request! {
22 pub struct Request {
23 pub test_igvm_agent_rpc_server: ReadVar<TestIgvmAgentRpcServerOutput>,
25 pub env: ReadVar<BTreeMap<String, String>>,
27 pub done: WriteVar<SideEffect>,
29 pub previous_done: Option<ReadVar<SideEffect>>,
31 }
32}
33
34new_simple_flow_node!(struct Node);
35
36impl SimpleFlowNode for Node {
37 type Request = Request;
38
39 fn imports(_ctx: &mut ImportCtx<'_>) {}
40
41 fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
42 let Request {
43 test_igvm_agent_rpc_server,
44 env,
45 done,
46 previous_done,
47 } = request;
48
49 ctx.emit_rust_step("starting test_igvm_agent_rpc_server", |ctx| {
50 let test_igvm_agent_rpc_server = test_igvm_agent_rpc_server.claim(ctx);
51 let env = env.claim(ctx);
52 done.claim(ctx);
53 previous_done.claim(ctx);
54 move |rt| start_rpc_server(rt, test_igvm_agent_rpc_server, env)
55 });
56
57 Ok(())
58 }
59}
60
61fn start_rpc_server(
62 rt: &mut RustRuntimeServices<'_>,
63 test_igvm_agent_rpc_server: ReadVar<TestIgvmAgentRpcServerOutput, VarClaimed>,
64 env: ReadVar<BTreeMap<String, String>, VarClaimed>,
65) -> anyhow::Result<()> {
66 use std::path::Path;
67
68 let windows_via_wsl2 = flowey_lib_common::_util::running_in_wsl(rt);
69 if !matches!(rt.platform(), FlowPlatform::Windows) && !windows_via_wsl2 {
70 anyhow::bail!("run_test_igvm_agent_rpc_server only supports Windows or WSL2");
71 }
72
73 let env = rt.read(env);
74
75 let test_output_path = env
76 .get(petri_artifacts_vmm_test::env::TEST_OUTPUT_PATH)
77 .context("TEST_OUTPUT_PATH not set")?;
78
79 let TestIgvmAgentRpcServerOutput { exe, .. } = rt.read(test_igvm_agent_rpc_server);
80
81 let test_output_path = if windows_via_wsl2 {
83 flowey_lib_common::_util::wslpath::win_to_linux(rt, test_output_path)?
84 } else {
85 Path::new(test_output_path).to_path_buf()
86 };
87 let log_file_path = test_output_path.join("test_igvm_agent_rpc_server.log");
88 let log_file = std::fs::File::create(&log_file_path)?;
89 let log_file_stderr = log_file.try_clone()?;
90
91 log::info!(
92 "starting test_igvm_agent_rpc_server from {}, logs at: {}",
93 exe.display(),
94 log_file_path.display()
95 );
96
97 let mut command = std::process::Command::new(&exe);
98 command
99 .stdin(std::process::Stdio::null())
100 .stdout(log_file)
101 .stderr(log_file_stderr);
102
103 #[cfg(windows)]
104 {
105 use std::os::windows::process::CommandExt;
106
107 const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
109 command.creation_flags(CREATE_NEW_PROCESS_GROUP);
110 }
111
112 let mut child = command.spawn().with_context(|| {
113 format!(
114 "failed to spawn test_igvm_agent_rpc_server: {}",
115 exe.display()
116 )
117 })?;
118
119 std::thread::sleep(std::time::Duration::from_millis(500));
121
122 match child.try_wait()? {
124 Some(status) => {
125 anyhow::bail!(
126 "test_igvm_agent_rpc_server exited unexpectedly with status: {:?}. \
127 Check logs at: {}",
128 status.code(),
129 log_file_path.display()
130 );
131 }
132 None => {
133 log::info!(
134 "test_igvm_agent_rpc_server started successfully (pid: {})",
135 child.id()
136 );
137 }
138 }
139
140 drop(child);
144
145 Ok(())
146}