Skip to content

Commit 9df48f7

Browse files
committed
vmm: api: temporarily make VmSendMigration call blocking again
Once we have a mechanism to query the progress of an ongoing live-migration, we can remove this workaround. Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de> On-behalf-of: SAP philipp.schuster@sap.com
1 parent bcf56d2 commit 9df48f7

File tree

3 files changed

+77
-3
lines changed

3 files changed

+77
-3
lines changed

vmm/src/api/http/http_endpoint.rs

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,22 @@
3232
3333
use std::fs::File;
3434
use std::os::unix::io::IntoRawFd;
35-
use std::sync::mpsc::Sender;
35+
use std::sync::mpsc::{Receiver, Sender, SyncSender};
36+
use std::sync::{LazyLock, Mutex};
3637

3738
use micro_http::{Body, Method, Request, Response, StatusCode, Version};
3839
use vmm_sys_util::eventfd::EventFd;
3940

41+
/// Helper to make the VmSendMigration call blocking as long as a migration is ongoing.
42+
#[allow(clippy::type_complexity)]
43+
pub static ONGOING_LIVEMIGRATION: LazyLock<(
44+
SyncSender<Result<(), vm_migration::MigratableError>>,
45+
Mutex<Receiver<Result<(), vm_migration::MigratableError>>>,
46+
)> = LazyLock::new(|| {
47+
let (sender, receiver) = std::sync::mpsc::sync_channel(0);
48+
(sender, Mutex::new(receiver))
49+
});
50+
4051
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
4152
use crate::api::VmCoredump;
4253
use crate::api::http::{EndpointHandler, HttpError, error_response};
@@ -230,7 +241,6 @@ vm_action_put_handler_body!(VmRemoveDevice);
230241
vm_action_put_handler_body!(VmResizeDisk);
231242
vm_action_put_handler_body!(VmResizeZone);
232243
vm_action_put_handler_body!(VmSnapshot);
233-
vm_action_put_handler_body!(VmSendMigration);
234244

235245
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
236246
vm_action_put_handler_body!(VmCoredump);
@@ -382,6 +392,46 @@ impl PutHandler for VmReceiveMigration {
382392

383393
impl GetHandler for VmReceiveMigration {}
384394

395+
// Special Handling for virtio-net Devices Backed by Network File Descriptors
396+
//
397+
// See above.
398+
impl PutHandler for VmSendMigration {
399+
fn handle_request(
400+
&'static self,
401+
api_notifier: EventFd,
402+
api_sender: Sender<ApiRequest>,
403+
body: &Option<Body>,
404+
_files: Vec<File>,
405+
) -> std::result::Result<Option<Body>, HttpError> {
406+
if let Some(body) = body {
407+
let res = self
408+
.send(
409+
api_notifier,
410+
api_sender,
411+
serde_json::from_slice(body.raw())?,
412+
)
413+
.map_err(HttpError::ApiError)?;
414+
415+
info!("live migration started");
416+
417+
let (_, receiver) = &*ONGOING_LIVEMIGRATION;
418+
419+
info!("waiting for live migration result");
420+
let mig_res = receiver.lock().unwrap().recv().unwrap();
421+
info!("received live migration result");
422+
423+
// We forward the migration error here to the guest
424+
mig_res
425+
.map(|_| res)
426+
.map_err(|e| HttpError::ApiError(ApiError::VmSendMigration(e)))
427+
} else {
428+
Err(HttpError::BadRequest)
429+
}
430+
}
431+
}
432+
433+
impl GetHandler for VmSendMigration {}
434+
385435
impl PutHandler for VmResize {
386436
fn handle_request(
387437
&'static self,

vmm/src/lib.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ use vmm_sys_util::eventfd::EventFd;
6464
use vmm_sys_util::signal::unblock_signal;
6565
use vmm_sys_util::sock_ctrl_msg::ScmSocket;
6666

67+
use crate::api::http::http_endpoint::ONGOING_LIVEMIGRATION;
6768
use crate::api::{
6869
ApiRequest, ApiResponse, RequestHandler, VmInfoResponse, VmReceiveMigrationData,
6970
VmSendMigrationData, VmmPingResponse,
@@ -2388,13 +2389,27 @@ impl Vmm {
23882389

23892390
match migration_res {
23902391
Ok(()) => {
2392+
{
2393+
info!("Sending Receiver in HTTP thread that migration succeeded");
2394+
let (sender, _) = &*ONGOING_LIVEMIGRATION;
2395+
// unblock API call; propagate migration result
2396+
sender.send(Ok(())).unwrap();
2397+
}
2398+
23912399
// Shutdown the VM after the migration succeeded
23922400
if let Err(e) = self.exit_evt.write(1) {
23932401
error!("Failed shutting down the VM after migration: {}", e);
23942402
}
23952403
}
23962404
Err(e) => {
23972405
error!("Migration failed: {}", e);
2406+
{
2407+
info!("Sending Receiver in HTTP thread that migration failed");
2408+
let (sender, _) = &*ONGOING_LIVEMIGRATION;
2409+
// unblock API call; propagate migration result
2410+
sender.send(Err(e)).unwrap();
2411+
}
2412+
// we don't fail the VMM here, it just continues running its VM
23982413
}
23992414
}
24002415
}
@@ -2922,10 +2937,18 @@ impl RequestHandler for Vmm {
29222937
}
29232938

29242939
fn vm_resize_disk(&mut self, id: String, desired_size: u64) -> result::Result<(), VmError> {
2940+
info!("request to resize disk: id={id}");
29252941
self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
29262942

29272943
match self.vm {
2928-
MaybeVmOwnership::Vmm(ref mut vm) => vm.resize_disk(id, desired_size),
2944+
MaybeVmOwnership::Vmm(ref mut vm) => {
2945+
if let Err(e) = vm.resize_disk(id, desired_size) {
2946+
error!("Error when resizing disk: {:?}", e);
2947+
Err(e)
2948+
} else {
2949+
Ok(())
2950+
}
2951+
}
29292952
MaybeVmOwnership::Migration => Err(VmError::VmMigrating),
29302953
MaybeVmOwnership::None => Err(VmError::ResizeDisk),
29312954
}

vmm/src/seccomp_filters.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,7 @@ fn http_api_thread_rules() -> Result<Vec<(i64, Vec<SeccompRule>)>, BackendError>
865865
(libc::SYS_write, vec![]),
866866
(libc::SYS_rt_sigprocmask, vec![]),
867867
(libc::SYS_getcwd, vec![]),
868+
(libc::SYS_clock_nanosleep, vec![]),
868869
])
869870
}
870871

0 commit comments

Comments
 (0)