Skip to content

Commit 7d1e566

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 d1f1ddc commit 7d1e566

File tree

3 files changed

+83
-7
lines changed

3 files changed

+83
-7
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: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use std::path::PathBuf;
3030
use std::rc::Rc;
3131
use std::sync::mpsc::{Receiver, RecvError, SendError, Sender, TrySendError};
3232
use std::sync::{Arc, Barrier, Mutex};
33-
use std::thread::JoinHandle;
33+
use std::thread::{JoinHandle, sleep};
3434
#[cfg(not(target_arch = "riscv64"))]
3535
use std::time::{Duration, Instant};
3636
use std::{io, mem, result, thread};
@@ -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,
@@ -2375,8 +2376,9 @@ impl Vmm {
23752376

23762377
/// Checks the migration result.
23772378
///
2378-
/// This should be called when the migration thread indicated is stopped.
2379-
// TODO return Result
2379+
/// This should be called when the migration thread indicated a state#
2380+
/// change. The function parses the callback and either shuts down the VMM
2381+
/// on success or keeps the VM and the VMM running on migration failure.
23802382
fn check_migration_result(&mut self) {
23812383
let receiver = self
23822384
.migration_state_receiver
@@ -2393,13 +2395,28 @@ impl Vmm {
23932395

23942396
match res {
23952397
Ok(()) => {
2398+
{
2399+
info!("Sending Receiver in HTTP thread that migration succeeded");
2400+
let (sender, _) = &*ONGOING_LIVEMIGRATION;
2401+
// unblock API call; propagate migration result
2402+
sender.send(Ok(())).unwrap();
2403+
}
2404+
23962405
// Shutdown the VM after the migration succeeded
23972406
if let Err(e) = self.exit_evt.write(1) {
23982407
error!("Failed shutting down the VM after migration: {}", e);
23992408
}
24002409
}
24012410
Err(e) => {
2402-
panic!("Migration failed: {}", e);
2411+
error!("Migration failed: {}", e);
2412+
{
2413+
info!("Sending Receiver in HTTP thread that migration failed");
2414+
let (sender, _) = &*ONGOING_LIVEMIGRATION;
2415+
// unblock API call; propagate migration result
2416+
sender.send(Err(e)).unwrap();
2417+
sleep(Duration::from_millis(1));
2418+
}
2419+
// we don't fail the VMM here, it just continues running its VM
24032420
}
24042421
}
24052422
}
@@ -2930,10 +2947,18 @@ impl RequestHandler for Vmm {
29302947
}
29312948

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

29352953
match self.vm {
2936-
MaybeVmOwnership::Vmm(ref mut vm) => vm.resize_disk(id, desired_size),
2954+
MaybeVmOwnership::Vmm(ref mut vm) => {
2955+
if let Err(e) = vm.resize_disk(id, desired_size) {
2956+
error!("Error when resizing disk: {:?}", e);
2957+
Err(e)
2958+
} else {
2959+
Ok(())
2960+
}
2961+
}
29372962
MaybeVmOwnership::Migration => Err(VmError::VmMigrating),
29382963
MaybeVmOwnership::None => Err(VmError::ResizeDisk),
29392964
}

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)