runtime-rs: add Qmp object to encapsulate QMP functionality

The constructor handles QMP connection initialisation, too, so there can
be non-functional Qmp instance.

Signed-off-by: Pavel Mores <pmores@redhat.com>
This commit is contained in:
Pavel Mores 2024-06-04 10:23:51 +02:00
parent a7931115a0
commit 6fdb262dca
3 changed files with 106 additions and 0 deletions

View File

@ -1644,6 +1644,9 @@ dependencies = [
"nix 0.24.3",
"path-clean",
"persist",
"qapi",
"qapi-qmp",
"qapi-spec",
"rand 0.8.5",
"rust-ini",
"safe-path 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2959,6 +2962,65 @@ dependencies = [
"ttrpc-codegen",
]
[[package]]
name = "qapi"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6412bdd014ebee03ddbbe79ac03a0b622cce4d80ba45254f6357c847f06fa38"
dependencies = [
"bytes",
"futures 0.3.28",
"log",
"memchr",
"qapi-qmp",
"qapi-spec",
"serde",
"serde_json",
"tokio",
"tokio-util",
]
[[package]]
name = "qapi-codegen"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ba4de731473de4c8bd508ddb38a9049e999b8a7429f3c052ba8735a178ff68c"
dependencies = [
"qapi-parser",
]
[[package]]
name = "qapi-parser"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80044db145aa2953ef5803d0376dcbca50f2763242547e856b7f37507adca677"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "qapi-qmp"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8b944db7e544d2fa97595e9a000a6ba5c62c426fa185e7e00aabe4b5640b538"
dependencies = [
"qapi-codegen",
"qapi-spec",
"serde",
]
[[package]]
name = "qapi-spec"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b360919a24ea5fc02fa762cb01bd8f43b643fee51c585f763257773b4dc5a9e8"
dependencies = [
"base64 0.13.1",
"serde",
"serde_json",
]
[[package]]
name = "quote"
version = "1.0.35"

View File

@ -43,6 +43,10 @@ safe-path = "0.1.0"
crossbeam-channel = "0.5.6"
tempdir = "0.3.7"
qapi = { version = "0.14", features = [ "qmp", "async-tokio-all" ] }
qapi-spec = "0.3.1"
qapi-qmp = "0.14.0"
[target.'cfg(not(target_arch = "s390x"))'.dependencies]
dragonball = { path = "../../../dragonball", features = ["atomic-guest-memory", "virtio-vsock", "hotplug", "virtio-blk", "virtio-net", "virtio-fs", "vhost-net", "dbs-upcall", "virtio-mem", "virtio-balloon", "vhost-user-net", "host-device"] }

View File

@ -0,0 +1,40 @@
// Copyright (c) 2024 Red Hat
//
// SPDX-License-Identifier: Apache-2.0
//
use anyhow::Result;
use std::io::BufReader;
use std::os::unix::net::UnixStream;
use std::time::Duration;
pub struct Qmp {
qmp: qapi::Qmp<qapi::Stream<BufReader<UnixStream>, UnixStream>>,
}
impl Qmp {
pub fn new(qmp_sock_path: &str) -> Result<Self> {
let stream = UnixStream::connect(qmp_sock_path)?;
// Set the read timeout to protect runtime-rs from blocking forever
// trying to set up QMP connection if qemu fails to launch. The exact
// value is a matter of judegement. Setting it too long would risk
// being ineffective since container runtime would timeout first anyway
// (containerd's task creation timeout is 2 s by default). OTOH
// setting it too short would risk interfering with a normal launch,
// perhaps just seeing some delay due to a heavily loaded host.
stream.set_read_timeout(Some(Duration::from_millis(250)))?;
let mut qmp = Qmp {
qmp: qapi::Qmp::new(qapi::Stream::new(
BufReader::new(stream.try_clone()?),
stream,
)),
};
let info = qmp.qmp.handshake()?;
info!(sl!(), "QMP initialized: {:#?}", info);
Ok(qmp)
}
}