Refactor VirtualizationHostTestCases
The init ramfs used by the test is now built using the soong module type
`android_filesystem`. This not only simplifies the build script, but
also verifies that the new build system construct correctly creates the
ramdisk image.
In addition, only the test data (kernel, initramfs, and the server) that
match with the target architecture are copied.
Bug: 178978059
Test: atest VirtualizationHostTestCases
Change-Id: Ibacc66fc5842f950c9ea16001e62bd44ed9b867c
diff --git a/docs/getting_started/index.md b/docs/getting_started/index.md
index 022831b..e43124c 100644
--- a/docs/getting_started/index.md
+++ b/docs/getting_started/index.md
@@ -35,7 +35,8 @@
[CrosVM](https://android.googlesource.com/platform/external/crosvm/) is a Rust-based Virtual Machine
Monitor (VMM) originally built for ChromeOS and ported to Android.
-It is not installed in `release` builds of Android but you will find it in `userdebug` and `eng`
+It is not installed in regular Android builds (yet!), but it's installed in the
+VIM3L (yukawa) build, as part of the `com.android.virt` APEX.
builds.
### Spawning your own VMs
@@ -46,31 +47,33 @@
$ adb root
$ adb push <kernel> /data/local/tmp/kernel
$ adb push <ramdisk> /data/local/tmp/ramdisk
-$ adb shell crosvm run --initrd /data/local/tmp/ramdisk /data/local/tmp/kernel
+$ adb shell /apex/com.android.virt/bin/crosvm run --initrd /data/local/tmp/ramdisk /data/local/tmp/kernel
```
-### Syncing system files
+### Building and updating CrosVM
-When you're developing CrosVM, it is handy to update the system files using `adb sync` instead of
-flashing the device each time. It requires root and mounting the system image as writable.
+You can update CrosVM by updating the `com.android.virt` APEX where CrosVM is
+in. If your device already has `com.android.virt` (e.g. VIM3L),
-If you're using the emulator (goldfish), the following instructions will only work if it was
-started with `-writable-system`.
+``` shell
+$ m com.android.virt
+$ adb install out/target/product/<device_name>/system/apex/com.android.virt.apex
+$ adb reboot
+```
-First, disable verity checks on your device, reboot and remount the system partition.
-This is only needed once:
+If it doesn't have the APEX yet, you first need to place it manually to the
+system partition.
+
``` shell
$ adb root
$ adb disable-verity
$ adb reboot
$ adb wait-for-device root
$ adb remount
+$ m com.android.virt
+$ adb sync
+$ adb reboot
```
-Now (re-)build CrosVM and sync the system files:
-``` shell
-$ m crosvm
-$ adb shell stop
-$ adb sync
-$ adb shell start
-```
+Once the APEX is in `/system/apex`, you can use `adb install` to update it
+further.
diff --git a/tests/hostside/Android.bp b/tests/hostside/Android.bp
index f099b9e..7946080 100644
--- a/tests/hostside/Android.bp
+++ b/tests/hostside/Android.bp
@@ -18,8 +18,8 @@
kernel_version = "5.10"
-kernel_target_stem = ":kernel_prebuilts-" + kernel_version
-vendor_ramdisk_target_stem = ":virt_device_prebuilts_initramfs-" + kernel_version
+kernel_stem = "kernel_prebuilts-" + kernel_version
+kernel_modules_stem = "virt_device_prebuilts_kernel_modules-" + kernel_version
// JAR containing all virtualization host-side tests.
java_test_host {
@@ -29,81 +29,46 @@
libs: ["tradefed"],
data: [
":virt_hostside_tests_kernel",
- ":virt_hostside_tests_initramfs-arm64",
- ":virt_hostside_tests_initramfs-x86_64",
- ":vm_config.arm64.json",
- ":vm_config.x86_64.json",
+ ":virt_hostside_tests_initramfs",
+ ":virt_hostside_tests_vm_config",
],
required: [
"virt_hostside_tests_vsock_server",
],
}
-// Give kernel images unique file names.
-genrule {
+prebuilt_etc {
name: "virt_hostside_tests_kernel",
- srcs: [
- kernel_target_stem + "-arm64",
- kernel_target_stem + "-x86_64",
- ],
- out: [
- "virt_hostside_tests_kernel-arm64",
- "virt_hostside_tests_kernel-x86_64",
- ],
- tool_files: ["scripts/place_files.sh"],
- cmd: "$(location scripts/place_files.sh) $(in) -- $(out)",
+ src: "nofile",
+ arch: {
+ arm64: {
+ src: ":" + kernel_stem + "-arm64",
+ },
+ x86_64: {
+ src: ":" + kernel_stem + "-x86_64",
+ },
+ },
}
// Copy config files to output directory so that AndroidTest.xml can copy them to the device.
filegroup {
- name: "vm_config.arm64.json",
- srcs: ["vm_config.arm64.json"],
+ name: "virt_hostside_tests_vm_config",
+ srcs: ["vm_config.json"],
}
-filegroup {
- name: "vm_config.x86_64.json",
- srcs: ["vm_config.x86_64.json"],
-}
-
-// Ramdisk containing /init and test binaries/resources needed inside guest.
-genrule {
- name: "virt_hostside_tests_initramfs_base",
- tools: [
- "mkbootfs",
- "lz4",
+android_filesystem {
+ name: "virt_hostside_tests_initramfs",
+ arch: {
+ arm64: {
+ deps: [kernel_modules_stem + "-arm64"],
+ },
+ x86_64: {
+ deps: [kernel_modules_stem + "-x86_64"],
+ },
+ },
+ deps: [
+ "virt_hostside_tests_guest_init",
+ "virt_hostside_tests_vsock_client",
],
- tool_files: ["scripts/place_files.sh"],
- out: ["initramfs.lz4"],
- srcs: [
- ":virt_hostside_tests_guest_init",
- ":virt_hostside_tests_vsock_client",
- ],
- cmd: "$(location scripts/place_files.sh) $(in) -- " +
- "$(genDir)/root/init " +
- "$(genDir)/root/bin/vsock_client " +
- "&& $(location mkbootfs) $(genDir)/root | $(location lz4) -fq - $(out)",
-}
-
-// Default rule for producing a combined base + vendor ramdisk.
-genrule_defaults {
- name: "virt_hostside_tests_initramfs_concat",
- srcs: [":virt_hostside_tests_initramfs_base"],
- tools: ["lz4"],
- cmd: "cat $(in) | $(location lz4) -dfq - $(out)",
-}
-
-// Combined base + vendor ramdisk for arm64.
-genrule {
- name: "virt_hostside_tests_initramfs-arm64",
- defaults: ["virt_hostside_tests_initramfs_concat"],
- srcs: [vendor_ramdisk_target_stem + "-arm64"],
- out: ["virt_hostside_tests_initramfs-arm64"],
-}
-
-// Combined base + vendor ramdisk for x86_64.
-genrule {
- name: "virt_hostside_tests_initramfs-x86_64",
- defaults: ["virt_hostside_tests_initramfs_concat"],
- srcs: [vendor_ramdisk_target_stem + "-x86_64"],
- out: ["virt_hostside_tests_initramfs-x86_64"],
+ type: "cpio",
}
diff --git a/tests/hostside/AndroidTest.xml b/tests/hostside/AndroidTest.xml
index 42dd680..c97a1df 100644
--- a/tests/hostside/AndroidTest.xml
+++ b/tests/hostside/AndroidTest.xml
@@ -33,13 +33,10 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="abort-on-push-failure" value="true" />
- <option name="push-file" key="virt_hostside_tests_kernel-arm64" value="/data/local/tmp/virt-test/arm64/kernel" />
- <option name="push-file" key="virt_hostside_tests_initramfs-arm64" value="/data/local/tmp/virt-test/arm64/initramfs" />
- <option name="push-file" key="vm_config.arm64.json" value="/data/local/tmp/virt-test/arm64/vm_config.json" />
- <option name="push-file" key="virt_hostside_tests_kernel-x86_64" value="/data/local/tmp/virt-test/x86_64/kernel" />
- <option name="push-file" key="virt_hostside_tests_initramfs-x86_64" value="/data/local/tmp/virt-test/x86_64/initramfs" />
- <option name="push-file" key="vm_config.x86_64.json" value="/data/local/tmp/virt-test/x86_64/vm_config.json" />
- <option name="push-file" key="virt_hostside_tests_vsock_server" value="/data/local/tmp/virt-test" />
+ <option name="push-file" key="vm_config.json" value="/data/local/tmp/virt-test/vm_config.json" />
+ <option name="push-file" key="virt_hostside_tests_kernel" value="/data/local/tmp/virt-test/kernel" />
+ <option name="push-file" key="virt_hostside_tests_initramfs.img" value="/data/local/tmp/virt-test/initramfs" />
+ <option name="push-file" key="vsock_server" value="/data/local/tmp/virt-test/vsock_server" />
</target_preparer>
<!-- Root currently needed to run CrosVM.
diff --git a/tests/hostside/java/android/virt/test/VirtTestCase.java b/tests/hostside/java/android/virt/test/VirtTestCase.java
index 1817847..5c030a8 100644
--- a/tests/hostside/java/android/virt/test/VirtTestCase.java
+++ b/tests/hostside/java/android/virt/test/VirtTestCase.java
@@ -19,33 +19,22 @@
import static org.junit.Assert.*;
import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
import org.junit.Before;
import java.util.ArrayList;
-public abstract class VirtTestCase extends DeviceTestCase implements IAbiReceiver {
- private static final String DEVICE_DIR = "/data/local/tmp/virt-test";
+public abstract class VirtTestCase extends DeviceTestCase {
- private IAbi mAbi;
+ private static final String DEVICE_DIR = "/data/local/tmp/virt-test";
@Before
public void setUp() throws Exception {
getDevice().waitForDeviceAvailable();
}
- private String getAbiName() {
- String name = mAbi.getName();
- if ("arm64-v8a".equals(name)) {
- name = "arm64";
- }
- return name;
- }
-
protected String getDevicePathForTestBinary(String targetName) throws Exception {
- String path = String.format("%s/%s/%s", DEVICE_DIR, getAbiName(), targetName);
+ String path = String.format("%s/%s", DEVICE_DIR, targetName);
if (!getDevice().doesFileExist(path)) {
throw new IllegalArgumentException(String.format(
"Binary for target %s not found on device at \"%s\"", targetName, path));
@@ -69,8 +58,4 @@
return String.join(" ", strings);
}
- @Override
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
}
diff --git a/tests/hostside/java/android/virt/test/VsockTest.java b/tests/hostside/java/android/virt/test/VsockTest.java
index 397b41e..4895c9a 100644
--- a/tests/hostside/java/android/virt/test/VsockTest.java
+++ b/tests/hostside/java/android/virt/test/VsockTest.java
@@ -31,12 +31,10 @@
private static final TimeUnit TIMEOUT_UNIT = TimeUnit.MINUTES;
private static final int RETRIES = 0;
- private static final Integer HOST_CID = 2;
private static final Integer GUEST_PORT = 45678;
private static final String TEST_MESSAGE = "HelloWorld";
- private static final String CLIENT_PATH = "bin/vsock_client";
- private static final String SERVER_TARGET = "virt_hostside_tests_vsock_server";
+ private static final String SERVER_TARGET = "vsock_server";
private static final String VIRT_MANAGER_COMMAND = "virtmanager";
@Test
@@ -46,7 +44,6 @@
final String serverPath = getDevicePathForTestBinary(SERVER_TARGET);
final String vmConfigPath = getDevicePathForTestBinary("vm_config.json");
final String serverCmd = createCommand(serverPath, GUEST_PORT, vmConfigPath);
- final String clientCmd = createCommand(CLIENT_PATH, HOST_CID, GUEST_PORT, TEST_MESSAGE);
// Start Virt Manager. This will eventually be a system service, but for now we run it
// manually.
diff --git a/tests/hostside/native/init/Android.bp b/tests/hostside/native/init/Android.bp
index 4934a6d..f2c179b 100644
--- a/tests/hostside/native/init/Android.bp
+++ b/tests/hostside/native/init/Android.bp
@@ -26,4 +26,5 @@
"liblog",
"libmodprobe",
],
+ stem: "init",
}
diff --git a/tests/hostside/native/vsock/Android.bp b/tests/hostside/native/vsock/Android.bp
index 966bc04..5151d62 100644
--- a/tests/hostside/native/vsock/Android.bp
+++ b/tests/hostside/native/vsock/Android.bp
@@ -19,14 +19,19 @@
cc_test {
name: "virt_hostside_tests_vsock_server",
srcs: ["server.cc"],
- shared_libs: [
+ static_libs: [
+ // The existence of the library in the system partition is not guaranteed.
+ // Let's have our own copy of it.
"android.system.virtmanager-cpp",
+ ],
+ shared_libs: [
"libbase",
"libbinder",
"liblog",
"libutils",
],
test_suites: ["device-tests"],
+ stem: "vsock_server",
}
cc_binary {
@@ -38,4 +43,5 @@
],
static_executable: true,
installable: false,
+ stem: "vsock_client",
}
diff --git a/tests/hostside/nofile b/tests/hostside/nofile
new file mode 100644
index 0000000..eb4638a
--- /dev/null
+++ b/tests/hostside/nofile
@@ -0,0 +1,2 @@
+// This file is used as src of virt_hostside_tests_kernel module for the architectures
+// other than arm64 and x86_64
diff --git a/tests/hostside/scripts/place_files.sh b/tests/hostside/scripts/place_files.sh
deleted file mode 100755
index f0a9603..0000000
--- a/tests/hostside/scripts/place_files.sh
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env bash
-##
-## Copyright (C) 2020 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.
-##
-
-set -euo pipefail
-
-# Wrapper around 'expr' that handles the fact that it returns code 1
-# if the result is zero/null. That messes with 'set -e'.
-function expr {
- eval 'val=$($(which expr) $@); ret=$?'
- if [ "$ret" != 0 -a "$ret" != 1 ]
- then
- return $ret
- fi
- echo "$val"
-}
-
-ARGS=( "$@" )
-NUM_ARGS=${#ARGS[@]}
-
-POS_DIVIDER=-1
-for i in $(seq 0 $(expr $NUM_ARGS - 1))
-do
- if [ "${ARGS[$i]}" == "--" ]
- then
- if [ "$POS_DIVIDER" -eq -1 ]
- then
- POS_DIVIDER=$i
- else
- echo "Multiple dividers in command line inputs" 1>&2
- exit 1
- fi
- fi
-done
-
-if [ "$POS_DIVIDER" -eq -1 ]
-then
- echo "Divider expected among command line inputs" 1>&2
- exit 1
-fi
-
-NUM_INPUT=${POS_DIVIDER}
-NUM_OUTPUT=$(expr $NUM_ARGS - $POS_DIVIDER - 1)
-
-if [ "$NUM_INPUT" -ne "$NUM_OUTPUT" ]
-then
- echo "Number of inputs does not match number of outputs" 1>&2
- exit 1
-fi
-
-for i in $(seq 0 $(expr $NUM_INPUT - 1))
-do
- INPUT="${ARGS[$i]}"
- OUTPUT="${ARGS[$NUM_INPUT + $i + 1]}"
- mkdir -p "$(dirname "$OUTPUT")"
- cp "$INPUT" "$OUTPUT"
-done
diff --git a/tests/hostside/vm_config.arm64.json b/tests/hostside/vm_config.arm64.json
deleted file mode 100644
index 92f2fb8..0000000
--- a/tests/hostside/vm_config.arm64.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "kernel": "/data/local/tmp/virt-test/arm64/kernel",
- "initrd": "/data/local/tmp/virt-test/arm64/initramfs",
- "params": "bin/vsock_client 2 45678 HelloWorld"
-}
\ No newline at end of file
diff --git a/tests/hostside/vm_config.json b/tests/hostside/vm_config.json
new file mode 100644
index 0000000..762baec
--- /dev/null
+++ b/tests/hostside/vm_config.json
@@ -0,0 +1,5 @@
+{
+ "kernel": "/data/local/tmp/virt-test/kernel",
+ "initrd": "/data/local/tmp/virt-test/initramfs",
+ "params": "rdinit=/bin/init bin/vsock_client 2 45678 HelloWorld"
+}
diff --git a/tests/hostside/vm_config.x86_64.json b/tests/hostside/vm_config.x86_64.json
deleted file mode 100644
index 9ea95ab..0000000
--- a/tests/hostside/vm_config.x86_64.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "kernel": "/data/local/tmp/virt-test/x86_64/kernel",
- "initrd": "/data/local/tmp/virt-test/x86_64/initramfs",
- "params": "bin/vsock_client 2 45678 HelloWorld"
-}
\ No newline at end of file
diff --git a/virtmanager/src/main.rs b/virtmanager/src/main.rs
index 971ef86..abc0d7b 100644
--- a/virtmanager/src/main.rs
+++ b/virtmanager/src/main.rs
@@ -179,6 +179,8 @@
if let Some(params) = &config.params {
command.arg("--params").arg(params);
}
+ // TODO(jiyong): Don't redirect console to the host syslog
+ command.arg("--serial=type=syslog");
command.arg(&config.kernel);
info!("Running {:?}", command);
// TODO: Monitor child process, and remove from VM map if it dies.