microsoft/openvmm

Public

mirrored fromhttps://github.com/microsoft/openvmmAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
e6c778cbebacf3a70be1d39295b4f090134c4091

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

petri/src/openhcl_diag.rs

122lines · modecode

1// Copyright (C) Microsoft Corporation. All rights reserved.
2
3use anyhow::Context;
4use diag_client::DiagClient;
5use diag_client::ExitStatus;
6use futures::io::AllowStdIo;
7use get_resources::ged::GuestEmulationRequest;
8use mesh::rpc::RpcSend;
9use mesh::Sender;
10use pal_async::DefaultDriver;
11use std::io::Read;
12use std::path::PathBuf;
13use std::sync::Arc;
14
15pub(crate) struct OpenHclDiagHandler {
16 pub(crate) vtl2_vsock_path: PathBuf,
17 pub(crate) ged_send: Arc<Sender<GuestEmulationRequest>>,
18}
19
20/// The result of running a VTL2 command.
21#[derive(Debug)]
22#[allow(dead_code)] // Fields output via Debug for debugging purposes.
23pub(crate) struct Vtl2CommandResult {
24 /// The stdout of the command.
25 pub stdout: String,
26 /// The stderr of the command.
27 pub stderr: String,
28 /// The raw stdout of the command.
29 pub stdout_raw: Vec<u8>,
30 /// The raw stderr of the command.
31 pub stderr_raw: Vec<u8>,
32 /// The exit status of the command.
33 pub exit_status: ExitStatus,
34}
35
36impl OpenHclDiagHandler {
37 pub(crate) async fn wait_for_vtl2(&self) -> anyhow::Result<()> {
38 self.ged_send
39 .call(GuestEmulationRequest::WaitForConnect, ())
40 .await
41 .context("failed to connect to VTL2")
42 }
43
44 pub(crate) async fn run_vtl2_command(
45 &self,
46 driver: &DefaultDriver,
47 command: impl AsRef<str>,
48 args: impl IntoIterator<Item = impl AsRef<str>>,
49 ) -> anyhow::Result<Vtl2CommandResult> {
50 let client = self.diag_client(driver).await?;
51 let mut proc = client
52 .exec(command.as_ref())
53 .args(args)
54 .stdout(true)
55 .stderr(true)
56 .raw_socket_io(true)
57 .spawn()
58 .await?;
59
60 let (mut stdout, mut stderr) = (proc.stdout.take().unwrap(), proc.stderr.take().unwrap());
61 let exit_status = proc.wait().await?;
62
63 let mut stdout_buf = Vec::new();
64 stdout
65 .read_to_end(&mut stdout_buf)
66 .context("error reading stdout socket")?;
67 let stdout_str = String::from_utf8_lossy(&stdout_buf);
68
69 let mut stderr_buf = Vec::new();
70 stderr
71 .read_to_end(&mut stderr_buf)
72 .context("error reading stderr socket")?;
73 let stderr_str = String::from_utf8_lossy(&stderr_buf);
74
75 Ok(Vtl2CommandResult {
76 stdout: stdout_str.to_string(),
77 stderr: stderr_str.to_string(),
78 stdout_raw: stdout_buf,
79 stderr_raw: stderr_buf,
80 exit_status,
81 })
82 }
83
84 pub(crate) async fn core_dump(
85 &self,
86 driver: &DefaultDriver,
87 name: &str,
88 path: &std::path::Path,
89 ) -> anyhow::Result<()> {
90 let client = self.diag_client(driver).await?;
91 let pid = client.get_pid(name).await?;
92 client
93 .core_dump(
94 pid,
95 AllowStdIo::new(fs_err::File::create(path)?),
96 AllowStdIo::new(std::io::stderr()),
97 true,
98 )
99 .await
100 }
101
102 pub(crate) async fn crash(&self, driver: &DefaultDriver, name: &str) -> anyhow::Result<()> {
103 let client = self.diag_client(driver).await?;
104 let pid = client.get_pid(name).await?;
105 client.crash(pid).await
106 }
107
108 pub(crate) async fn test_inspect(&self, driver: &DefaultDriver) -> anyhow::Result<()> {
109 self.diag_client(driver)
110 .await?
111 .inspect("", None, None)
112 .await
113 .map(|_| ())
114 }
115
116 async fn diag_client(&self, driver: &DefaultDriver) -> anyhow::Result<DiagClient> {
117 self.wait_for_vtl2().await?;
118 DiagClient::from_hybrid_vsock(driver.clone(), &self.vtl2_vsock_path)
119 .await
120 .map_err(anyhow::Error::from)
121 }
122}
123