Use Virt Manager for test
Bug: 171278952
Test: atest VirtualizationHostTestCases
Change-Id: Ib603194acb90d4e0952cf276c136efd246d0ce31
diff --git a/tests/hostside/Android.bp b/tests/hostside/Android.bp
index 63b3a3d..f099b9e 100644
--- a/tests/hostside/Android.bp
+++ b/tests/hostside/Android.bp
@@ -31,6 +31,8 @@
":virt_hostside_tests_kernel",
":virt_hostside_tests_initramfs-arm64",
":virt_hostside_tests_initramfs-x86_64",
+ ":vm_config.arm64.json",
+ ":vm_config.x86_64.json",
],
required: [
"virt_hostside_tests_vsock_server",
@@ -52,6 +54,17 @@
cmd: "$(location scripts/place_files.sh) $(in) -- $(out)",
}
+// 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"],
+}
+
+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",
diff --git a/tests/hostside/AndroidTest.xml b/tests/hostside/AndroidTest.xml
index 1fd86ef..42dd680 100644
--- a/tests/hostside/AndroidTest.xml
+++ b/tests/hostside/AndroidTest.xml
@@ -24,7 +24,9 @@
<!-- Kernel has vhost-vsock enabled. -->
<option name="run-command" value="ls /dev/vhost-vsock" />
<!-- CrosVM is installed. -->
- <option name="run-command" value="which crosvm" />
+ <option name="run-command" value="ls /apex/com.android.virt/bin/crosvm" />
+ <!-- Virt Manager is installed. -->
+ <option name="run-command" value="which virtmanager" />
</target_preparer>
<!-- Push test binaries to the device. -->
@@ -33,8 +35,10 @@
<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" />
</target_preparer>
diff --git a/tests/hostside/java/android/virt/test/VirtTestCase.java b/tests/hostside/java/android/virt/test/VirtTestCase.java
index 7ba6409..1817847 100644
--- a/tests/hostside/java/android/virt/test/VirtTestCase.java
+++ b/tests/hostside/java/android/virt/test/VirtTestCase.java
@@ -27,11 +27,8 @@
import java.util.ArrayList;
public abstract class VirtTestCase extends DeviceTestCase implements IAbiReceiver {
-
private static final String DEVICE_DIR = "/data/local/tmp/virt-test";
- private static final int CID_RESERVED = 2;
-
private IAbi mAbi;
@Before
@@ -72,34 +69,6 @@
return String.join(" ", strings);
}
- protected String getVmCommand(String guestCmd, Integer cid) throws Exception {
- ArrayList<String> cmd = new ArrayList<>();
-
- cmd.add("crosvm");
- cmd.add("run");
-
- cmd.add("--disable-sandbox");
-
- if (cid != null) {
- if (cid > CID_RESERVED) {
- cmd.add("--cid");
- cmd.add(cid.toString());
- } else {
- throw new IllegalArgumentException("Invalid CID " + cid);
- }
- }
-
- cmd.add("--initrd");
- cmd.add(getDevicePathForTestBinary("initramfs"));
-
- cmd.add("--params");
- cmd.add(String.format("'%s'", guestCmd));
-
- cmd.add(getDevicePathForTestBinary("kernel"));
-
- return String.join(" ", cmd);
- }
-
@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 c82db77..397b41e 100644
--- a/tests/hostside/java/android/virt/test/VsockTest.java
+++ b/tests/hostside/java/android/virt/test/VsockTest.java
@@ -18,7 +18,6 @@
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.util.CommandResult;
-import com.android.tradefed.util.CommandStatus;
import org.junit.Test;
@@ -33,21 +32,30 @@
private static final int RETRIES = 0;
private static final Integer HOST_CID = 2;
- private static final Integer GUEST_CID = 42;
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 VIRT_MANAGER_COMMAND = "virtmanager";
@Test
public void testVsockServer() throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(2);
final String serverPath = getDevicePathForTestBinary(SERVER_TARGET);
- final String serverCmd = createCommand(serverPath, GUEST_PORT);
+ 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);
- final String vmCmd = getVmCommand(clientCmd, GUEST_CID);
+
+ // Start Virt Manager. This will eventually be a system service, but for now we run it
+ // manually.
+ Future<?> virtManagerTask = executor.submit(() -> {
+ CommandResult res = getDevice().executeShellV2Command(
+ VIRT_MANAGER_COMMAND, TIMEOUT, TIMEOUT_UNIT, RETRIES);
+ CLog.d(res.getStdout());
+ return null;
+ });
// Start server in Android that listens for vsock connections.
// It will receive a message from a client in the guest VM.
@@ -58,27 +66,6 @@
return null;
});
- // Run VM that will connect to the server and send a message to it.
- Future<?> vmTask = executor.submit(() -> {
- CommandResult res = getDevice().executeShellV2Command(
- vmCmd, TIMEOUT, TIMEOUT_UNIT, RETRIES);
- CLog.d(res.getStdout()); // print VMM output into host_log
- assertEquals(CommandStatus.SUCCESS, res.getStatus());
- return null;
- });
-
- // Wait for the VMM to finish sending the message.
- try {
- vmTask.get(TIMEOUT, TIMEOUT_UNIT);
- } catch (Throwable ex) {
- // The VMM either exited with a non-zero code or it timed out.
- // Kill the server process, the test has failed.
- // Note: executeShellV2Command cannot be interrupted. This will wait
- // until `serverTask` times out.
- executor.shutdownNow();
- throw ex;
- }
-
// Wait for the server to finish processing the message.
serverTask.get(TIMEOUT, TIMEOUT_UNIT);
}
diff --git a/tests/hostside/native/vsock/Android.bp b/tests/hostside/native/vsock/Android.bp
index 13b46d5..966bc04 100644
--- a/tests/hostside/native/vsock/Android.bp
+++ b/tests/hostside/native/vsock/Android.bp
@@ -19,11 +19,13 @@
cc_test {
name: "virt_hostside_tests_vsock_server",
srcs: ["server.cc"],
- static_libs: [
+ shared_libs: [
+ "android.system.virtmanager-cpp",
"libbase",
+ "libbinder",
"liblog",
+ "libutils",
],
- static_executable: true,
test_suites: ["device-tests"],
}
diff --git a/tests/hostside/native/vsock/server.cc b/tests/hostside/native/vsock/server.cc
index d4a99d2..1a1aa37 100644
--- a/tests/hostside/native/vsock/server.cc
+++ b/tests/hostside/native/vsock/server.cc
@@ -26,15 +26,21 @@
#include "android-base/logging.h"
#include "android-base/parseint.h"
#include "android-base/unique_fd.h"
+#include "android/system/virtmanager/IVirtManager.h"
+#include "android/system/virtmanager/IVirtualMachine.h"
+#include "binder/IServiceManager.h"
+using namespace android;
using namespace android::base;
+using namespace android::system::virtmanager;
int main(int argc, const char *argv[]) {
unsigned int port;
- if (argc != 2 || !ParseUint(argv[1], &port)) {
- LOG(ERROR) << "Usage: " << argv[0] << " <port>";
+ if (argc != 3 || !ParseUint(argv[1], &port)) {
+ LOG(ERROR) << "Usage: " << argv[0] << " <port> <vm_config.json>";
return EXIT_FAILURE;
}
+ String16 vm_config(argv[2]);
unique_fd server_fd(TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM, 0)));
if (server_fd < 0) {
@@ -61,6 +67,27 @@
return EXIT_FAILURE;
}
+ LOG(INFO) << "Getting Virt Manager";
+ sp<IVirtManager> virt_manager;
+ status_t err = getService<IVirtManager>(String16("android.system.virtmanager"), &virt_manager);
+ if (err != 0) {
+ LOG(ERROR) << "Error getting Virt Manager from Service Manager: " << err;
+ return EXIT_FAILURE;
+ }
+ sp<IVirtualMachine> vm;
+ binder::Status status = virt_manager->startVm(vm_config, &vm);
+ if (!status.isOk()) {
+ LOG(ERROR) << "Error starting VM: " << status;
+ return EXIT_FAILURE;
+ }
+ int32_t cid;
+ status = vm->getCid(&cid);
+ if (!status.isOk()) {
+ LOG(ERROR) << "Error getting CID: " << status;
+ return EXIT_FAILURE;
+ }
+ LOG(INFO) << "VM starting with CID " << cid;
+
LOG(INFO) << "Accepting connection...";
struct sockaddr_vm client_sa;
socklen_t client_sa_len = sizeof(client_sa);
diff --git a/tests/hostside/vm_config.arm64.json b/tests/hostside/vm_config.arm64.json
new file mode 100644
index 0000000..92f2fb8
--- /dev/null
+++ b/tests/hostside/vm_config.arm64.json
@@ -0,0 +1,5 @@
+{
+ "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.x86_64.json b/tests/hostside/vm_config.x86_64.json
new file mode 100644
index 0000000..9ea95ab
--- /dev/null
+++ b/tests/hostside/vm_config.x86_64.json
@@ -0,0 +1,5 @@
+{
+ "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 7b0423b..88d6ed7 100644
--- a/virtmanager/src/main.rs
+++ b/virtmanager/src/main.rs
@@ -34,6 +34,7 @@
const FIRST_GUEST_CID: Cid = 10;
const BINDER_SERVICE_IDENTIFIER: &str = "android.system.virtmanager";
+const CROSVM_PATH: &str = "/apex/com.android.virt/bin/crosvm";
/// The unique ID of a VM used (together with a port number) for vsock communication.
type Cid = u32;
@@ -169,7 +170,7 @@
/// Start an instance of `crosvm` to manage a new VM.
fn run_vm(config: &VmConfig, cid: Cid) -> Result<Child, io::Error> {
- let mut command = Command::new("crosvm");
+ let mut command = Command::new(CROSVM_PATH);
// TODO(qwandor): Remove --disable-sandbox.
command.arg("run").arg("--disable-sandbox").arg("--cid").arg(cid.to_string());
if let Some(initrd) = &config.initrd {