Merge "Enable deleting instances by specifying --adb-port."
diff --git a/create/avd_spec.py b/create/avd_spec.py
index 039b167..e800b87 100644
--- a/create/avd_spec.py
+++ b/create/avd_spec.py
@@ -107,6 +107,9 @@
# Reporting args.
self._serial_log_file = None
self._logcat_file = None
+ # gpu and emulator_build_id is only used for goldfish avd_type.
+ self._gpu = None
+ self._emulator_build_id = None
self._ProcessArgs(args)
@@ -248,6 +251,8 @@
self._kernel_build_id = args.kernel_build_id
self._serial_log_file = args.serial_log_file
self._logcat_file = args.logcat_file
+ self._emulator_build_id = args.emulator_build_id
+ self._gpu = args.gpu
@staticmethod
def _GetFlavorFromLocalImage(image_path):
@@ -516,3 +521,13 @@
def logcat_file(self):
"""Return logcat file path."""
return self._logcat_file
+
+ @property
+ def gpu(self):
+ """Return gpu."""
+ return self._gpu
+
+ @property
+ def emulator_build_id(self):
+ """Return emulator_build_id."""
+ return self._emulator_build_id
diff --git a/create/create.py b/create/create.py
index 011eb8b..0769593 100644
--- a/create/create.py
+++ b/create/create.py
@@ -32,6 +32,7 @@
from acloud.create import cheeps_remote_image_remote_instance
from acloud.create import gce_local_image_remote_instance
from acloud.create import gce_remote_image_remote_instance
+from acloud.create import goldfish_remote_image_remote_instance
from acloud.create import local_image_local_instance
from acloud.create import local_image_remote_instance
from acloud.create import remote_image_remote_instance
@@ -63,6 +64,9 @@
# Cheeps types
(constants.TYPE_CHEEPS, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_REMOTE):
cheeps_remote_image_remote_instance.CheepsRemoteImageRemoteInstance,
+ # GF types
+ (constants.TYPE_GF, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_REMOTE):
+ goldfish_remote_image_remote_instance.GoldfishRemoteImageRemoteInstance,
}
diff --git a/create/create_args.py b/create/create_args.py
index 638e2ea..730682d 100644
--- a/create/create_args.py
+++ b/create/create_args.py
@@ -208,6 +208,24 @@
choices=constants.SPEC_NAMES,
help="The name of a pre-configured device spec that we are "
"going to use.")
+ # Arguments for goldfish type.
+ # TODO(b/118439885): Verify args that are used in wrong avd_type.
+ # e.g. $acloud create --avd-type cuttlefish --emulator-build-id
+ create_parser.add_argument(
+ "--gpu",
+ type=str,
+ dest="gpu",
+ required=False,
+ default=None,
+ help="'goldfish only' GPU accelerator to use if any. "
+ "e.g. nvidia-tesla-k80, omit to use swiftshader")
+ create_parser.add_argument(
+ "--emulator-build-id",
+ type=int,
+ dest="emulator_build_id",
+ required=False,
+ help="'goldfish only' Emulator build used to run the images. "
+ "e.g. 4669466.")
AddCommonCreateArgs(create_parser)
return create_parser
diff --git a/create/goldfish_remote_image_remote_instance.py b/create/goldfish_remote_image_remote_instance.py
new file mode 100644
index 0000000..592ffaf
--- /dev/null
+++ b/create/goldfish_remote_image_remote_instance.py
@@ -0,0 +1,45 @@
+# Copyright 2019 - 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.
+r"""GoldfishRemoteImageRemoteInstance class.
+
+Create class that is responsible for creating a goldfish remote instance AVD
+with a remote image.
+"""
+
+from acloud.create import base_avd_create
+from acloud.internal.lib import utils
+from acloud.public.actions import create_goldfish_action
+
+
+class GoldfishRemoteImageRemoteInstance(base_avd_create.BaseAVDCreate):
+ """Create class for a remote image remote instance AVD."""
+
+ @utils.TimeExecute(function_description="Total time: ",
+ print_before_call=False, print_status=False)
+ def _CreateAVD(self, avd_spec, no_prompts):
+ """Create the AVD.
+
+ Args:
+ avd_spec: AVDSpec object that tells us what we're going to create.
+ no_prompts: Boolean, True to skip all prompts.
+
+ Returns:
+ A Report instance.
+ """
+ report = create_goldfish_action.CreateDevices(avd_spec=avd_spec)
+
+ # Launch vnc client if we're auto-connecting.
+ if avd_spec.autoconnect:
+ utils.LaunchVNCFromReport(report, avd_spec, no_prompts)
+ return report
diff --git a/internal/lib/goldfish_compute_client.py b/internal/lib/goldfish_compute_client.py
index 4377d6d..be2209c 100644
--- a/internal/lib/goldfish_compute_client.py
+++ b/internal/lib/goldfish_compute_client.py
@@ -43,6 +43,7 @@
import logging
from acloud import errors
+from acloud.internal import constants
from acloud.internal.lib import android_compute_client
from acloud.internal.lib import gcompute_client
@@ -132,7 +133,8 @@
emulator_branch=None,
emulator_build_id=None,
blank_data_disk_size_gb=None,
- gpu=None):
+ gpu=None,
+ avd_spec=None):
"""Create a goldfish instance given a stable host image and a build id.
Args:
@@ -148,6 +150,7 @@
blank_data_disk_size_gb: Integer, size of the blank data disk in GB.
gpu: String, GPU that should be attached to the instance, or None of no
acceleration is needed. e.g. "nvidia-tesla-k80"
+ avd_spec: An AVDSpec instance.
"""
self._CheckMachineSize()
@@ -161,10 +164,10 @@
# Goldfish instances are metadata compatible with cuttlefish devices.
# See details goto/goldfish-deployment
metadata = self._metadata.copy()
- resolution = self._resolution.split("x")
+ metadata["user"] = getpass.getuser()
+ metadata[constants.INS_KEY_AVD_TYPE] = constants.TYPE_GF
# 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)
@@ -173,8 +176,28 @@
"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]
+
+ # Update metadata by avd_spec
+ # for legacy create_gf cmd, we will keep using resolution.
+ # And always use avd_spec for acloud create cmd.
+ if avd_spec:
+ metadata[constants.INS_KEY_AVD_FLAVOR] = avd_spec.flavor
+ metadata["cvd_01_x_res"] = avd_spec.hw_property[constants.HW_X_RES]
+ metadata["cvd_01_y_res"] = avd_spec.hw_property[constants.HW_Y_RES]
+ metadata["cvd_01_dpi"] = avd_spec.hw_property[constants.HW_ALIAS_DPI]
+ metadata[constants.INS_KEY_DISPLAY] = ("%sx%s (%s)" % (
+ avd_spec.hw_property[constants.HW_X_RES],
+ avd_spec.hw_property[constants.HW_Y_RES],
+ avd_spec.hw_property[constants.HW_ALIAS_DPI]))
+ else:
+ resolution = self._resolution.split("x")
+ metadata["cvd_01_x_res"] = resolution[0]
+ metadata["cvd_01_y_res"] = resolution[1]
+ metadata["cvd_01_dpi"] = resolution[3]
+
+ # Add labels for giving the instances ability to be filter for
+ # acloud list/delete cmds.
+ labels = {constants.LABEL_CREATE_BY: getpass.getuser()}
# Add per-instance ssh key
if self._ssh_public_key_path:
@@ -197,4 +220,5 @@
machine_type=self._machine_type,
network=self._network,
zone=self._zone,
- gpu=gpu)
+ gpu=gpu,
+ labels=labels)
diff --git a/internal/lib/goldfish_compute_client_test.py b/internal/lib/goldfish_compute_client_test.py
index 461fa48..33f16e7 100644
--- a/internal/lib/goldfish_compute_client_test.py
+++ b/internal/lib/goldfish_compute_client_test.py
@@ -86,29 +86,28 @@
"fake_arg": "fake_value"
}])
- def testCreateInstance(self):
+ @mock.patch("getpass.getuser", return_value="fake_user")
+ def testCreateInstance(self, _mock_user):
"""Test CreateInstance."""
expected_metadata = {
- "cvd_01_dpi":
- str(self.DPI),
- "cvd_01_fetch_android_build_target":
- self.TARGET,
+ "user": "fake_user",
+ "avd_type": "goldfish",
+ "cvd_01_fetch_android_build_target": self.TARGET,
"cvd_01_fetch_android_bid":
"{branch}/{build_id}".format(
branch=self.BRANCH, build_id=self.BUILD_ID),
"cvd_01_fetch_emulator_bid":
"{branch}/{build_id}".format(
branch=self.EMULATOR_BRANCH, build_id=self.EMULATOR_BUILD_ID),
- "cvd_01_launch":
- "1",
- "cvd_01_x_res":
- str(self.X_RES),
- "cvd_01_y_res":
- str(self.Y_RES),
+ "cvd_01_launch": "1",
+ "cvd_01_dpi": str(self.DPI),
+ "cvd_01_x_res": str(self.X_RES),
+ "cvd_01_y_res": str(self.Y_RES),
}
expected_metadata.update(self.METADATA)
expected_disk_args = [{"fake_arg": "fake_value"}]
+ expected_labels = {'created_by': "fake_user"}
self.goldfish_compute_client.CreateInstance(
self.INSTANCE, self.IMAGE, self.IMAGE_PROJECT, self.TARGET,
@@ -126,7 +125,8 @@
machine_type=self.MACHINE_TYPE,
network=self.NETWORK,
zone=self.ZONE,
- gpu=self.GPU)
+ gpu=self.GPU,
+ labels=expected_labels)
if __name__ == "__main__":
diff --git a/public/actions/create_goldfish_action.py b/public/actions/create_goldfish_action.py
index 42e3f0f..8046227 100644
--- a/public/actions/create_goldfish_action.py
+++ b/public/actions/create_goldfish_action.py
@@ -22,8 +22,8 @@
import os
from acloud import errors
-from acloud.public.actions import common_operations
from acloud.public.actions import base_device_factory
+from acloud.public.actions import common_operations
from acloud.internal import constants
from acloud.internal.lib import android_build_client
from acloud.internal.lib import auth
@@ -64,7 +64,8 @@
build_id,
emulator_build_target,
emulator_build_id,
- gpu=None):
+ gpu=None,
+ avd_spec=None):
"""Initialize.
@@ -75,6 +76,7 @@
emulator_build_target: String, the emulator build target, e.g. aosp_x86-eng.
emulator_build_id: String, emulator build id.
gpu: String, GPU to attach to the device or None. e.g. "nvidia-tesla-k80"
+ avd_spec: An AVDSpec instance.
"""
self.credentials = auth.CreateCredentials(cfg)
@@ -90,6 +92,7 @@
self._emulator_build_id = emulator_build_id
self._emulator_build_target = emulator_build_target
self._gpu = gpu
+ self._avd_spec = avd_spec
self._blank_data_disk_size_gb = cfg.extra_data_disk_size_gb
# Configure clients
@@ -109,7 +112,8 @@
Returns:
String, the name of the created instance.
"""
- instance = self._compute_client.GenerateInstanceName(self._build_id)
+ instance = self._compute_client.GenerateInstanceName(
+ build_id=self._build_id, build_target=self._build_target)
self._compute_client.CreateInstance(
instance=instance,
@@ -121,7 +125,8 @@
emulator_branch=self._emulator_branch,
emulator_build_id=self._emulator_build_id,
gpu=self._gpu,
- blank_data_disk_size_gb=self._blank_data_disk_size_gb)
+ blank_data_disk_size_gb=self._blank_data_disk_size_gb,
+ avd_spec=self._avd_spec)
return instance
@@ -180,7 +185,8 @@
return ParseBuildInfo(temp_filename, pattern)
-def CreateDevices(cfg,
+def CreateDevices(avd_spec=None,
+ cfg=None,
build_target=None,
build_id=None,
emulator_build_id=None,
@@ -194,6 +200,7 @@
"""Create one or multiple Goldfish devices.
Args:
+ avd_spec: An AVDSpec instance.
cfg: An AcloudConfig instance.
build_target: String, the build target, e.g. aosp_x86-eng.
build_id: String, Build id, e.g. "2263051", "P2804227"
@@ -211,6 +218,19 @@
Returns:
A Report instance.
"""
+ if avd_spec:
+ cfg = avd_spec.cfg
+ build_target = avd_spec.remote_image[constants.BUILD_TARGET]
+ build_id = avd_spec.remote_image[constants.BUILD_ID]
+ branch = avd_spec.remote_image[constants.BUILD_BRANCH]
+ num = avd_spec.num
+ emulator_build_id = avd_spec.emulator_build_id
+ gpu = avd_spec.gpu
+ serial_log_file = avd_spec.serial_log_file
+ logcat_file = avd_spec.logcat_file
+ autoconnect = avd_spec.autoconnect
+ report_internal_ip = avd_spec.report_internal_ip
+
if emulator_build_id is None:
emulator_build_id = _FetchBuildIdFromFile(cfg,
build_target,
@@ -242,7 +262,7 @@
device_factory = GoldfishDeviceFactory(cfg, build_target, build_id,
cfg.emulator_build_target,
- emulator_build_id, gpu)
+ emulator_build_id, gpu, avd_spec)
return common_operations.CreateDevices(
command="create_gf",
@@ -250,6 +270,7 @@
device_factory=device_factory,
num=num,
report_internal_ip=report_internal_ip,
+ autoconnect=autoconnect,
vnc_port=constants.DEFAULT_GOLDFISH_VNC_PORT,
adb_port=constants.DEFAULT_GOLDFISH_ADB_PORT,
serial_log_file=serial_log_file,
diff --git a/public/actions/create_goldfish_action_test.py b/public/actions/create_goldfish_action_test.py
index 3d841b1..dc45741 100644
--- a/public/actions/create_goldfish_action_test.py
+++ b/public/actions/create_goldfish_action_test.py
@@ -15,9 +15,10 @@
# limitations under the License.
"""Tests for acloud.public.actions.create_goldfish_actions."""
import uuid
-
import unittest
import mock
+
+from acloud.internal import constants
from acloud.internal.lib import android_build_client
from acloud.internal.lib import android_compute_client
from acloud.internal.lib import auth
@@ -62,6 +63,16 @@
"AndroidComputeClient",
return_value=self.compute_client)
self.Patch(auth, "CreateCredentials", return_value=mock.MagicMock())
+ #Initialize new avd_spec
+ self.avd_spec = mock.MagicMock()
+ self.avd_spec.cfg = self._CreateCfg()
+ self.avd_spec.remote_image = {constants.BUILD_ID: self.BUILD_ID,
+ constants.BUILD_BRANCH: self.BRANCH,
+ constants.BUILD_TARGET: self.BUILD_TARGET}
+ self.avd_spec.emulator_build_id = self.EMULATOR_BUILD_ID
+ self.avd_spec.gpu = self.GPU
+ self.avd_spec.serial_log_file = None
+ self.avd_spec.autoconnect = False
def _CreateCfg(self):
"""A helper method that creates a mock configuration object."""
@@ -95,10 +106,12 @@
self.BRANCH, self.EMULATOR_BRANCH
]
- # Call CreateDevices
+ none_avd_spec = None
+
+ # Call CreateDevices with avd_spec is None
report = create_goldfish_action.CreateDevices(
- cfg, self.BUILD_TARGET, self.BUILD_ID, self.EMULATOR_BUILD_ID,
- self.GPU)
+ none_avd_spec, cfg, self.BUILD_TARGET, self.BUILD_ID,
+ self.EMULATOR_BUILD_ID, self.GPU)
# Verify
self.compute_client.CreateInstance.assert_called_with(
@@ -111,7 +124,8 @@
build_id=self.BUILD_ID,
emulator_branch=self.EMULATOR_BRANCH,
emulator_build_id=self.EMULATOR_BUILD_ID,
- gpu=self.GPU)
+ gpu=self.GPU,
+ avd_spec=none_avd_spec)
self.assertEquals(report.data, {
"devices": [
@@ -124,6 +138,25 @@
self.assertEquals(report.command, "create_gf")
self.assertEquals(report.status, "SUCCESS")
+ # Call CreateDevices with avd_spec
+ self.build_client.GetBranch.side_effect = [
+ self.BRANCH, self.EMULATOR_BRANCH
+ ]
+ report = create_goldfish_action.CreateDevices(avd_spec=self.avd_spec)
+ # Verify
+ self.compute_client.CreateInstance.assert_called_with(
+ instance=self.INSTANCE,
+ blank_data_disk_size_gb=self.EXTRA_DATA_DISK_GB,
+ image_name=self.GOLDFISH_HOST_IMAGE_NAME,
+ image_project=self.GOLDFISH_HOST_IMAGE_PROJECT,
+ build_target=self.BUILD_TARGET,
+ branch=self.BRANCH,
+ build_id=self.BUILD_ID,
+ emulator_branch=self.EMULATOR_BRANCH,
+ emulator_build_id=self.EMULATOR_BUILD_ID,
+ gpu=self.GPU,
+ avd_spec=self.avd_spec)
+
def testCreateDevicesWithoutBuildId(self):
"""Test CreateDevices when emulator sys image build id is not provided."""
cfg = self._CreateCfg()
@@ -148,8 +181,10 @@
"_FetchBuildIdFromFile",
return_value=self.BUILD_ID)
- # Call CreateDevices
+ none_avd_spec = None
+ # Call CreateDevices with no avd_spec
report = create_goldfish_action.CreateDevices(
+ none_avd_spec,
cfg,
self.BUILD_TARGET,
None,
@@ -168,7 +203,8 @@
build_id=self.BUILD_ID,
emulator_branch=self.EMULATOR_BRANCH,
emulator_build_id=self.EMULATOR_BUILD_ID,
- gpu=self.GPU)
+ gpu=self.GPU,
+ avd_spec=none_avd_spec)
self.assertEquals(report.data, {
"devices": [{
@@ -179,6 +215,25 @@
self.assertEquals(report.command, "create_gf")
self.assertEquals(report.status, "SUCCESS")
+ # Call CreateDevices with avd_spec
+ self.build_client.GetBranch.side_effect = [
+ self.BRANCH, self.EMULATOR_BRANCH
+ ]
+ report = create_goldfish_action.CreateDevices(avd_spec=self.avd_spec)
+ # Verify
+ self.compute_client.CreateInstance.assert_called_with(
+ instance=self.INSTANCE,
+ blank_data_disk_size_gb=self.EXTRA_DATA_DISK_GB,
+ image_name=self.GOLDFISH_HOST_IMAGE_NAME,
+ image_project=self.GOLDFISH_HOST_IMAGE_PROJECT,
+ build_target=self.BUILD_TARGET,
+ branch=self.BRANCH,
+ build_id=self.BUILD_ID,
+ emulator_branch=self.EMULATOR_BRANCH,
+ emulator_build_id=self.EMULATOR_BUILD_ID,
+ gpu=self.GPU,
+ avd_spec=self.avd_spec)
+
#pylint: disable=invalid-name
def testCreateDevicesWithoutEmulatorBuildId(self):
"""Test CreateDevices when emulator build id is not provided."""
@@ -204,9 +259,11 @@
"_FetchBuildIdFromFile",
return_value=self.EMULATOR_BUILD_ID)
+ none_avd_spec = None
# Call CreateDevices
report = create_goldfish_action.CreateDevices(
- cfg, self.BUILD_TARGET, self.BUILD_ID, None, self.GPU)
+ none_avd_spec, cfg, self.BUILD_TARGET, self.BUILD_ID, None,
+ self.GPU)
# Verify
self.compute_client.CreateInstance.assert_called_with(
@@ -219,7 +276,8 @@
build_id=self.BUILD_ID,
emulator_branch=self.EMULATOR_BRANCH,
emulator_build_id=self.EMULATOR_BUILD_ID,
- gpu=self.GPU)
+ gpu=self.GPU,
+ avd_spec=none_avd_spec)
self.assertEquals(report.data, {
"devices": [{
@@ -230,6 +288,25 @@
self.assertEquals(report.command, "create_gf")
self.assertEquals(report.status, "SUCCESS")
+ # Call CreateDevices with avd_spec
+ self.build_client.GetBranch.side_effect = [
+ self.BRANCH, self.EMULATOR_BRANCH
+ ]
+ report = create_goldfish_action.CreateDevices(avd_spec=self.avd_spec)
+ # Verify
+ self.compute_client.CreateInstance.assert_called_with(
+ instance=self.INSTANCE,
+ blank_data_disk_size_gb=self.EXTRA_DATA_DISK_GB,
+ image_name=self.GOLDFISH_HOST_IMAGE_NAME,
+ image_project=self.GOLDFISH_HOST_IMAGE_PROJECT,
+ build_target=self.BUILD_TARGET,
+ branch=self.BRANCH,
+ build_id=self.BUILD_ID,
+ emulator_branch=self.EMULATOR_BRANCH,
+ emulator_build_id=self.EMULATOR_BUILD_ID,
+ gpu=self.GPU,
+ avd_spec=self.avd_spec)
+
if __name__ == "__main__":
unittest.main()
diff --git a/public/data/default.config b/public/data/default.config
index 702f2fa..53d114f 100644
--- a/public/data/default.config
+++ b/public/data/default.config
@@ -8,6 +8,11 @@
creds_cache_file: ".acloud_oauth2.dat"
user_agent: "acloud"
+# [GOLDFISH only] The emulator build target: "sdk_tools_linux".
+# We use it to get build id if build id is not provided and It's very unlikely
+# that this will ever change.
+emulator_build_target: "sdk_tools_linux"
+
default_usr_cfg {
machine_type: "n1-standard-4"
network: "default"