Imago
Provides access to VM image formats.
Simple example (requires the sync-wrappers feature):
use File;
use Qcow2;
use SyncFormatAccess;
use OpenOptions;
// Produce read-only qcow2 instance using purely `File` for storage
let mut qcow2 = open_path_sync?;
qcow2.open_implicit_dependencies_sync?;
let qcow2 = new?;
let mut buf = vec!;
qcow2.read?;
Another example, using the native async interface instead of sync wrapper functions, explicitly overriding the implicit references contained in qcow2 files, and showcasing using different types of storage (specifically normal files and null storage):
use File;
use Null;
use Qcow2;
use Raw;
use ;
use Arc;
let qcow2_file_opts = new
.write
.filename;
let qcow2_file = open.await?;
// Produce qcow2 instance with arbitrary (and potentially mixed) storage instances
let mut qcow2 =
open_image
.await?;
let backing_storage: = Boxnew;
let backing = open_image.await?;
let backing = new;
qcow2.set_backing;
// Open potentially remaining dependencies (like an external data file)
qcow2.open_implicit_dependencies.await?;
let qcow2 = new;
let mut buf = vec!;
qcow2.read.await?;
qcow2.flush.await?;
Flushing
Given that AsyncDrop is not stable yet (and probably will not be stable for a long time),
callers must ensure that images are properly flushed before dropping them, i.e. call
.flush().await on any image that is not read-only.
(The synchronous wrapper SyncFormatAccess does perform a synchronous flush in its Drop
implementation.)
Features
-
sync-wrappers: Provide synchronous wrappers for the nativeasyncinterface. Note that these build atokioruntime in which they run theasyncfunctions, so using theasyncinterface is definitely preferred. -
vm-memory: Provide conversion functionsIoVector::from_volatile_sliceandIoVectorMut::from_volatile_sliceto convert the vm-memory crate’s[VolatileSlice]arrays into imago’s native I/O vectors.