1 // Copyright © 2020 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))] 6 use crate::coredump::GuestDebuggableError; 7 use crate::{config::VmConfig, vm::VmSnapshot}; 8 use anyhow::anyhow; 9 use std::fs::File; 10 use std::io::Read; 11 use std::path::PathBuf; 12 use vm_migration::{MigratableError, Snapshot}; 13 14 pub const SNAPSHOT_STATE_FILE: &str = "state.json"; 15 pub const SNAPSHOT_CONFIG_FILE: &str = "config.json"; 16 17 pub fn url_to_path(url: &str) -> std::result::Result<PathBuf, MigratableError> { 18 let path: PathBuf = url 19 .strip_prefix("file://") 20 .ok_or_else(|| { 21 MigratableError::MigrateSend(anyhow!("Could not extract path from URL: {}", url)) 22 }) 23 .map(|s| s.into())?; 24 25 if !path.is_dir() { 26 return Err(MigratableError::MigrateSend(anyhow!( 27 "Destination is not a directory" 28 ))); 29 } 30 31 Ok(path) 32 } 33 34 #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))] 35 pub fn url_to_file(url: &str) -> std::result::Result<PathBuf, GuestDebuggableError> { 36 let file: PathBuf = url 37 .strip_prefix("file://") 38 .ok_or_else(|| { 39 GuestDebuggableError::Coredump(anyhow!("Could not extract file from URL: {}", url)) 40 }) 41 .map(|s| s.into())?; 42 43 Ok(file) 44 } 45 46 pub fn recv_vm_config(source_url: &str) -> std::result::Result<VmConfig, MigratableError> { 47 let mut vm_config_path = url_to_path(source_url)?; 48 49 vm_config_path.push(SNAPSHOT_CONFIG_FILE); 50 51 // Try opening the snapshot file 52 let mut vm_config_file = 53 File::open(vm_config_path).map_err(|e| MigratableError::MigrateReceive(e.into()))?; 54 let mut bytes = Vec::new(); 55 vm_config_file 56 .read_to_end(&mut bytes) 57 .map_err(|e| MigratableError::MigrateReceive(e.into()))?; 58 59 serde_json::from_slice(&bytes).map_err(|e| MigratableError::MigrateReceive(e.into())) 60 } 61 62 pub fn recv_vm_state(source_url: &str) -> std::result::Result<Snapshot, MigratableError> { 63 let mut vm_state_path = url_to_path(source_url)?; 64 65 vm_state_path.push(SNAPSHOT_STATE_FILE); 66 67 // Try opening the snapshot file 68 let mut vm_state_file = 69 File::open(vm_state_path).map_err(|e| MigratableError::MigrateReceive(e.into()))?; 70 let mut bytes = Vec::new(); 71 vm_state_file 72 .read_to_end(&mut bytes) 73 .map_err(|e| MigratableError::MigrateReceive(e.into()))?; 74 75 serde_json::from_slice(&bytes).map_err(|e| MigratableError::MigrateReceive(e.into())) 76 } 77 78 pub fn get_vm_snapshot(snapshot: &Snapshot) -> std::result::Result<VmSnapshot, MigratableError> { 79 if let Some(snapshot_data) = snapshot.snapshot_data.as_ref() { 80 return snapshot_data.to_state(); 81 } 82 83 Err(MigratableError::Restore(anyhow!( 84 "Could not find VM config snapshot section" 85 ))) 86 } 87