Secondary migration from google3 into AOSP.
The 2nd revival of AOSP acloud is upon us!
The cl revision the acloud g3 code was pulled from is 195930083.
Things I did:
- Added AOSP copyright for new files and updated g3 imports to be relative.
- Merged in changes into existing files (easier to see changes here and
for future cls).
- Scrubbed default.config of project and build info.
- Merge acloud.py (from g3) into acloud_main.py (entry point for AOSP
acloud).
- Regenerated internal_config_pb2.py and user_config_pb2.py.
- Removed add_mock from gcomputer_client_test and added TODO in file
where to replace it and updated parameterized to import from
absl.testing.
- Updated references to gce_x86 to aosp_cf_x86_phone and updated branch
references to 'aosp-master'.
Thing to note:
- New files fail pylint (in order to make it easy to check history on new files,
formatting will be done using yapf in another cl).
- pip install acloud.zip seg faults so investigation and fix for that
will happen in another cl.
- User needs to 'pip install absl-py' for parameterized lib in unittests.
Bug: 79684654
Test: ./run_tests.sh
Change-Id: I060641227d7c9162a45557e732686f22b83895e9
diff --git a/internal/lib/goldfish_compute_client.py b/internal/lib/goldfish_compute_client.py
new file mode 100644
index 0000000..01278fc
--- /dev/null
+++ b/internal/lib/goldfish_compute_client.py
@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+#
+# Copyright 2018 - 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.
+
+"""A client that manages Goldfish Virtual Device on compute engine.
+
+** GoldfishComputeClient **
+
+GoldfishComputeClient derives from AndroidComputeClient. It manges a google
+compute engine project that is setup for running Goldfish Virtual Devices.
+It knows how to create a host instance from a Goldfish Stable Host Image, fetch
+Android build, an emulator build, and start Android within the host instance.
+
+** Class hierarchy **
+
+ base_cloud_client.BaseCloudApiClient
+ ^
+ |
+ gcompute_client.ComputeClient
+ ^
+ |
+ android_compute_client.AndroidComputeClient
+ ^
+ |
+ goldfish_compute_client.GoldfishComputeClient
+
+
+TODO(jansen): This class should likely be merged with CvdComputeClient
+"""
+
+import getpass
+import logging
+import os
+
+from acloud.internal.lib import android_compute_client
+from acloud.internal.lib import gcompute_client
+from acloud.public import errors
+
+logger = logging.getLogger(__name__)
+
+
+class GoldfishComputeClient(android_compute_client.AndroidComputeClient):
+ """Client that manages Goldfish based Android Virtual Device."""
+
+ # To determine if the boot failed
+ BOOT_FAILED_MSG = "VIRTUAL_DEVICE_FAILED"
+
+ # To determine the failure reason
+ # If the emulator build is not available
+ EMULATOR_FETCH_FAILED_MSG = "EMULATOR_FETCH_FAILED"
+ # If the system image build is not available
+ ANDROID_FETCH_FAILED_MSG = "ANDROID_FETCH_FAILED"
+ # If the emulator could not boot in time
+ BOOT_TIMEOUT_MSG = "VIRTUAL_DEVICE_BOOT_FAILED"
+
+ def __init__(self, acloud_config, oauth2_credentials):
+ """Initialize.
+
+ Args:
+ acloud_config: An AcloudConfig object.
+ oauth2_credentials: An oauth2client.OAuth2Credentials instance.
+ """
+ super(GoldfishComputeClient, self).__init__(acloud_config,
+ oauth2_credentials)
+
+ def _GetDiskArgs(self, disk_name, image_name, image_project, disk_size_gb):
+ """Helper to generate disk args that is used to create an instance.
+
+ Args:
+ disk_name: A string
+ image_name: A string
+ image_project: A string
+ disk_size_gb: An integer
+
+ Returns:
+ A dictionary representing disk args.
+ """
+ return [{
+ "type": "PERSISTENT",
+ "boot": True,
+ "mode": "READ_WRITE",
+ "autoDelete": True,
+ "initializeParams": {
+ "diskName":
+ disk_name,
+ "sourceImage":
+ self.GetImage(image_name, image_project)["selfLink"],
+ "diskSizeGb":
+ disk_size_gb
+ },
+ }]
+
+ def CheckBootFailure(self, serial_out, instance):
+ """Overriding method from the parent class.
+
+ Args:
+ serial_out: A string
+ instance: A string
+
+ Raises:
+ Raises an errors.DeviceBootError exception if a failure is detected.
+ """
+ if self.BOOT_FAILED_MSG in serial_out:
+ if self.EMULATOR_FETCH_FAILED_MSG in serial_out:
+ raise errors.DeviceBootError(
+ "Failed to download emulator build. Re-run with a newer build.")
+ if self.ANDROID_FETCH_FAILED_MSG in serial_out:
+ raise errors.DeviceBootError(
+ "Failed to download system image build. Re-run with a newer build.")
+ if self.BOOT_TIMEOUT_MSG in serial_out:
+ raise errors.DeviceBootError(
+ "Emulator timed out while booting.")
+
+ def CreateInstance(self,
+ instance,
+ image_name,
+ image_project,
+ build_target,
+ branch,
+ build_id,
+ emulator_branch=None,
+ emulator_build_id=None,
+ blank_data_disk_size_gb=None,
+ gpu=None):
+ """Create a goldfish instance given a stable host image and a build id.
+
+ Args:
+ instance: instance name.
+ image_name: A string, the name of the system image.
+ image_project: A string, name of the project where the image belongs.
+ Assume the default project if None.
+ build_target: Target name, e.g. "sdk_phone_x86_64-sdk"
+ branch: Branch name, e.g. "git_pi-dev"
+ build_id: Build id, a string, e.g. "2263051", "P2804227"
+ emulator_branch: emulator branch name, e.g.
+ "aosp-emu-master-dev"
+ emulator_build_id: emulator build id, a string, e.g. "2263051", "P2804227"
+ blank_data_disk_size_gb: Size of the blank data disk in GB.
+ gpu: GPU that should be attached to the instance, or None of no
+ acceleration is needed. e.g. "nvidia-tesla-k80"
+ """
+ self._CheckMachineSize()
+
+ # Add space for possible data partition.
+ boot_disk_size_gb = (
+ int(self.GetImage(image_name, image_project)["diskSizeGb"]) +
+ blank_data_disk_size_gb)
+ disk_args = self._GetDiskArgs(instance, image_name, image_project,
+ boot_disk_size_gb)
+
+ # Goldfish instances are metadata compatible with cuttlefish devices.
+ # See details goto/goldfish-deployment
+ metadata = self._metadata.copy()
+ resolution = self._resolution.split("x")
+
+ # Note that we use the same metadata naming conventions as cuttlefish
+ metadata["cvd_01_dpi"] = resolution[3]
+ metadata["cvd_01_fetch_android_build_target"] = build_target
+ metadata["cvd_01_fetch_android_bid"] = "{branch}/{build_id}".format(
+ branch=branch, build_id=build_id)
+ if emulator_branch and emulator_build_id:
+ metadata["cvd_01_fetch_emulator_bid"] = "{branch}/{build_id}".format(
+ branch=emulator_branch, build_id=emulator_build_id)
+ metadata["cvd_01_launch"] = "1"
+ metadata["cvd_01_x_res"] = resolution[0]
+ metadata["cvd_01_y_res"] = resolution[1]
+
+ # Add per-instance ssh key
+ if self._ssh_public_key_path:
+ rsa = self._LoadSshPublicKey(self._ssh_public_key_path)
+ logger.info("ssh_public_key_path is specified in config: %s, "
+ "will add the key to the instance.",
+ self._ssh_public_key_path)
+ metadata["sshKeys"] = "%s:%s" % (getpass.getuser(), rsa)
+ else:
+ logger.warning("ssh_public_key_path is not specified in config, "
+ "only project-wide key will be effective.")
+
+ gcompute_client.ComputeClient.CreateInstance(
+ self,
+ instance=instance,
+ image_name=image_name,
+ image_project=image_project,
+ disk_args=disk_args,
+ metadata=metadata,
+ machine_type=self._machine_type,
+ network=self._network,
+ zone=self._zone,
+ gpu=gpu)