Build composite image in VirtualizationService.
Bug: 184131523
Test: atest VirtualizationTestCases
Test: ran microdroid manually
Change-Id: I24eb776bb3049a4cdc5f000607447a73bd0adeec
diff --git a/vm/src/config.rs b/vm/src/config.rs
index cbdd0bf..3bd023f 100644
--- a/vm/src/config.rs
+++ b/vm/src/config.rs
@@ -16,6 +16,7 @@
use android_system_virtualizationservice::{
aidl::android::system::virtualizationservice::DiskImage::DiskImage as AidlDiskImage,
+ aidl::android::system::virtualizationservice::Partition::Partition as AidlPartition,
aidl::android::system::virtualizationservice::VirtualMachineConfig::VirtualMachineConfig,
binder::ParcelFileDescriptor,
};
@@ -53,6 +54,11 @@
if self.bootloader.is_some() && (self.kernel.is_some() || self.initrd.is_some()) {
bail!("Can't have both bootloader and kernel/initrd image.");
}
+ for disk in &self.disks {
+ if disk.image.is_none() == disk.partitions.is_empty() {
+ bail!("Exactly one of image and partitions must be specified. (Was {:?}.)", disk);
+ }
+ }
Ok(())
}
@@ -68,20 +74,11 @@
/// Manager.
pub fn to_parcelable(&self) -> Result<VirtualMachineConfig, Error> {
Ok(VirtualMachineConfig {
- kernel: maybe_open_parcel_file(&self.kernel)?,
- initrd: maybe_open_parcel_file(&self.initrd)?,
+ kernel: maybe_open_parcel_file(&self.kernel, false)?,
+ initrd: maybe_open_parcel_file(&self.initrd, false)?,
params: self.params.clone(),
- bootloader: maybe_open_parcel_file(&self.bootloader)?,
- disks: self
- .disks
- .iter()
- .map(|disk| {
- Ok(AidlDiskImage {
- writable: disk.writable,
- image: Some(open_parcel_file(&disk.image, disk.writable)?),
- })
- })
- .collect::<Result<_, Error>>()?,
+ bootloader: maybe_open_parcel_file(&self.bootloader, false)?,
+ disks: self.disks.iter().map(DiskImage::to_parcelable).collect::<Result<_, Error>>()?,
})
}
}
@@ -89,12 +86,52 @@
/// A disk image to be made available to the VM.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct DiskImage {
- /// The filename of the disk image.
- pub image: PathBuf,
+ /// The filename of the disk image, if it already exists. Exactly one of this and `partitions`
+ /// must be specified.
+ #[serde(default)]
+ pub image: Option<PathBuf>,
+ /// A set of partitions to be assembled into a composite image.
+ #[serde(default)]
+ pub partitions: Vec<Partition>,
/// Whether this disk should be writable by the VM.
pub writable: bool,
}
+impl DiskImage {
+ fn to_parcelable(&self) -> Result<AidlDiskImage, Error> {
+ let partitions =
+ self.partitions.iter().map(Partition::to_parcelable).collect::<Result<_, Error>>()?;
+ Ok(AidlDiskImage {
+ image: maybe_open_parcel_file(&self.image, self.writable)?,
+ writable: self.writable,
+ partitions,
+ })
+ }
+}
+
+// TODO: Share this type with virtualizationservice::composite::config.
+/// A partition for a disk image to be made available to the VM.
+#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
+pub struct Partition {
+ /// A label for the partition.
+ pub label: String,
+ /// The filename of the partition image.
+ pub path: PathBuf,
+ /// Whether the partition should be writable.
+ #[serde(default)]
+ pub writable: bool,
+}
+
+impl Partition {
+ fn to_parcelable(&self) -> Result<AidlPartition, Error> {
+ Ok(AidlPartition {
+ image: Some(open_parcel_file(&self.path, self.writable)?),
+ writable: self.writable,
+ label: self.label.to_owned(),
+ })
+ }
+}
+
/// Try to open the given file and wrap it in a [`ParcelFileDescriptor`].
fn open_parcel_file(filename: &Path, writable: bool) -> Result<ParcelFileDescriptor, Error> {
Ok(ParcelFileDescriptor::new(
@@ -109,6 +146,7 @@
/// If the given filename is `Some`, try to open it and wrap it in a [`ParcelFileDescriptor`].
fn maybe_open_parcel_file(
filename: &Option<PathBuf>,
+ writable: bool,
) -> Result<Option<ParcelFileDescriptor>, Error> {
- filename.as_deref().map(|filename| open_parcel_file(filename, false)).transpose()
+ filename.as_deref().map(|filename| open_parcel_file(filename, writable)).transpose()
}