diff --git a/vmm/src/memory_manager.rs b/vmm/src/memory_manager.rs index da7f8eed5..2b24917bd 100644 --- a/vmm/src/memory_manager.rs +++ b/vmm/src/memory_manager.rs @@ -6,6 +6,7 @@ extern crate hypervisor; #[cfg(target_arch = "x86_64")] use crate::config::SgxEpcConfig; use crate::config::{HotplugMethod, MemoryConfig, MemoryZoneConfig}; +use crate::migration::url_to_path; use crate::MEMORY_MANAGER_SNAPSHOT_ID; #[cfg(feature = "acpi")] use acpi_tables::{aml, aml::Aml}; @@ -851,9 +852,7 @@ impl MemoryManager { )?; if let Some(source_url) = source_url { - let url = Url::parse(source_url).unwrap(); - /* url must be valid dir which is verified in recv_vm_snapshot() */ - let vm_snapshot_path = url.to_file_path().unwrap(); + let vm_snapshot_path = url_to_path(source_url).map_err(Error::Restore)?; if let Some(mem_section) = snapshot .snapshot_data diff --git a/vmm/src/migration.rs b/vmm/src/migration.rs index e68f81f97..3c2ffa30f 100644 --- a/vmm/src/migration.rs +++ b/vmm/src/migration.rs @@ -7,61 +7,40 @@ use anyhow::anyhow; use std::fs::File; use std::io::BufReader; use std::path::PathBuf; -use url::Url; use vm_migration::{MigratableError, Snapshot}; pub const VM_SNAPSHOT_FILE: &str = "vm.json"; -pub fn url_to_path(url: &Url) -> std::result::Result { - match url.scheme() { - "file" => url - .to_file_path() - .map_err(|_| { - MigratableError::MigrateSend(anyhow!( - "Could not convert file URL to a file path: {}", - url.as_str() - )) - }) - .and_then(|path| { - if !path.is_dir() { - return Err(MigratableError::MigrateSend(anyhow!( - "Destination is not a directory" - ))); - } - Ok(path) - }), +pub fn url_to_path(url: &str) -> std::result::Result { + let path: PathBuf = url + .strip_prefix("file://") + .ok_or_else(|| { + MigratableError::MigrateSend(anyhow!("Could not extract path from URL: {}", url)) + }) + .map(|s| s.into())?; - _ => Err(MigratableError::MigrateSend(anyhow!( - "URL scheme is not file: {}", - url.scheme() - ))), + if !path.is_dir() { + return Err(MigratableError::MigrateSend(anyhow!( + "Destination is not a directory" + ))); } + + Ok(path) } pub fn recv_vm_snapshot(source_url: &str) -> std::result::Result { - let url = Url::parse(source_url).map_err(|e| { - MigratableError::MigrateSend(anyhow!("Could not parse destination URL: {}", e)) - })?; + let mut vm_snapshot_path = url_to_path(source_url)?; - match url.scheme() { - "file" => { - let mut vm_snapshot_path = url_to_path(&url)?; - vm_snapshot_path.push(VM_SNAPSHOT_FILE); + vm_snapshot_path.push(VM_SNAPSHOT_FILE); - // Try opening the snapshot file - let vm_snapshot_file = - File::open(vm_snapshot_path).map_err(|e| MigratableError::MigrateSend(e.into()))?; - let vm_snapshot_reader = BufReader::new(vm_snapshot_file); - let vm_snapshot = serde_json::from_reader(vm_snapshot_reader) - .map_err(|e| MigratableError::MigrateReceive(e.into()))?; + // Try opening the snapshot file + let vm_snapshot_file = + File::open(vm_snapshot_path).map_err(|e| MigratableError::MigrateSend(e.into()))?; + let vm_snapshot_reader = BufReader::new(vm_snapshot_file); + let vm_snapshot = serde_json::from_reader(vm_snapshot_reader) + .map_err(|e| MigratableError::MigrateReceive(e.into()))?; - Ok(vm_snapshot) - } - _ => Err(MigratableError::MigrateSend(anyhow!( - "Unsupported VM transport URL scheme: {}", - url.scheme() - ))), - } + Ok(vm_snapshot) } pub fn get_vm_snapshot(snapshot: &Snapshot) -> std::result::Result { diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 3cc90195a..78c55e26c 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -71,7 +71,6 @@ use std::num::Wrapping; use std::ops::Deref; use std::sync::{Arc, Mutex, RwLock}; use std::{result, str, thread}; -use url::Url; use vm_device::Bus; use vm_memory::{ Address, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, @@ -2311,52 +2310,37 @@ impl Transportable for Vm { snapshot: &Snapshot, destination_url: &str, ) -> std::result::Result<(), MigratableError> { - let url = Url::parse(destination_url).map_err(|e| { - MigratableError::MigrateSend(anyhow!("Could not parse destination URL: {}", e)) - })?; + let mut vm_snapshot_path = url_to_path(destination_url)?; + vm_snapshot_path.push(VM_SNAPSHOT_FILE); - match url.scheme() { - "file" => { - let mut vm_snapshot_path = url_to_path(&url)?; - vm_snapshot_path.push(VM_SNAPSHOT_FILE); + // Create the snapshot file + let mut vm_snapshot_file = OpenOptions::new() + .read(true) + .write(true) + .create_new(true) + .open(vm_snapshot_path) + .map_err(|e| MigratableError::MigrateSend(e.into()))?; - // Create the snapshot file - let mut vm_snapshot_file = OpenOptions::new() - .read(true) - .write(true) - .create_new(true) - .open(vm_snapshot_path) - .map_err(|e| MigratableError::MigrateSend(e.into()))?; + // Serialize and write the snapshot + let vm_snapshot = + serde_json::to_vec(snapshot).map_err(|e| MigratableError::MigrateSend(e.into()))?; - // Serialize and write the snapshot - let vm_snapshot = serde_json::to_vec(snapshot) - .map_err(|e| MigratableError::MigrateSend(e.into()))?; + vm_snapshot_file + .write(&vm_snapshot) + .map_err(|e| MigratableError::MigrateSend(e.into()))?; - vm_snapshot_file - .write(&vm_snapshot) - .map_err(|e| MigratableError::MigrateSend(e.into()))?; - - // Tell the memory manager to also send/write its own snapshot. - if let Some(memory_manager_snapshot) = - snapshot.snapshots.get(MEMORY_MANAGER_SNAPSHOT_ID) - { - self.memory_manager - .lock() - .unwrap() - .send(&*memory_manager_snapshot.clone(), destination_url)?; - } else { - return Err(MigratableError::Restore(anyhow!( - "Missing memory manager snapshot" - ))); - } - } - _ => { - return Err(MigratableError::MigrateSend(anyhow!( - "Unsupported VM transport URL scheme: {}", - url.scheme() - ))) - } + // Tell the memory manager to also send/write its own snapshot. + if let Some(memory_manager_snapshot) = snapshot.snapshots.get(MEMORY_MANAGER_SNAPSHOT_ID) { + self.memory_manager + .lock() + .unwrap() + .send(&*memory_manager_snapshot.clone(), destination_url)?; + } else { + return Err(MigratableError::Restore(anyhow!( + "Missing memory manager snapshot" + ))); } + Ok(()) } }