Merge "Format instance.img"

This commit is contained in:
Jiyong Park 2021-08-25 05:59:42 +00:00 committed by Gerrit Code Review
commit 1b9e4e620b
8 changed files with 106 additions and 9 deletions

View File

@ -54,6 +54,7 @@ using aidl::android::system::virtualizationservice::BnVirtualMachineCallback;
using aidl::android::system::virtualizationservice::IVirtualizationService;
using aidl::android::system::virtualizationservice::IVirtualMachine;
using aidl::android::system::virtualizationservice::IVirtualMachineCallback;
using aidl::android::system::virtualizationservice::PartitionType;
using aidl::android::system::virtualizationservice::VirtualMachineConfig;
using aidl::com::android::compos::CompOsKeyData;
using aidl::com::android::compos::ICompOsService;
@ -442,7 +443,8 @@ static Result<void> makeInstanceImage(const std::string& image_path) {
return ErrnoError() << "Failed to create image file";
}
auto status = service->initializeWritablePartition(fd, 10 * 1024 * 1024);
auto status = service->initializeWritablePartition(fd, 10 * 1024 * 1024,
PartitionType::ANDROID_VM_INSTANCE);
if (!status.isOk()) {
return Error() << "Failed to initialize partition: " << status.getDescription();
}

View File

@ -29,6 +29,7 @@ import android.os.ServiceManager;
import android.system.virtualizationservice.IVirtualMachine;
import android.system.virtualizationservice.IVirtualMachineCallback;
import android.system.virtualizationservice.IVirtualizationService;
import android.system.virtualizationservice.PartitionType;
import android.system.virtualizationservice.VirtualMachineAppConfig;
import java.io.File;
@ -165,7 +166,8 @@ public class VirtualMachine {
try {
service.initializeWritablePartition(
ParcelFileDescriptor.open(vm.mInstanceFilePath, MODE_READ_WRITE),
INSTANCE_FILE_SIZE);
INSTANCE_FILE_SIZE,
PartitionType.ANDROID_VM_INSTANCE);
} catch (FileNotFoundException e) {
throw new VirtualMachineException("instance image missing", e);
} catch (RemoteException e) {
@ -288,7 +290,6 @@ public class VirtualMachine {
android.system.virtualizationservice.VirtualMachineConfig vmConfigParcel =
android.system.virtualizationservice.VirtualMachineConfig.appConfig(appConfig);
mVirtualMachine = service.startVm(vmConfigParcel, mConsoleWriter);
mVirtualMachine.registerCallback(
new IVirtualMachineCallback.Stub() {

View File

@ -16,6 +16,7 @@
package android.system.virtualizationservice;
import android.system.virtualizationservice.IVirtualMachine;
import android.system.virtualizationservice.PartitionType;
import android.system.virtualizationservice.VirtualMachineConfig;
import android.system.virtualizationservice.VirtualMachineDebugInfo;
@ -32,7 +33,8 @@ interface IVirtualizationService {
*
* The file must be open with both read and write permissions, and should be a new empty file.
*/
void initializeWritablePartition(in ParcelFileDescriptor imageFd, long size);
void initializeWritablePartition(
in ParcelFileDescriptor imageFd, long size, PartitionType type);
/**
* Create or update an idsig file that digests the given APK file. The idsig file follows the

View File

@ -0,0 +1,32 @@
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.system.virtualizationservice;
/**
* Type of the writable partition that virtualizationservice creates via
* initializeWritablePartition.
*/
@Backing(type="int")
enum PartitionType {
/**
* The partition is simply initialized as all zeros
*/
RAW = 0,
/**
* The partition is initialized as an instance image which is formatted to hold per-VM secrets
*/
ANDROID_VM_INSTANCE = 1,
}

View File

@ -32,6 +32,7 @@ use android_system_virtualizationservice::aidl::android::system::virtualizations
VirtualMachineRawConfig::VirtualMachineRawConfig,
};
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::VirtualMachineDebugInfo::VirtualMachineDebugInfo;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::PartitionType::PartitionType;
use android_system_virtualizationservice::binder::{
self, BinderFeatures, ExceptionCode, Interface, ParcelFileDescriptor, Status, Strong, ThreadState,
};
@ -47,6 +48,7 @@ use microdroid_payload_config::VmPayloadConfig;
use std::convert::TryInto;
use std::ffi::CString;
use std::fs::{File, OpenOptions, create_dir};
use std::io::{Error, ErrorKind, Write};
use std::num::NonZeroU32;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
use std::path::{Path, PathBuf};
@ -76,6 +78,12 @@ const PORT_VM_BINDER_SERVICE: u32 = 5000;
/// Gaps in composite disk images are filled with a shared zero.img.
const ZERO_FILLER_SIZE: u64 = 4096;
/// Magic string for the instance image
const ANDROID_VM_INSTANCE_MAGIC: &str = "Android-VM-instance";
/// Version of the instance image format
const ANDROID_VM_INSTANCE_VERSION: u16 = 1;
/// Implementation of `IVirtualizationService`, the entry point of the AIDL service.
#[derive(Debug, Default)]
pub struct VirtualizationService {
@ -199,6 +207,7 @@ impl IVirtualizationService for VirtualizationService {
&self,
image_fd: &ParcelFileDescriptor,
size: i64,
partition_type: PartitionType,
) -> binder::Result<()> {
check_manage_access()?;
let size = size.try_into().map_err(|e| {
@ -209,13 +218,28 @@ impl IVirtualizationService for VirtualizationService {
})?;
let image = clone_file(image_fd)?;
QcowFile::new(image, size).map_err(|e| {
let mut part = QcowFile::new(image, size).map_err(|e| {
new_binder_exception(
ExceptionCode::SERVICE_SPECIFIC,
format!("Failed to create QCOW2 image: {}", e),
)
})?;
match partition_type {
PartitionType::RAW => Ok(()),
PartitionType::ANDROID_VM_INSTANCE => format_as_android_vm_instance(&mut part),
_ => Err(Error::new(
ErrorKind::Unsupported,
format!("Unsupported partition type {:?}", partition_type),
)),
}
.map_err(|e| {
new_binder_exception(
ExceptionCode::SERVICE_SPECIFIC,
format!("Failed to initialize partition as {:?}: {}", partition_type, e),
)
})?;
Ok(())
}
@ -351,6 +375,12 @@ fn write_zero_filler(zero_filler_path: &Path) -> Result<()> {
Ok(())
}
fn format_as_android_vm_instance(part: &mut dyn Write) -> std::io::Result<()> {
part.write_all(ANDROID_VM_INSTANCE_MAGIC.as_bytes())?;
part.write_all(&ANDROID_VM_INSTANCE_VERSION.to_le_bytes())?;
part.flush()
}
/// Given the configuration for a disk image, assembles the `DiskFile` to pass to crosvm.
///
/// This may involve assembling a composite disk from a set of partition images.

View File

@ -15,6 +15,7 @@
//! Command to create an empty partition
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualizationService::IVirtualizationService;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::PartitionType::PartitionType;
use android_system_virtualizationservice::binder::{ParcelFileDescriptor, Strong};
use anyhow::{Context, Error};
use std::convert::TryInto;
@ -26,6 +27,7 @@ pub fn command_create_partition(
service: Strong<dyn IVirtualizationService>,
image_path: &Path,
size: u64,
partition_type: PartitionType,
) -> Result<(), Error> {
let image = OpenOptions::new()
.create_new(true)
@ -34,7 +36,14 @@ pub fn command_create_partition(
.open(image_path)
.with_context(|| format!("Failed to create {:?}", image_path))?;
service
.initializeWritablePartition(&ParcelFileDescriptor::new(image), size.try_into()?)
.context("Failed to initialize partition with size {}, size")?;
.initializeWritablePartition(
&ParcelFileDescriptor::new(image),
size.try_into()?,
partition_type,
)
.context(format!(
"Failed to initialize partition type: {:?}, size: {}",
partition_type, size
))?;
Ok(())
}

View File

@ -19,6 +19,7 @@ mod run;
mod sync;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualizationService::IVirtualizationService;
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::PartitionType::PartitionType;
use android_system_virtualizationservice::binder::{wait_for_interface, ProcessState, Strong};
use anyhow::{Context, Error};
use create_partition::command_create_partition;
@ -91,9 +92,21 @@ enum Opt {
/// The desired size of the partition, in bytes.
size: u64,
/// Type of the partition
#[structopt(short="t", long="type", default_value="raw", parse(try_from_str=parse_partition_type))]
partition_type: PartitionType,
},
}
fn parse_partition_type(s: &str) -> Result<PartitionType, String> {
match s {
"raw" => Ok(PartitionType::RAW),
"instance" => Ok(PartitionType::ANDROID_VM_INSTANCE),
_ => Err(format!("Invalid partition type {}", s)),
}
}
fn main() -> Result<(), Error> {
env_logger::init();
let opt = Opt::from_args();
@ -122,7 +135,9 @@ fn main() -> Result<(), Error> {
}
Opt::Stop { cid } => command_stop(service, cid),
Opt::List => command_list(service),
Opt::CreatePartition { path, size } => command_create_partition(service, &path, size),
Opt::CreatePartition { path, size, partition_type } => {
command_create_partition(service, &path, size, partition_type)
}
}
}

View File

@ -22,6 +22,7 @@ use android_system_virtualizationservice::aidl::android::system::virtualizations
BnVirtualMachineCallback, IVirtualMachineCallback,
};
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
PartitionType::PartitionType,
VirtualMachineAppConfig::VirtualMachineAppConfig,
VirtualMachineConfig::VirtualMachineConfig,
};
@ -60,7 +61,12 @@ pub fn command_run_app(
if !instance.exists() {
const INSTANCE_FILE_SIZE: u64 = 10 * 1024 * 1024;
command_create_partition(service.clone(), instance, INSTANCE_FILE_SIZE)?;
command_create_partition(
service.clone(),
instance,
INSTANCE_FILE_SIZE,
PartitionType::ANDROID_VM_INSTANCE,
)?;
}
let config = VirtualMachineConfig::AppConfig(VirtualMachineAppConfig {