Skip to content

Commit 7be8666

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 3626c9e commit 7be8666

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
@@ -35,11 +35,22 @@
3535
//! [special HTTP library]: https://github.com/firecracker-microvm/micro-http
3636
3737
use std::fs::File;
38-
use std::sync::mpsc::Sender;
38+
use std::sync::mpsc::{Receiver, Sender, SyncSender};
39+
use std::sync::{LazyLock, Mutex};
3940

4041
use micro_http::{Body, Method, Request, Response, StatusCode, Version};
4142
use vmm_sys_util::eventfd::EventFd;
4243

44+
/// Helper to make the VmSendMigration call blocking as long as a migration is ongoing.
45+
#[allow(clippy::type_complexity)]
46+
pub static ONGOING_LIVEMIGRATION: LazyLock<(
47+
SyncSender<Result<(), vm_migration::MigratableError>>,
48+
Mutex<Receiver<Result<(), vm_migration::MigratableError>>>,
49+
)> = LazyLock::new(|| {
50+
let (sender, receiver) = std::sync::mpsc::sync_channel(0);
51+
(sender, Mutex::new(receiver))
52+
});
53+
4354
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
4455
use crate::api::VmCoredump;
4556
use crate::api::http::http_endpoint::fds_helper::{attach_fds_to_cfg, attach_fds_to_cfgs};
@@ -425,7 +436,6 @@ vm_action_put_handler_body!(VmRemoveDevice);
425436
vm_action_put_handler_body!(VmResizeDisk);
426437
vm_action_put_handler_body!(VmResizeZone);
427438
vm_action_put_handler_body!(VmSnapshot);
428-
vm_action_put_handler_body!(VmSendMigration);
429439

430440
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
431441
vm_action_put_handler_body!(VmCoredump);
@@ -482,6 +492,46 @@ impl PutHandler for VmReceiveMigration {
482492

483493
impl GetHandler for VmReceiveMigration {}
484494

495+
// Special Handling for virtio-net Devices Backed by Network File Descriptors
496+
//
497+
// See above.
498+
impl PutHandler for VmSendMigration {
499+
fn handle_request(
500+
&'static self,
501+
api_notifier: EventFd,
502+
api_sender: Sender<ApiRequest>,
503+
body: &Option<Body>,
504+
_files: Vec<File>,
505+
) -> std::result::Result<Option<Body>, HttpError> {
506+
if let Some(body) = body {
507+
let res = self
508+
.send(
509+
api_notifier,
510+
api_sender,
511+
serde_json::from_slice(body.raw())?,
512+
)
513+
.map_err(HttpError::ApiError)?;
514+
515+
info!("live migration started");
516+
517+
let (_, receiver) = &*ONGOING_LIVEMIGRATION;
518+
519+
info!("waiting for live migration result");
520+
let mig_res = receiver.lock().unwrap().recv().unwrap();
521+
info!("received live migration result");
522+
523+
// We forward the migration error here to the guest
524+
mig_res
525+
.map(|_| res)
526+
.map_err(|e| HttpError::ApiError(ApiError::VmSendMigration(e)))
527+
} else {
528+
Err(HttpError::BadRequest)
529+
}
530+
}
531+
}
532+
533+
impl GetHandler for VmSendMigration {}
534+
485535
impl PutHandler for VmResize {
486536
fn handle_request(
487537
&'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,
@@ -2389,13 +2390,27 @@ impl Vmm {
23892390

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

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

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

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)