mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
ch-remote: support live disk resizing
Support disk resizing via ch-remote and REST api. On-behalf-of: SAP thomas.prescher@sap.com Signed-off-by: Thomas Prescher <thomas.prescher@cyberus-technology.de>
This commit is contained in:
committed by
Rob Bradford
parent
aac240d076
commit
5fb078305a
@@ -65,6 +65,8 @@ enum Error {
|
||||
ReadingStdin(#[source] std::io::Error),
|
||||
#[error("Error reading from file")]
|
||||
ReadingFile(#[source] std::io::Error),
|
||||
#[error("Invalid disk size")]
|
||||
InvalidDiskSize(#[source] ByteSizedParseError),
|
||||
}
|
||||
|
||||
enum TargetApi<'a> {
|
||||
@@ -320,6 +322,22 @@ fn rest_api_do_command(matches: &ArgMatches, socket: &mut UnixStream) -> ApiResu
|
||||
)?;
|
||||
simple_api_command(socket, "PUT", "resize", Some(&resize)).map_err(Error::HttpApiClient)
|
||||
}
|
||||
Some("resize-disk") => {
|
||||
let resize_disk = resize_disk_config(
|
||||
matches
|
||||
.subcommand_matches("resize-disk")
|
||||
.unwrap()
|
||||
.get_one::<String>("disk")
|
||||
.unwrap(),
|
||||
matches
|
||||
.subcommand_matches("resize-disk")
|
||||
.unwrap()
|
||||
.get_one::<String>("size")
|
||||
.unwrap(),
|
||||
)?;
|
||||
simple_api_command(socket, "PUT", "resize-disk", Some(&resize_disk))
|
||||
.map_err(Error::HttpApiClient)
|
||||
}
|
||||
Some("resize-zone") => {
|
||||
let resize_zone = resize_zone_config(
|
||||
matches
|
||||
@@ -762,6 +780,15 @@ fn resize_config(
|
||||
Ok(serde_json::to_string(&resize).unwrap())
|
||||
}
|
||||
|
||||
fn resize_disk_config(id: &str, size: &str) -> Result<String, Error> {
|
||||
let resize_disk = vmm::api::VmResizeDiskData {
|
||||
id: id.to_owned(),
|
||||
desired_size: size.parse::<ByteSized>().map_err(Error::InvalidDiskSize)?.0,
|
||||
};
|
||||
|
||||
Ok(serde_json::to_string(&resize_disk).unwrap())
|
||||
}
|
||||
|
||||
fn resize_zone_config(id: &str, size: &str) -> Result<String, Error> {
|
||||
let resize_zone = vmm::api::VmResizeZoneData {
|
||||
id: id.to_owned(),
|
||||
@@ -1022,6 +1049,20 @@ fn get_cli_commands_sorted() -> Box<[Command]> {
|
||||
.help("New memory size in bytes (supports K/M/G suffix)")
|
||||
.num_args(1),
|
||||
),
|
||||
Command::new("resize-disk")
|
||||
.about("Resize an attached disk")
|
||||
.arg(
|
||||
Arg::new("disk")
|
||||
.long("disk")
|
||||
.help("Disk identifier")
|
||||
.num_args(1),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("size")
|
||||
.long("size")
|
||||
.help("New disk size")
|
||||
.num_args(1),
|
||||
),
|
||||
Command::new("resize-zone")
|
||||
.about("Resize a memory zone")
|
||||
.arg(
|
||||
|
||||
@@ -47,8 +47,8 @@ use crate::api::http::{EndpointHandler, HttpError, error_response};
|
||||
use crate::api::{
|
||||
AddDisk, ApiAction, ApiError, ApiRequest, NetConfig, VmAddDevice, VmAddFs, VmAddNet, VmAddPmem,
|
||||
VmAddUserDevice, VmAddVdpa, VmAddVsock, VmBoot, VmConfig, VmCounters, VmDelete, VmNmi, VmPause,
|
||||
VmPowerButton, VmReboot, VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeZone, VmRestore,
|
||||
VmResume, VmSendMigration, VmShutdown, VmSnapshot,
|
||||
VmPowerButton, VmReboot, VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeDisk,
|
||||
VmResizeZone, VmRestore, VmResume, VmSendMigration, VmShutdown, VmSnapshot,
|
||||
};
|
||||
use crate::config::RestoreConfig;
|
||||
use crate::cpu::Error as CpuError;
|
||||
@@ -424,6 +424,7 @@ vm_action_put_handler_body!(VmAddVdpa);
|
||||
vm_action_put_handler_body!(VmAddVsock);
|
||||
vm_action_put_handler_body!(VmAddUserDevice);
|
||||
vm_action_put_handler_body!(VmRemoveDevice);
|
||||
vm_action_put_handler_body!(VmResizeDisk);
|
||||
vm_action_put_handler_body!(VmResizeZone);
|
||||
vm_action_put_handler_body!(VmSnapshot);
|
||||
vm_action_put_handler_body!(VmReceiveMigration);
|
||||
|
||||
@@ -30,7 +30,7 @@ use crate::api::VmCoredump;
|
||||
use crate::api::{
|
||||
AddDisk, ApiError, ApiRequest, VmAddDevice, VmAddFs, VmAddNet, VmAddPmem, VmAddUserDevice,
|
||||
VmAddVdpa, VmAddVsock, VmBoot, VmCounters, VmDelete, VmNmi, VmPause, VmPowerButton, VmReboot,
|
||||
VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeZone, VmRestore, VmResume,
|
||||
VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeDisk, VmResizeZone, VmRestore, VmResume,
|
||||
VmSendMigration, VmShutdown, VmSnapshot,
|
||||
};
|
||||
use crate::landlock::Landlock;
|
||||
@@ -251,6 +251,10 @@ pub static HTTP_ROUTES: LazyLock<HttpRoutes> = LazyLock::new(|| {
|
||||
endpoint!("/vm.resize"),
|
||||
Box::new(VmActionHandler::new(&VmResize)),
|
||||
);
|
||||
r.routes.insert(
|
||||
endpoint!("/vm.resize-disk"),
|
||||
Box::new(VmActionHandler::new(&VmResizeDisk)),
|
||||
);
|
||||
r.routes.insert(
|
||||
endpoint!("/vm.resize-zone"),
|
||||
Box::new(VmActionHandler::new(&VmResizeZone)),
|
||||
|
||||
@@ -134,6 +134,10 @@ pub enum ApiError {
|
||||
#[error("The VM could not be resized")]
|
||||
VmResize(#[source] VmError),
|
||||
|
||||
/// The disk could not be resized.
|
||||
#[error("The disk could not be resized")]
|
||||
VmResizeDisk(#[source] VmError),
|
||||
|
||||
/// The memory zone could not be resized.
|
||||
#[error("The memory zone could not be resized")]
|
||||
VmResizeZone(#[source] VmError),
|
||||
@@ -223,6 +227,12 @@ pub struct VmResizeData {
|
||||
pub desired_balloon: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize, Default, Debug)]
|
||||
pub struct VmResizeDiskData {
|
||||
pub id: String,
|
||||
pub desired_size: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize, Default, Debug)]
|
||||
pub struct VmResizeZoneData {
|
||||
pub id: String,
|
||||
@@ -1139,6 +1149,41 @@ impl ApiAction for VmResize {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VmResizeDisk;
|
||||
|
||||
impl ApiAction for VmResizeDisk {
|
||||
type RequestBody = VmResizeDiskData;
|
||||
type ResponseBody = Option<Body>;
|
||||
|
||||
fn request(
|
||||
&self,
|
||||
resize_disk_data: Self::RequestBody,
|
||||
response_sender: Sender<ApiResponse>,
|
||||
) -> ApiRequest {
|
||||
Box::new(move |vmm| {
|
||||
let response = vmm
|
||||
.vm_resize_disk(resize_disk_data.id, resize_disk_data.desired_size)
|
||||
.map_err(ApiError::VmResizeDisk)
|
||||
.map(|_| ApiResponsePayload::Empty);
|
||||
|
||||
response_sender
|
||||
.send(response)
|
||||
.map_err(VmmError::ApiResponseSend)?;
|
||||
|
||||
Ok(false)
|
||||
})
|
||||
}
|
||||
|
||||
fn send(
|
||||
&self,
|
||||
api_evt: EventFd,
|
||||
api_sender: Sender<ApiRequest>,
|
||||
data: Self::RequestBody,
|
||||
) -> ApiResult<Self::ResponseBody> {
|
||||
get_response_body(self, api_evt, api_sender, data)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VmResizeZone;
|
||||
|
||||
impl ApiAction for VmResizeZone {
|
||||
|
||||
Reference in New Issue
Block a user