mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 13:45:20 +00:00
vm-migration: Add versioned versions of snapshot & state API
This will allow progressive porting of parts of the VMM to using versioned state. A new trait VersionMapped is introduced with a default implementation that returns an empty VersionMap to ease implementation. If a struct is updated the the trait will need to be fully implemented with VersionMapped::version_map() returning a new VersionMap handling the change. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
2eeeaf5753
commit
bbda08717f
45
Cargo.lock
generated
45
Cargo.lock
generated
@ -108,6 +108,15 @@ dependencies = [
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.5.0"
|
||||
@ -215,6 +224,12 @@ dependencies = [
|
||||
"bitflags 1.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc64"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55626594feae15d266d52440b26ff77de0e22230cf0c113abe619084c1ddc910"
|
||||
|
||||
[[package]]
|
||||
name = "credibility"
|
||||
version = "0.1.3"
|
||||
@ -1128,6 +1143,34 @@ version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "versionize"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7429cf68de8f091b667d27323ed323afd39584a56d533995b12ddd748e5e6ca9"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"crc64",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn",
|
||||
"versionize_derive",
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "versionize_derive"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "140aa9fd298f667ea50fa1cb0d8530076924079285c623b18b8f8a1c28386b4a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vfio-bindings"
|
||||
version = "0.2.0"
|
||||
@ -1295,6 +1338,8 @@ dependencies = [
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vm-memory",
|
||||
]
|
||||
|
||||
|
@ -10,4 +10,6 @@ thiserror = "1.0"
|
||||
serde = {version = ">=1.0.27", features = ["rc"] }
|
||||
serde_derive = ">=1.0.27"
|
||||
serde_json = ">=1.0.9"
|
||||
versionize = "0.1.6"
|
||||
versionize_derive = "0.1.4"
|
||||
vm-memory = { version = "0.5.0", features = ["backend-mmap", "backend-atomic"] }
|
||||
|
@ -12,9 +12,21 @@ extern crate vm_memory;
|
||||
use anyhow::anyhow;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize};
|
||||
|
||||
pub mod protocol;
|
||||
|
||||
/// Global VMM version for versioning
|
||||
const MAJOR_VERSION: u16 = 15;
|
||||
const MINOR_VERSION: u16 = 0;
|
||||
const VMM_VERSION: u16 = MAJOR_VERSION << 12 | MINOR_VERSION & 0b1111;
|
||||
|
||||
pub trait VersionMapped {
|
||||
fn version_map() -> VersionMap {
|
||||
VersionMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum MigratableError {
|
||||
#[error("Failed to pause migratable component: {0}")]
|
||||
@ -77,6 +89,19 @@ impl SnapshotDataSection {
|
||||
})
|
||||
}
|
||||
|
||||
/// Generate versioned state
|
||||
pub fn to_versioned_state<T>(&self) -> Result<T, MigratableError>
|
||||
where
|
||||
T: Versionize + VersionMapped,
|
||||
{
|
||||
T::deserialize(
|
||||
&mut self.snapshot.as_slice(),
|
||||
&T::version_map(),
|
||||
VMM_VERSION,
|
||||
)
|
||||
.map_err(|e| MigratableError::Restore(anyhow!("Error deserialising: {} {}", self.id, e)))
|
||||
}
|
||||
|
||||
/// Create from state that can be serialized
|
||||
pub fn new_from_state<T>(id: &str, state: &T) -> Result<Self, MigratableError>
|
||||
where
|
||||
@ -92,6 +117,24 @@ impl SnapshotDataSection {
|
||||
|
||||
Ok(snapshot_data)
|
||||
}
|
||||
|
||||
/// Create from versioned state
|
||||
pub fn new_from_versioned_state<T>(id: &str, state: &T) -> Result<Self, MigratableError>
|
||||
where
|
||||
T: Versionize + VersionMapped,
|
||||
{
|
||||
let mut snapshot = Vec::new();
|
||||
state
|
||||
.serialize(&mut snapshot, &T::version_map(), VMM_VERSION)
|
||||
.map_err(|e| MigratableError::Snapshot(anyhow!("Error serialising: {} {}", id, e)))?;
|
||||
|
||||
let snapshot_data = SnapshotDataSection {
|
||||
id: format!("{}-section", id),
|
||||
snapshot,
|
||||
};
|
||||
|
||||
Ok(snapshot_data)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Snapshottable component's snapshot is a tree of snapshots, where leafs
|
||||
@ -138,6 +181,17 @@ impl Snapshot {
|
||||
Ok(snapshot_data)
|
||||
}
|
||||
|
||||
/// Create from versioned state
|
||||
pub fn new_from_versioned_state<T>(id: &str, state: &T) -> Result<Self, MigratableError>
|
||||
where
|
||||
T: Versionize + VersionMapped,
|
||||
{
|
||||
let mut snapshot_data = Snapshot::new(id);
|
||||
snapshot_data.add_data_section(SnapshotDataSection::new_from_versioned_state(id, state)?);
|
||||
|
||||
Ok(snapshot_data)
|
||||
}
|
||||
|
||||
/// Add a sub-component's Snapshot to the Snapshot.
|
||||
pub fn add_snapshot(&mut self, snapshot: Snapshot) {
|
||||
self.snapshots
|
||||
@ -159,6 +213,17 @@ impl Snapshot {
|
||||
.ok_or_else(|| MigratableError::Restore(anyhow!("Missing section for {}", id)))?
|
||||
.to_state()
|
||||
}
|
||||
|
||||
/// Generate versioned state
|
||||
pub fn to_versioned_state<T>(&self, id: &str) -> Result<T, MigratableError>
|
||||
where
|
||||
T: Versionize + VersionMapped,
|
||||
{
|
||||
self.snapshot_data
|
||||
.get(&format!("{}-section", id))
|
||||
.ok_or_else(|| MigratableError::Restore(anyhow!("Missing section for {}", id)))?
|
||||
.to_versioned_state()
|
||||
}
|
||||
}
|
||||
|
||||
/// A snapshottable component can be snapshotted.
|
||||
|
Loading…
Reference in New Issue
Block a user