2020-04-01 15:22:40 +00:00
|
|
|
// Copyright © 2020 Intel Corporation
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2022-12-05 16:33:54 +00:00
|
|
|
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
2022-05-24 00:35:15 +00:00
|
|
|
use crate::coredump::GuestDebuggableError;
|
2022-02-08 10:32:19 +00:00
|
|
|
use crate::{
|
|
|
|
config::VmConfig,
|
|
|
|
vm::{VmSnapshot, VM_SNAPSHOT_ID},
|
|
|
|
};
|
2020-04-01 15:22:40 +00:00
|
|
|
use anyhow::anyhow;
|
|
|
|
use std::fs::File;
|
|
|
|
use std::io::BufReader;
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use vm_migration::{MigratableError, Snapshot};
|
|
|
|
|
2022-02-08 10:32:19 +00:00
|
|
|
pub const SNAPSHOT_STATE_FILE: &str = "state.json";
|
|
|
|
pub const SNAPSHOT_CONFIG_FILE: &str = "config.json";
|
2020-04-01 15:22:40 +00:00
|
|
|
|
2021-03-12 10:46:36 +00:00
|
|
|
pub fn url_to_path(url: &str) -> std::result::Result<PathBuf, MigratableError> {
|
|
|
|
let path: PathBuf = url
|
|
|
|
.strip_prefix("file://")
|
|
|
|
.ok_or_else(|| {
|
|
|
|
MigratableError::MigrateSend(anyhow!("Could not extract path from URL: {}", url))
|
|
|
|
})
|
|
|
|
.map(|s| s.into())?;
|
|
|
|
|
|
|
|
if !path.is_dir() {
|
|
|
|
return Err(MigratableError::MigrateSend(anyhow!(
|
|
|
|
"Destination is not a directory"
|
|
|
|
)));
|
2020-04-01 15:22:40 +00:00
|
|
|
}
|
2021-03-12 10:46:36 +00:00
|
|
|
|
|
|
|
Ok(path)
|
2020-04-01 15:22:40 +00:00
|
|
|
}
|
|
|
|
|
2022-12-05 16:33:54 +00:00
|
|
|
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
2022-05-24 00:35:15 +00:00
|
|
|
pub fn url_to_file(url: &str) -> std::result::Result<PathBuf, GuestDebuggableError> {
|
|
|
|
let file: PathBuf = url
|
|
|
|
.strip_prefix("file://")
|
|
|
|
.ok_or_else(|| {
|
|
|
|
GuestDebuggableError::Coredump(anyhow!("Could not extract file from URL: {}", url))
|
|
|
|
})
|
|
|
|
.map(|s| s.into())?;
|
|
|
|
|
|
|
|
Ok(file)
|
|
|
|
}
|
|
|
|
|
2022-02-08 10:32:19 +00:00
|
|
|
pub fn recv_vm_config(source_url: &str) -> std::result::Result<VmConfig, MigratableError> {
|
|
|
|
let mut vm_config_path = url_to_path(source_url)?;
|
2020-04-01 15:22:40 +00:00
|
|
|
|
2022-02-08 10:32:19 +00:00
|
|
|
vm_config_path.push(SNAPSHOT_CONFIG_FILE);
|
2020-04-01 15:22:40 +00:00
|
|
|
|
2021-03-12 10:46:36 +00:00
|
|
|
// Try opening the snapshot file
|
2022-02-08 10:32:19 +00:00
|
|
|
let vm_config_file =
|
|
|
|
File::open(vm_config_path).map_err(|e| MigratableError::MigrateSend(e.into()))?;
|
|
|
|
let vm_config_reader = BufReader::new(vm_config_file);
|
|
|
|
serde_json::from_reader(vm_config_reader).map_err(|e| MigratableError::MigrateReceive(e.into()))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn recv_vm_state(source_url: &str) -> std::result::Result<Snapshot, MigratableError> {
|
|
|
|
let mut vm_state_path = url_to_path(source_url)?;
|
2020-04-01 15:22:40 +00:00
|
|
|
|
2022-02-08 10:32:19 +00:00
|
|
|
vm_state_path.push(SNAPSHOT_STATE_FILE);
|
|
|
|
|
|
|
|
// Try opening the snapshot file
|
|
|
|
let vm_state_file =
|
|
|
|
File::open(vm_state_path).map_err(|e| MigratableError::MigrateSend(e.into()))?;
|
|
|
|
let vm_state_reader = BufReader::new(vm_state_file);
|
|
|
|
serde_json::from_reader(vm_state_reader).map_err(|e| MigratableError::MigrateReceive(e.into()))
|
2020-04-01 15:22:40 +00:00
|
|
|
}
|
2020-02-25 23:03:06 +00:00
|
|
|
|
2020-06-23 09:39:39 +00:00
|
|
|
pub fn get_vm_snapshot(snapshot: &Snapshot) -> std::result::Result<VmSnapshot, MigratableError> {
|
2020-02-25 23:03:06 +00:00
|
|
|
if let Some(vm_section) = snapshot
|
|
|
|
.snapshot_data
|
|
|
|
.get(&format!("{}-section", VM_SNAPSHOT_ID))
|
|
|
|
{
|
2020-06-23 09:39:39 +00:00
|
|
|
return serde_json::from_slice(&vm_section.snapshot).map_err(|e| {
|
|
|
|
MigratableError::Restore(anyhow!("Could not deserialize VM snapshot {}", e))
|
|
|
|
});
|
2020-02-25 23:03:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Err(MigratableError::Restore(anyhow!(
|
|
|
|
"Could not find VM config snapshot section"
|
|
|
|
)))
|
|
|
|
}
|