Skip to content

Commit

Permalink
runtime-rs: add param qmp into cmdline
Browse files Browse the repository at this point in the history
Fixes: kata-containers#9603

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
  • Loading branch information
Apokleos committed May 7, 2024
1 parent e5e0983 commit 3e64728
Showing 1 changed file with 82 additions and 0 deletions.
82 changes: 82 additions & 0 deletions src/runtime-rs/crates/hypervisor/src/qemu/cmdline_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ use tokio;
const MI_B: u64 = 1024 * 1024;
const GI_B: u64 = 1024 * MI_B;

const QMP_SOCKET_TYPE: &str = "unix";
const QMP_SOCKET_FILE: &str = "qmp.sock";

// The approach taken here is inspired by govmm. We build structs, each
// corresponding to a qemu command line parameter, like Kernel, or a device,
// for instance MemoryBackendFile. Members of these structs mostly directly
Expand Down Expand Up @@ -1178,6 +1181,82 @@ impl ToQemuParams for DeviceIntelIommu {
}
}

// Qemu provides methods and types for managing QEMU instances.
// To manage a qemu instance after it has been launched you need
// to pass the -qmp option during launch requesting the qemu instance
// to create a QMP unix domain manageent socket, e.g.,
// -qmp unix:/tmp/qmp-socket,server=on,wait=off.
#[derive(Debug, Default, PartialEq)]
#[allow(dead_code)]
pub enum MonitorProtocol {
// Socket using a human-friendly text-based protocol.
Hmp,

// Socket using a richer json-based protocol.
#[default]
Qmp,

// Same as Qmp with pretty json formatting.
QmpPretty,
}

#[allow(dead_code)]
impl MonitorProtocol {
pub fn new(proto: &str) -> Self {
match proto {
"hmp" => MonitorProtocol::Hmp,
"qmp-pretty" => MonitorProtocol::QmpPretty,
_ => MonitorProtocol::Qmp,
}
}
}

impl ToString for MonitorProtocol {
fn to_string(&self) -> String {
match *self {
MonitorProtocol::Hmp => "hmp".to_string(),
MonitorProtocol::QmpPretty => "qmp-pretty".to_string(),
_ => "qmp".to_string(),
}
}
}

#[derive(Debug)]
pub struct QmpSocket {
// type is the socket type (e.g. "unix").
pub socket_type: String,
// protocol to be used on the socket.
pub protocol: MonitorProtocol,
// QMP listener file descriptor to be passed to qemu
pub fd: Option<File>,
// name is the socket name.
pub name: String,
// server tells if this is a server socket.
pub server: bool,
// nowait tells if qemu should block waiting for a client to connect.
pub nowait: bool,
}

impl QmpSocket {
fn new(_sid: &str) -> Result<Self> {
Ok(QmpSocket {
socket_type: QMP_SOCKET_TYPE.to_owned(),
protocol: MonitorProtocol::new("qmp"),
fd: None,
name: QMP_SOCKET_FILE.to_owned(),
server: true,
nowait: true,
})
}
}

#[async_trait]
impl ToQemuParams for QmpSocket {
async fn qemu_params(&self) -> Result<Vec<String>> {
Ok(vec![])
}
}

fn is_running_in_vm() -> Result<bool> {
let res = read_to_string("/proc/cpuinfo")?
.lines()
Expand Down Expand Up @@ -1213,6 +1292,7 @@ pub struct QemuCmdLine<'a> {
machine: Machine,
cpu: Cpu,
rtc: Rtc,
qmp_socket: QmpSocket,

knobs: Knobs,

Expand All @@ -1230,6 +1310,7 @@ impl<'a> QemuCmdLine<'a> {
machine: Machine::new(config),
cpu: Cpu::new(config),
rtc: Rtc::new(),
qmp_socket: QmpSocket::new(id)?,
knobs: Knobs::new(config),
devices: Vec::new(),
};
Expand Down Expand Up @@ -1433,6 +1514,7 @@ impl<'a> QemuCmdLine<'a> {
result.append(&mut self.cpu.qemu_params().await?);
result.append(&mut self.memory.qemu_params().await?);
result.append(&mut self.rtc.qemu_params().await?);
result.append(&mut self.qmp_socket.qemu_params().await?);

for device in &self.devices {
result.append(&mut device.qemu_params().await?);
Expand Down

0 comments on commit 3e64728

Please sign in to comment.