mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-24 18:52:08 +00:00
runtime-rs: add base vCPU hotplugging support
We take advantage of the Inner pattern to enable QemuInner::resize_vcpu() take `&mut self` which we need to call non-const functions on Qmp. This runs on Intel architecture but will need to be verified and ported (if necessary) to other architectures in the future. Signed-off-by: Pavel Mores <pmores@redhat.com>
This commit is contained in:
parent
8231c6c4a3
commit
380f8ad03f
@ -17,6 +17,7 @@ use kata_types::{
|
|||||||
config::KATA_PATH,
|
config::KATA_PATH,
|
||||||
};
|
};
|
||||||
use persist::sandbox_persist::Persist;
|
use persist::sandbox_persist::Persist;
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
@ -244,15 +245,48 @@ impl QemuInner {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn resize_vcpu(&self, old_vcpus: u32, new_vcpus: u32) -> Result<(u32, u32)> {
|
pub(crate) async fn resize_vcpu(
|
||||||
|
&mut self,
|
||||||
|
old_vcpus: u32,
|
||||||
|
mut new_vcpus: u32,
|
||||||
|
) -> Result<(u32, u32)> {
|
||||||
info!(
|
info!(
|
||||||
sl!(),
|
sl!(),
|
||||||
"QemuInner::resize_vcpu(): {} -> {}", old_vcpus, new_vcpus
|
"QemuInner::resize_vcpu(): {} -> {}", old_vcpus, new_vcpus
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO The following sanity checks apparently have to be performed by
|
||||||
|
// any hypervisor - wouldn't it make sense to move them to the caller?
|
||||||
if new_vcpus == old_vcpus {
|
if new_vcpus == old_vcpus {
|
||||||
return Ok((old_vcpus, new_vcpus));
|
return Ok((old_vcpus, new_vcpus));
|
||||||
}
|
}
|
||||||
todo!()
|
|
||||||
|
if new_vcpus == 0 {
|
||||||
|
return Err(anyhow!("resize to 0 vcpus requested"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if new_vcpus > self.config.cpu_info.default_maxvcpus {
|
||||||
|
warn!(
|
||||||
|
sl!(),
|
||||||
|
"Cannot allocate more vcpus than the max allowed number of vcpus. The maximum allowed amount of vcpus will be used instead.");
|
||||||
|
new_vcpus = self.config.cpu_info.default_maxvcpus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref mut qmp) = self.qmp {
|
||||||
|
match new_vcpus.cmp(&old_vcpus) {
|
||||||
|
Ordering::Greater => {
|
||||||
|
let hotplugged = qmp.hotplug_vcpus(new_vcpus - old_vcpus)?;
|
||||||
|
new_vcpus = old_vcpus + hotplugged;
|
||||||
|
}
|
||||||
|
Ordering::Less => {
|
||||||
|
let hotunplugged = qmp.hotunplug_vcpus(old_vcpus - new_vcpus)?;
|
||||||
|
new_vcpus = old_vcpus - hotunplugged;
|
||||||
|
}
|
||||||
|
Ordering::Equal => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((old_vcpus, new_vcpus))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_pids(&self) -> Result<Vec<u32>> {
|
pub(crate) async fn get_pids(&self) -> Result<Vec<u32>> {
|
||||||
|
@ -128,7 +128,7 @@ impl Hypervisor for Qemu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn resize_vcpu(&self, old_vcpus: u32, new_vcpus: u32) -> Result<(u32, u32)> {
|
async fn resize_vcpu(&self, old_vcpus: u32, new_vcpus: u32) -> Result<(u32, u32)> {
|
||||||
let inner = self.inner.read().await;
|
let mut inner = self.inner.write().await;
|
||||||
inner.resize_vcpu(old_vcpus, new_vcpus).await
|
inner.resize_vcpu(old_vcpus, new_vcpus).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,9 @@ use std::io::BufReader;
|
|||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use qapi::qmp;
|
||||||
|
use qapi_spec::Dictionary;
|
||||||
|
|
||||||
pub struct Qmp {
|
pub struct Qmp {
|
||||||
qmp: qapi::Qmp<qapi::Stream<BufReader<UnixStream>, UnixStream>>,
|
qmp: qapi::Qmp<qapi::Stream<BufReader<UnixStream>, UnixStream>>,
|
||||||
}
|
}
|
||||||
@ -47,4 +50,86 @@ impl Qmp {
|
|||||||
|
|
||||||
Ok(qmp)
|
Ok(qmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hotplug_vcpus(&mut self, vcpu_cnt: u32) -> Result<u32> {
|
||||||
|
let hotpluggable_cpus = self.qmp.execute(&qmp::query_hotpluggable_cpus {})?;
|
||||||
|
//info!(sl!(), "hotpluggable CPUs: {:#?}", hotpluggable_cpus);
|
||||||
|
|
||||||
|
let mut hotplugged = 0;
|
||||||
|
for vcpu in &hotpluggable_cpus {
|
||||||
|
if hotplugged >= vcpu_cnt {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let core_id = match vcpu.props.core_id {
|
||||||
|
Some(id) => id,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
if vcpu.qom_path.is_some() {
|
||||||
|
info!(sl!(), "hotpluggable vcpu {} hotplugged already", core_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let socket_id = match vcpu.props.socket_id {
|
||||||
|
Some(id) => id,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
let thread_id = match vcpu.props.thread_id {
|
||||||
|
Some(id) => id,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut cpu_args = Dictionary::new();
|
||||||
|
cpu_args.insert("socket-id".to_owned(), socket_id.into());
|
||||||
|
cpu_args.insert("core-id".to_owned(), core_id.into());
|
||||||
|
cpu_args.insert("thread-id".to_owned(), thread_id.into());
|
||||||
|
self.qmp.execute(&qmp::device_add {
|
||||||
|
bus: None,
|
||||||
|
id: Some(vcpu_id_from_core_id(core_id)),
|
||||||
|
driver: hotpluggable_cpus[0].type_.clone(),
|
||||||
|
arguments: cpu_args,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
hotplugged += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
info!(
|
||||||
|
sl!(),
|
||||||
|
"Qmp::hotplug_vcpus(): hotplugged {}/{} vcpus", hotplugged, vcpu_cnt
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(hotplugged)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hotunplug_vcpus(&mut self, vcpu_cnt: u32) -> Result<u32> {
|
||||||
|
let hotpluggable_cpus = self.qmp.execute(&qmp::query_hotpluggable_cpus {})?;
|
||||||
|
|
||||||
|
let mut hotunplugged = 0;
|
||||||
|
for vcpu in &hotpluggable_cpus {
|
||||||
|
if hotunplugged >= vcpu_cnt {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let core_id = match vcpu.props.core_id {
|
||||||
|
Some(id) => id,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
if vcpu.qom_path.is_none() {
|
||||||
|
info!(sl!(), "hotpluggable vcpu {} not hotplugged yet", core_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
self.qmp.execute(&qmp::device_del {
|
||||||
|
id: vcpu_id_from_core_id(core_id),
|
||||||
|
})?;
|
||||||
|
hotunplugged += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
info!(
|
||||||
|
sl!(),
|
||||||
|
"Qmp::hotunplug_vcpus(): hotunplugged {}/{} vcpus", hotunplugged, vcpu_cnt
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(hotunplugged)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vcpu_id_from_core_id(core_id: i64) -> String {
|
||||||
|
format!("cpu-{}", core_id)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user