Expand description
Provides access to VM image formats.
Simple example (requires the sync-wrappers
feature):
use imago::file::File;
use imago::qcow2::Qcow2;
use imago::{FormatDriverBuilder, PermissiveImplicitOpenGate, SyncFormatAccess};
use std::fs::OpenOptions;
// Produce read-only qcow2 instance using purely `File` for storage
let mut qcow2 = Qcow2::<File>::builder_path("image.qcow2")
.open_sync(PermissiveImplicitOpenGate::default())?;
let qcow2 = SyncFormatAccess::new(qcow2)?;
let mut buf = vec![0u8; 512];
qcow2.read(&mut buf, 0)?;
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 imago::file::File;
use imago::null::Null;
use imago::qcow2::Qcow2;
use imago::raw::Raw;
use imago::{
DenyImplicitOpenGate, DynStorage, FormatAccess, FormatDriverBuilder,
PermissiveImplicitOpenGate, Storage, StorageOpenOptions,
};
use std::sync::Arc;
// Produce qcow2 instance with arbitrary (and potentially mixed) storage instances
// (By using `Box<dyn DynStorage>` as the `Storage` type.)
let backing_storage: Box<dyn DynStorage> = Box::new(Null::new(0));
let backing = Raw::builder(backing_storage)
.open(DenyImplicitOpenGate::default())
.await?;
let backing = Arc::new(FormatAccess::new(backing));
// `Box<dyn DynStorage>::open()` defaults to using the `imago::file::File` driver, so we can
// use paths with `Box<dyn DynStorage>`, too.
// Despite explicitly setting a backing image, we still need `PermissiveImplicitOpenGate`
// instead of `DenyImplicitOpenGate`, because `builder_path()` will need to implicitly open
// that storage object. Passing an explicitly opened storage object via `builder()` would
// remedy that.
let qcow2 = Qcow2::builder_path("image.qcow2")
.storage_open_options(StorageOpenOptions::new().direct(true))
.write(true)
.backing(Some(Arc::clone(&backing)))
.open(PermissiveImplicitOpenGate::default())
.await?;
let qcow2 = FormatAccess::new(qcow2);
let mut buf = vec![0u8; 512];
qcow2.read(&mut buf, 0).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 nativeasync
interface. Note that these build atokio
runtime in which they run theasync
functions, so using theasync
interface is definitely preferred. -
vm-memory
: Provide conversion functionsIoVector::from_volatile_slice
andIoVectorMut::from_volatile_slice
to convert the vm-memory crate’s[VolatileSlice]
arrays into imago’s native I/O vectors.
Re-exports§
pub use format::access::FormatAccess;
pub use format::access::Mapping;
pub use format::builder::FormatCreateBuilder;
pub use format::builder::FormatDriverBuilder;
pub use format::drivers::ShallowMapping;
pub use format::gate::DenyImplicitOpenGate;
pub use format::gate::PermissiveImplicitOpenGate;
pub use format::sync_wrappers::SyncFormatAccess;
pub use storage::ext::StorageExt;
pub use storage::DynStorage;
pub use storage::Storage;
pub use storage::StorageCreateOptions;
pub use storage::StorageOpenOptions;
Modules§
- annotated
- Annotating wrapper around storage objects.
- async_
lru_ 🔒cache - Provides a least-recently-used cache with async access.
- file
- Use a plain file or host block device as storage.
- format
- Core functionality.
- io_
buffers - Types for I/O buffers.
- macros 🔒
- Helper macros.
- misc_
helpers 🔒 - Miscellaneous helper functions.
- null
- Null storage.
- qcow2
- Qcow2 implementation.
- raw
- Access generic files as images.
- storage
- Helper functionality to access storage.
- vector_
select 🔒 - Async select over future vectors.