qmp: add utility to execute hmp commands
Mostly for ease of use and later usage.
This commit is contained in:
parent
0e017cd00d
commit
c4caa5f643
3 changed files with 30 additions and 3 deletions
|
@ -25,6 +25,9 @@ async fn main() {
|
||||||
|
|
||||||
println!("Connected to QMP server");
|
println!("Connected to QMP server");
|
||||||
|
|
||||||
|
|
||||||
|
println!("res {}", client.execute_hmp("info block".into()).await.expect("this shouldn't fail"));
|
||||||
|
|
||||||
// let's try to get all STOP events from QMP now.
|
// let's try to get all STOP events from QMP now.
|
||||||
let mut rx = client.subscribe_to_event("STOP".into()).await.unwrap();
|
let mut rx = client.subscribe_to_event("STOP".into()).await.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -217,8 +217,7 @@ where
|
||||||
let (tx, rx) = mpsc::channel(8);
|
let (tx, rx) = mpsc::channel(8);
|
||||||
let inner = QmpClientActor::new(socket, rx);
|
let inner = QmpClientActor::new(socket, rx);
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let res = inner.run().await;
|
inner.run().await.inspect_err(|err| {
|
||||||
res.inspect_err(|err| {
|
|
||||||
tracing::error!("error in actor runloop: {err}");
|
tracing::error!("error in actor runloop: {err}");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! QMP client.
|
//! QMP client.
|
||||||
|
|
||||||
|
use serde_json::json;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::{AsyncReadExt, AsyncWriteExt},
|
io::{AsyncReadExt, AsyncWriteExt},
|
||||||
sync::{mpsc, oneshot},
|
sync::{mpsc, oneshot},
|
||||||
|
@ -35,6 +36,16 @@ impl QmpClient {
|
||||||
|
|
||||||
// TODO handle errors properly
|
// TODO handle errors properly
|
||||||
|
|
||||||
|
/// Closes this client.
|
||||||
|
pub async fn close(&self) -> result::Result<()> {
|
||||||
|
let _ = self
|
||||||
|
.tx
|
||||||
|
.send(actor::QmpActorMessage::QmpDoClose { })
|
||||||
|
.await;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handshakes QMP with the server. This **MUST** be the first operation you do.
|
||||||
pub async fn handshake(&self) -> result::Result<types::QmpHandshake> {
|
pub async fn handshake(&self) -> result::Result<types::QmpHandshake> {
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
|
|
||||||
|
@ -48,7 +59,10 @@ impl QmpClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: QMP errors should bubble out into an Rust error,
|
||||||
|
// for now this isn't done.
|
||||||
|
|
||||||
|
/// Executes a single QMP command.
|
||||||
pub async fn execute(&self, command: String, arguments: Option<serde_json::Value>) -> result::Result<serde_json::Value> {
|
pub async fn execute(&self, command: String, arguments: Option<serde_json::Value>) -> result::Result<serde_json::Value> {
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
|
|
||||||
|
@ -62,7 +76,18 @@ impl QmpClient {
|
||||||
Err(err) => Err(result::QmpError::GeneralFail),
|
Err(err) => Err(result::QmpError::GeneralFail),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Subscribes to a QMP event.
|
|
||||||
|
/// Executes a HMP (QEMU Monitor) command.
|
||||||
|
pub async fn execute_hmp(&self, hmp_line: String) -> result::Result<String> {
|
||||||
|
let res = self.execute("human-monitor-command".into(), Some(json!({
|
||||||
|
"command-line": hmp_line
|
||||||
|
}))).await?;
|
||||||
|
|
||||||
|
// This is very nasty, but this is always a string.
|
||||||
|
Ok(String::from(res["return"].as_str().unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subscribes to a QMP event with the given event name.
|
||||||
/// Returns the recvieving arm of a [mpsc::channel] which will recieve
|
/// Returns the recvieving arm of a [mpsc::channel] which will recieve
|
||||||
/// the JSON event payloads when an event is sent by the server.
|
/// the JSON event payloads when an event is sent by the server.
|
||||||
pub async fn subscribe_to_event(
|
pub async fn subscribe_to_event(
|
||||||
|
|
Loading…
Reference in a new issue