Snap for 6001391 from 10b111c8044faf0acf0be504fc630c921c758134 to qt-aml-networking-release
Change-Id: Ie397377e6ec9cb635f955a9048184e53556af97e
diff --git a/README.md b/README.md
index 9bd3fed..e9e9c06 100755
--- a/README.md
+++ b/README.md
@@ -105,6 +105,10 @@
disk in a key:value format like so:
`cpu:2,resolution:1280x700,dpi:160,memory:2g,disk:2g`
+* `--reuse-gce`: 'cuttlefish only' This can help users use their own instance.
+Reusing specific gce instance if `--reuse-gce` [instance-name] is provided.
+Select one gce instance to reuse if `--reuse-gce` is provided.
+
The full list of options are available via `--help`
> $ acloud create --help
diff --git a/create/local_image_local_instance.py b/create/local_image_local_instance.py
index 2b9f96e..25871ed 100644
--- a/create/local_image_local_instance.py
+++ b/create/local_image_local_instance.py
@@ -38,11 +38,9 @@
import json
import logging
import os
-import re
import shutil
import subprocess
import sys
-import tempfile
from acloud import errors
from acloud.create import base_avd_create
@@ -50,13 +48,13 @@
from acloud.internal import constants
from acloud.internal.lib import utils
from acloud.internal.lib.adb_tools import AdbTools
+from acloud.list import list as list_instance
from acloud.list import instance
from acloud.public import report
logger = logging.getLogger(__name__)
-_ACLOUD_CVD_TEMP = os.path.join(tempfile.gettempdir(), "acloud_cvd_temp")
_CMD_LAUNCH_CVD_ARGS = (" -daemon -cpus %s -x_res %s -y_res %s -dpi %s "
"-memory_mb %s -system_image_dir %s "
"-instance_dir %s")
@@ -65,16 +63,12 @@
_CONFIRM_RELAUNCH = ("\nCuttlefish AVD[id:%d] is already running. \n"
"Enter 'y' to terminate current instance and launch a new "
"instance, enter anything else to exit out[y/N]: ")
-_CVD_RUNTIME_FOLDER_NAME = "cuttlefish_runtime"
-_CVD_CONFIG_NAME = "cuttlefish_config.json"
_ENV_ANDROID_HOST_OUT = "ANDROID_HOST_OUT"
_ENV_CVD_HOME = "HOME"
_ENV_CUTTLEFISH_INSTANCE = "CUTTLEFISH_INSTANCE"
_LAUNCH_CVD_TIMEOUT_SECS = 60 # default timeout as 60 seconds
_LAUNCH_CVD_TIMEOUT_ERROR = ("Cuttlefish AVD launch timeout, did not complete "
"within %d secs.")
-_LOCAL_INSTANCE_HOME = "instance_home_%s"
-_RE_LOCAL_CVD_PORT = re.compile(r"^127\.0\.0\.1:65(?P<cvd_port_suffix>\d{2})\s+")
_VIRTUAL_DISK_PATHS = "virtual_disk_paths"
@@ -157,7 +151,8 @@
return avd_spec.local_image_dir, host_bins_path
- def PrepareLaunchCVDCmd(self, launch_cvd_path, hw_property, system_image_dir,
+ @staticmethod
+ def PrepareLaunchCVDCmd(launch_cvd_path, hw_property, system_image_dir,
local_instance_id):
"""Prepare launch_cvd command.
@@ -173,7 +168,7 @@
Returns:
String, launch_cvd cmd.
"""
- instance_dir = self.GetLocalInstanceRuntimeDir(local_instance_id)
+ instance_dir = instance.GetLocalInstanceRuntimeDir(local_instance_id)
launch_cvd_w_args = launch_cvd_path + _CMD_LAUNCH_CVD_ARGS % (
hw_property["cpu"], hw_property["x_res"], hw_property["y_res"],
hw_property["dpi"], hw_property["memory"], system_image_dir,
@@ -231,7 +226,8 @@
_LAUNCH_CVD_TIMEOUT_ERROR % timeout_secs)
timeout_exception(self._LaunchCvd)(cmd, local_instance_id)
- def _StopCvd(self, host_bins_path, local_instance_id):
+ @staticmethod
+ def _StopCvd(host_bins_path, local_instance_id):
"""Execute stop_cvd to stop cuttlefish instance.
Args:
@@ -244,7 +240,7 @@
with open(os.devnull, "w") as dev_null:
cvd_env = os.environ.copy()
cvd_env[constants.ENV_CUTTLEFISH_CONFIG_FILE] = os.path.join(
- self.GetLocalInstanceRuntimeDir(local_instance_id),
+ instance.GetLocalInstanceRuntimeDir(local_instance_id),
constants.CUTTLEFISH_CONFIG_FILE)
subprocess.check_call(
utils.AddUserGroupsToCmd(
@@ -260,8 +256,9 @@
# sure adb device is completely gone since it will use the same adb port
adb_cmd.DisconnectAdb(retry=True)
+ @staticmethod
@utils.TimeExecute(function_description="Waiting for AVD(s) to boot up")
- def _LaunchCvd(self, cmd, local_instance_id):
+ def _LaunchCvd(cmd, local_instance_id):
"""Execute Launch CVD.
Kick off the launch_cvd command and log the output.
@@ -275,8 +272,8 @@
"""
# Delete the cvd home/runtime temp if exist. The runtime folder is
# under the cvd home dir, so we only delete them from home dir.
- cvd_home_dir = self.GetLocalInstanceHomeDir(local_instance_id)
- cvd_runtime_dir = self.GetLocalInstanceRuntimeDir(local_instance_id)
+ cvd_home_dir = instance.GetLocalInstanceHomeDir(local_instance_id)
+ cvd_runtime_dir = instance.GetLocalInstanceRuntimeDir(local_instance_id)
shutil.rmtree(cvd_home_dir, ignore_errors=True)
os.makedirs(cvd_runtime_dir)
@@ -303,31 +300,6 @@
utils.TextColors.WARNING)
@staticmethod
- def GetLocalInstanceHomeDir(local_instance_id):
- """Get instance home dir
-
- Args:
- local_instance_id: Integer of instance id.
-
- Return:
- String, path of instance home dir.
- """
- return os.path.join(_ACLOUD_CVD_TEMP,
- _LOCAL_INSTANCE_HOME % local_instance_id)
-
- def GetLocalInstanceRuntimeDir(self, local_instance_id):
- """Get instance runtime dir
-
- Args:
- local_instance_id: Integer of instance id.
-
- Return:
- String, path of instance runtime dir.
- """
- return os.path.join(self.GetLocalInstanceHomeDir(local_instance_id),
- _CVD_RUNTIME_FOLDER_NAME)
-
- @staticmethod
def IsLocalCVDRunning(local_instance_id):
"""Check if the AVD with specific instance id is running
@@ -340,7 +312,8 @@
local_ports = instance.GetLocalPortsbyInsId(local_instance_id)
return AdbTools(local_ports.adb_port).IsAdbConnected()
- def IsLocalImageOccupied(self, local_image_dir):
+ @staticmethod
+ def IsLocalImageOccupied(local_image_dir):
"""Check if the given image path is being used by a running CVD process.
Args:
@@ -349,10 +322,10 @@
Return:
Integer of instance id which using the same image path.
"""
- local_cvd_ids = self._GetActiveCVDIds()
+ local_cvd_ids = list_instance.GetActiveCVDIds()
for cvd_id in local_cvd_ids:
- cvd_config_path = os.path.join(self.GetLocalInstanceRuntimeDir(
- cvd_id), _CVD_CONFIG_NAME)
+ cvd_config_path = os.path.join(instance.GetLocalInstanceRuntimeDir(
+ cvd_id), constants.CUTTLEFISH_CONFIG_FILE)
if not os.path.isfile(cvd_config_path):
continue
with open(cvd_config_path, "r") as config_file:
@@ -361,24 +334,3 @@
if local_image_dir in disk_path:
return cvd_id
return None
-
- @staticmethod
- def _GetActiveCVDIds():
- """Get active cvd ids from adb devices.
-
- The adb port of local instance will be decided according to instance id.
- The rule of adb port will be '6520 + [instance id] - 1'. So we grep last
- two digits of port and calculate the instance id.
-
- Return:
- List of cvd id.
- """
- local_cvd_ids = []
- adb_cmd = [constants.ADB_BIN, "devices"]
- device_info = subprocess.check_output(adb_cmd)
- for device in device_info.splitlines():
- match = _RE_LOCAL_CVD_PORT.match(device)
- if match:
- cvd_serial = match.group("cvd_port_suffix")
- local_cvd_ids.append(int(cvd_serial) - 19)
- return local_cvd_ids
diff --git a/create/local_image_local_instance_test.py b/create/local_image_local_instance_test.py
index fdc7618..1007739 100644
--- a/create/local_image_local_instance_test.py
+++ b/create/local_image_local_instance_test.py
@@ -19,6 +19,7 @@
import mock
from acloud.create import local_image_local_instance
+from acloud.list import instance
from acloud.internal import constants
from acloud.internal.lib import utils
@@ -41,8 +42,7 @@
self.local_image_local_instance = local_image_local_instance.LocalImageLocalInstance()
# pylint: disable=protected-access
- @mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
- "GetLocalInstanceRuntimeDir")
+ @mock.patch.object(instance, "GetLocalInstanceRuntimeDir")
@mock.patch.object(utils, "CheckUserInGroups")
def testPrepareLaunchCVDCmd(self, mock_usergroups, mock_cvd_dir):
"""test PrepareLaunchCVDCmd."""
diff --git a/create/local_image_remote_instance.py b/create/local_image_remote_instance.py
index d741a4f..20d03aa 100644
--- a/create/local_image_remote_instance.py
+++ b/create/local_image_remote_instance.py
@@ -54,8 +54,7 @@
Return:
A string, the path to the host package.
"""
- dirs_to_check = filter(None,
- [os.environ.get(constants.ENV_ANDROID_HOST_OUT)])
+ dirs_to_check = list(filter(None, [os.environ.get(constants.ENV_ANDROID_HOST_OUT)]))
dist_dir = utils.GetDistDir()
if dist_dir:
dirs_to_check.append(dist_dir)
diff --git a/delete/delete.py b/delete/delete.py
index 8318c37..64ca254 100644
--- a/delete/delete.py
+++ b/delete/delete.py
@@ -28,7 +28,6 @@
from acloud.internal import constants
from acloud.internal.lib import utils
from acloud.list import list as list_instances
-from acloud.list import instance as instance_class
from acloud.public import config
from acloud.public import device_driver
from acloud.public import report
@@ -49,11 +48,11 @@
Try to get directory of "run_cvd" by "ps -o command -p <pid>." command.
For example: "/tmp/bin/run_cvd"
- Raises:
- errors.NoExecuteCmd: Can't find stop_cvd.
-
Returns:
String of stop_cvd file path.
+
+ Raises:
+ errors.NoExecuteCmd: Can't find stop_cvd.
"""
process_id = subprocess.check_output(_COMMAND_GET_PROCESS_ID)
process_info = subprocess.check_output(
@@ -103,7 +102,7 @@
remote_instance_list = []
for instance in instances_to_delete:
if instance.islocal:
- delete_report = DeleteLocalInstance()
+ delete_report = DeleteLocalInstance(instance, delete_report)
else:
remote_instance_list.append(instance.name)
# Delete ssvnc viewer
@@ -150,32 +149,42 @@
@utils.TimeExecute(function_description="Deleting local instances",
result_evaluator=utils.ReportEvaluator)
-def DeleteLocalInstance():
+def DeleteLocalInstance(instance, delete_report=None):
"""Delete local instance.
Delete local instance with stop_cvd command and write delete instance
information to report.
+ Args:
+ instance: instance.LocalInstance object.
+ delete_report: Report object.
+
Returns:
A Report instance.
"""
- delete_report = report.Report(command="delete")
+ if not delete_report:
+ delete_report = report.Report(command="delete")
+
try:
with open(os.devnull, "w") as dev_null:
+ cvd_env = os.environ.copy()
+ if instance.instance_dir:
+ cvd_env[constants.ENV_CUTTLEFISH_CONFIG_FILE] = os.path.join(
+ instance.instance_dir, constants.CUTTLEFISH_CONFIG_FILE)
subprocess.check_call(
utils.AddUserGroupsToCmd(_GetStopCvd(),
constants.LIST_CF_USER_GROUPS),
- stderr=dev_null, stdout=dev_null, shell=True)
+ stderr=dev_null, stdout=dev_null, shell=True, env=cvd_env)
delete_report.SetStatus(report.Status.SUCCESS)
device_driver.AddDeletionResultToReport(
- delete_report, [constants.LOCAL_INS_NAME], failed=[],
+ delete_report, [instance.name], failed=[],
error_msgs=[],
resource_name="instance")
+ CleanupSSVncviewer(instance.vnc_port)
except subprocess.CalledProcessError as e:
delete_report.AddError(str(e))
delete_report.SetStatus(report.Status.FAIL)
- # Only CF supports local instances so assume it's a CF VNC port.
- CleanupSSVncviewer(constants.CF_VNC_PORT)
+
return delete_report
@@ -192,16 +201,12 @@
A Report instance.
"""
cfg = config.GetAcloudConfig(args)
- remote_instances_to_delete = args.instance_names
+ instances_to_delete = args.instance_names
- if remote_instances_to_delete:
- return DeleteRemoteInstances(cfg, remote_instances_to_delete)
-
- if args.local_instance:
- if instance_class.LocalInstance():
- return DeleteLocalInstance()
- print("There is no local instance AVD to delete.")
- return report.Report(command="delete")
+ if instances_to_delete:
+ return DeleteInstances(cfg,
+ list_instances.GetInstancesFromInstanceNames(
+ cfg, instances_to_delete))
if args.adb_port:
return DeleteInstances(
diff --git a/delete/delete_args.py b/delete/delete_args.py
index dc9c106..9058d28 100644
--- a/delete/delete_args.py
+++ b/delete/delete_args.py
@@ -40,8 +40,8 @@
dest="instance_names",
nargs="+",
required=False,
- help="The names of the remote instances that need to delete, "
- "separated by spaces, e.g. --instance-names instance-1 instance-2")
+ help="The names of the instances that need to delete, "
+ "separated by spaces, e.g. --instance-names instance-1 local-instance-1")
delete_group.add_argument(
"--all",
action="store_true",
@@ -49,12 +49,6 @@
required=False,
help="If more than 1 AVD instance is found, delete them all.")
delete_group.add_argument(
- "--local-instance",
- action="store_true",
- dest="local_instance",
- required=False,
- help="Only delete the local instance.")
- delete_group.add_argument(
"--adb-port", "-p",
type=int,
dest="adb_port",
diff --git a/delete/delete_test.py b/delete/delete_test.py
index 916cd22..bb7c10e 100644
--- a/delete/delete_test.py
+++ b/delete/delete_test.py
@@ -31,7 +31,7 @@
@mock.patch("subprocess.check_output")
def testGetStopcvd(self, mock_subprocess, mock_path_exist):
"""Test _GetStopCvd."""
- mock_subprocess.side_effect = ["fack_id",
+ mock_subprocess.side_effect = ["fake_id",
"/tmp/bin/run_cvd"]
expected_value = "/tmp/bin/stop_cvd"
self.assertEqual(expected_value, delete._GetStopCvd())
@@ -41,7 +41,10 @@
def testDeleteLocalInstance(self, mock_subprocess, mock_get_stopcvd):
"""Test DeleteLocalInstance."""
mock_subprocess.return_value = True
- delete_report = delete.DeleteLocalInstance()
+ instance_object = mock.MagicMock()
+ instance_object.instance_dir = "fake_instance_dir"
+ instance_object.name = "local-instance"
+ delete_report = delete.DeleteLocalInstance(instance_object)
self.assertEqual(delete_report.data, {
"deleted": [
{
diff --git a/errors.py b/errors.py
index ca28398..d77ed28 100644
--- a/errors.py
+++ b/errors.py
@@ -245,3 +245,7 @@
class UnsupportedLocalInstanceId(Exception):
"""Unsupported local instance id."""
+
+
+class InvalidInstanceDir(Exception):
+ """Invalid instance dir."""
diff --git a/internal/constants.py b/internal/constants.py
index 895a312..9d91677 100755
--- a/internal/constants.py
+++ b/internal/constants.py
@@ -113,6 +113,7 @@
COMMAND_PS = ["ps", "aux"]
CMD_LAUNCH_CVD = "launch_cvd"
+CMD_PGREP = "pgrep"
CMD_STOP_CVD = "stop_cvd"
CMD_RUN_CVD = "run_cvd"
ENV_ANDROID_BUILD_TOP = "ANDROID_BUILD_TOP"
@@ -144,6 +145,7 @@
INS_KEY_IS_LOCAL = "remote"
INS_STATUS_RUNNING = "RUNNING"
LOCAL_INS_NAME = "local-instance"
+LOCAL_INS_HOME_PREFIX = "instance_home_"
ENV_CUTTLEFISH_CONFIG_FILE = "CUTTLEFISH_CONFIG_FILE"
CUTTLEFISH_CONFIG_FILE = "cuttlefish_config.json"
@@ -151,7 +153,6 @@
TOOL_NAME = "acloud"
EXIT_BY_USER = 1
EXIT_BY_ERROR = -99
-RE_LAUNCH_CVD_PATTERN = "launch_cvd.*%(arg_name)s %(arg_value)s"
# For reuse gce instance
SELECT_ONE_GCE_INSTANCE = "select_one_gce_instance"
diff --git a/internal/lib/cvd_compute_client_multi_stage.py b/internal/lib/cvd_compute_client_multi_stage.py
index 44c0e90..98783a4 100644
--- a/internal/lib/cvd_compute_client_multi_stage.py
+++ b/internal/lib/cvd_compute_client_multi_stage.py
@@ -175,7 +175,7 @@
if avd_spec:
if avd_spec.instance_name_to_reuse:
self.StopCvd()
- self.CleanUpImages()
+ self.CleanUp()
return instance
# TODO: Remove following code after create_cf deprecated.
@@ -277,17 +277,18 @@
except subprocess.CalledProcessError as e:
logger.debug("Failed to stop_cvd (possibly no running device): %s", e)
- def CleanUpImages(self):
- """Clean up the images on the existing instance.
+ def CleanUp(self):
+ """Clean up the files/folders on the existing instance.
- If previous AVD have these images, reusing the instance may have
- side effects if didn't clean it.
+ If previous AVD have these files/folders, reusing the instance may have
+ side effects if not cleaned. The path in the instance is /home/vsoc-01/*
+ if the GCE user is vsoc-01.
"""
- ssh_command = "/bin/rm ./*.img"
+ ssh_command = "'/bin/rm -rf /home/%s/*'" % constants.GCE_USER
try:
self._ssh.Run(ssh_command)
except subprocess.CalledProcessError as e:
- logger.debug("Failed to clean up the images failed: %s", e)
+ logger.debug("Failed to clean up the files/folders: %s", e)
@utils.TimeExecute(function_description="Launching AVD(s) and waiting for boot up",
result_evaluator=utils.BootEvaluator)
diff --git a/internal/lib/gcompute_client.py b/internal/lib/gcompute_client.py
index 5709445..bde5ac2 100755
--- a/internal/lib/gcompute_client.py
+++ b/internal/lib/gcompute_client.py
@@ -1584,7 +1584,7 @@
# in the metadata. There may not be an actual ssh key value so
# that's why we filter for None to avoid an empty line in front.
ssh_key_item[_METADATA_KEY_VALUE] = "\n".join(
- filter(None, [ssh_key_item[_METADATA_KEY_VALUE], entry]))
+ list(filter(None, [ssh_key_item[_METADATA_KEY_VALUE], entry])))
else:
# Since there is no ssh key item in the metadata, we need to add it in.
ssh_key_item = {_METADATA_KEY: _SSH_KEYS_NAME,
diff --git a/internal/lib/goldfish_compute_client.py b/internal/lib/goldfish_compute_client.py
index 926cdac..d9d1d20 100644
--- a/internal/lib/goldfish_compute_client.py
+++ b/internal/lib/goldfish_compute_client.py
@@ -122,6 +122,17 @@
raise errors.DeviceBootError(
"Emulator timed out while booting.")
+ @staticmethod
+ def GetKernelBuildArtifact(target):
+ if target == "kernel":
+ return "bzImage"
+ if target == "kernel_x86_64":
+ return "bzImage"
+ if target == "kernel_aarch64":
+ return "Image.gz"
+ raise errors.DeviceBootError(
+ "Don't know the artifact name for '%s' target" % target)
+
# pylint: disable=too-many-locals,arguments-differ
# TODO: Refactor CreateInstance to pass in an object instead of all these args.
def CreateInstance(self,
@@ -133,6 +144,7 @@
build_id,
kernel_branch=None,
kernel_build_id=None,
+ kernel_build_target=None,
emulator_branch=None,
emulator_build_id=None,
blank_data_disk_size_gb=None,
@@ -152,6 +164,7 @@
build_id: String, build id, a string, e.g. "2263051", "P2804227"
kernel_branch: String, kernel branch name.
kernel_build_id: String, kernel build id.
+ kernel_build_target: kernel target, e.g. "kernel_x86_64"
emulator_branch: String, emulator branch name, e.g."aosp-emu-master-dev"
emulator_build_id: String, emulator build id, a string, e.g. "2263051", "P2804227"
blank_data_disk_size_gb: Integer, size of the blank data disk in GB.
@@ -181,9 +194,12 @@
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 kernel_branch and kernel_build_id:
+ if kernel_branch and kernel_build_id and kernel_build_target:
metadata["cvd_01_fetch_kernel_bid"] = "{branch}/{build_id}".format(
branch=kernel_branch, build_id=kernel_build_id)
+ metadata["cvd_01_fetch_kernel_build_target"] = kernel_build_target
+ metadata["cvd_01_fetch_kernel_build_artifact"] = (
+ self.GetKernelBuildArtifact(kernel_build_target))
metadata["cvd_01_use_custom_kernel"] = "true"
if emulator_branch and emulator_build_id:
metadata[
diff --git a/internal/lib/goldfish_compute_client_test.py b/internal/lib/goldfish_compute_client_test.py
index 8b67088..cfee21f 100644
--- a/internal/lib/goldfish_compute_client_test.py
+++ b/internal/lib/goldfish_compute_client_test.py
@@ -37,6 +37,8 @@
BUILD_ID = "2263051"
KERNEL_BRANCH = "kernel-p-dev-android-goldfish-4.14-x86-64"
KERNEL_BUILD_ID = "112233"
+ KERNEL_BUILD_TARGET = "kernel_x86_64"
+ KERNEL_BUILD_ARTIFACT = "bzImage"
EMULATOR_BRANCH = "aosp-emu-master-dev"
EMULATOR_BUILD_ID = "1234567"
DPI = 160
@@ -105,6 +107,8 @@
"cvd_01_fetch_kernel_bid":
"{branch}/{build_id}".format(
branch=self.KERNEL_BRANCH, build_id=self.KERNEL_BUILD_ID),
+ "cvd_01_fetch_kernel_build_target": self.KERNEL_BUILD_TARGET,
+ "cvd_01_fetch_kernel_build_artifact": self.KERNEL_BUILD_ARTIFACT,
"cvd_01_use_custom_kernel": "true",
"cvd_01_fetch_emulator_bid":
"{branch}/{build_id}".format(
@@ -120,8 +124,11 @@
self.goldfish_compute_client.CreateInstance(
self.INSTANCE, self.IMAGE, self.IMAGE_PROJECT, self.TARGET,
- self.BRANCH, self.BUILD_ID, self.KERNEL_BRANCH,
- self.KERNEL_BUILD_ID, self.EMULATOR_BRANCH,
+ self.BRANCH, self.BUILD_ID,
+ self.KERNEL_BRANCH,
+ self.KERNEL_BUILD_ID,
+ self.KERNEL_BUILD_TARGET,
+ self.EMULATOR_BRANCH,
self.EMULATOR_BUILD_ID, self.EXTRA_DATA_DISK_SIZE_GB, self.GPU,
extra_scopes=self.EXTRA_SCOPES,
tags=self.TAGS)
diff --git a/internal/lib/utils.py b/internal/lib/utils.py
index af0d234..ff7e3a8 100755
--- a/internal/lib/utils.py
+++ b/internal/lib/utils.py
@@ -78,7 +78,6 @@
_VNC_BIN = "ssvnc"
_CMD_KILL = ["pkill", "-9", "-f"]
-_CMD_PGREP = "pgrep"
_CMD_SG = "sg "
_CMD_START_VNC = "%(bin)s vnc://127.0.0.1:%(port)d"
_CMD_INSTALL_SSVNC = "sudo apt-get --assume-yes install ssvnc"
@@ -1028,7 +1027,7 @@
"""
try:
with open(os.devnull, "w") as dev_null:
- subprocess.check_call([_CMD_PGREP, "-af", command],
+ subprocess.check_call([constants.CMD_PGREP, "-af", command],
stderr=dev_null, stdout=dev_null)
return True
except subprocess.CalledProcessError:
diff --git a/list/instance.py b/list/instance.py
index 005abcf..7b58792 100644
--- a/list/instance.py
+++ b/list/instance.py
@@ -33,6 +33,7 @@
import os
import re
import subprocess
+import tempfile
# pylint: disable=import-error
import dateutil.parser
@@ -46,6 +47,9 @@
logger = logging.getLogger(__name__)
+_ACLOUD_CVD_TEMP = os.path.join(tempfile.gettempdir(), "acloud_cvd_temp")
+_CVD_RUNTIME_FOLDER_NAME = "cuttlefish_runtime"
+_LOCAL_INSTANCE_HOME = "instance_home_%s"
_MSG_UNABLE_TO_CALCULATE = "Unable to calculate"
_RE_GROUP_ADB = "local_adb_port"
_RE_GROUP_VNC = "local_vnc_port"
@@ -62,6 +66,53 @@
constants.ADB_PORT])
+def GetLocalInstanceHomeDir(local_instance_id):
+ """Get local instance home dir accroding to instance id.
+
+ Args:
+ local_instance_id: Integer of instance id.
+
+ Return:
+ String, path of instance home dir.
+ """
+ return os.path.join(_ACLOUD_CVD_TEMP,
+ _LOCAL_INSTANCE_HOME % local_instance_id)
+
+
+def GetLocalInstanceRuntimeDir(local_instance_id):
+ """Get instance runtime dir
+
+ Args:
+ local_instance_id: Integer of instance id.
+
+ Return:
+ String, path of instance runtime dir.
+ """
+ return os.path.join(GetLocalInstanceHomeDir(local_instance_id),
+ _CVD_RUNTIME_FOLDER_NAME)
+
+
+def GetCuttlefishRuntimeConfig(local_instance_id):
+ """Get and parse cuttlefish_config.json.
+
+ Args:
+ local_instance_id: Integer of instance id.
+
+ Returns:
+ A dictionary that parsed from cuttlefish runtime config.
+
+ Raises:
+ errors.ConfigError: if file not found or config load failed.
+ """
+ runtime_cf_config_path = os.path.join(GetLocalInstanceRuntimeDir(
+ local_instance_id), constants.CUTTLEFISH_CONFIG_FILE)
+ if not os.path.exists(runtime_cf_config_path):
+ raise errors.ConfigError(
+ "file does not exist: %s" % runtime_cf_config_path)
+ with open(runtime_cf_config_path, "r") as cf_config:
+ return json.load(cf_config)
+
+
def GetLocalPortsbyInsId(local_instance_id):
"""Get vnc and adb port by local instance id.
@@ -105,21 +156,25 @@
class Instance(object):
"""Class to store data of instance."""
- def __init__(self):
- self._name = None
- self._fullname = None
- self._status = None
- self._display = None # Resolution and dpi
- self._ip = None
- self._adb_port = None # adb port which is forwarding to remote
- self._vnc_port = None # vnc port which is forwarding to remote
- self._ssh_tunnel_is_connected = None # True if ssh tunnel is still connected
- self._createtime = None
- self._elapsed_time = None
- self._avd_type = None
- self._avd_flavor = None
- self._is_local = None # True if this is a local instance
- self._device_information = None
+ def __init__(self, name, fullname, display, ip, status=None, adb_port=None,
+ vnc_port=None, ssh_tunnel_is_connected=None, createtime=None,
+ elapsed_time=None, avd_type=None, avd_flavor=None,
+ is_local=False, device_information=None):
+ self._name = name
+ self._fullname = fullname
+ self._status = status
+ self._display = display # Resolution and dpi
+ self._ip = ip
+ self._adb_port = adb_port # adb port which is forwarding to remote
+ self._vnc_port = vnc_port # vnc port which is forwarding to remote
+ # True if ssh tunnel is still connected
+ self._ssh_tunnel_is_connected = ssh_tunnel_is_connected
+ self._createtime = createtime
+ self._elapsed_time = elapsed_time
+ self._avd_type = avd_type
+ self._avd_flavor = avd_flavor
+ self._is_local = is_local # True if this is a local instance
+ self._device_information = device_information
def __repr__(self):
"""Return full name property for print."""
@@ -214,95 +269,73 @@
"""Return if it is a local instance."""
return self._is_local
+ @property
+ def adb_port(self):
+ """Return adb_port."""
+ return self._adb_port
+
+ @property
+ def vnc_port(self):
+ """Return vnc_port."""
+ return self._vnc_port
+
class LocalInstance(Instance):
"""Class to store data of local instance."""
- # pylint: disable=protected-access
- def __new__(cls):
+ def __init__(self, local_instance_id, x_res, y_res, dpi, create_time,
+ ins_dir=None):
"""Initialize a localInstance object.
- Gather local instance information from launch_cvd process.
-
- returns:
- Instance object if launch_cvd process is found otherwise return None.
+ Args:
+ local_instance_id: Integer of instance id.
+ x_res: Integer of x dimension.
+ y_res: Integer of y dimension.
+ dpi: Integer of dpi.
+ date_str: String of create time.
+ ins_dir: String, path of instance idr.
"""
- # Running instances on local is not supported on all OS.
- if not utils.IsSupportedPlatform():
- return None
+ display = ("%sx%s (%s)" % (x_res, y_res, dpi))
+ elapsed_time = _GetElapsedTime(create_time) if create_time else None
+ name = "%s-%d" % (constants.LOCAL_INS_NAME, local_instance_id)
+ local_ports = GetLocalPortsbyInsId(local_instance_id)
+ fullname = (_FULL_NAME_STRING %
+ {"device_serial": "127.0.0.1:%d" % local_ports.adb_port,
+ "instance_name": name,
+ "elapsed_time": elapsed_time})
+ adb_device = AdbTools(local_ports.adb_port)
+ device_information = None
+ if adb_device.IsAdbConnected():
+ device_information = adb_device.device_information
- process_output = subprocess.check_output(_COMMAND_PS_LAUNCH_CVD)
- for line in process_output.splitlines():
- match = _RE_RUN_CVD.match(line)
- if match:
- local_instance = Instance()
- cf_runtime_config_dict = GetCuttlefishRuntimeConfig()
- x_res = cf_runtime_config_dict["x_res"]
- y_res = cf_runtime_config_dict["y_res"]
- dpi = cf_runtime_config_dict["dpi"]
- date_str = match.group("date_str").strip()
- local_instance._name = constants.LOCAL_INS_NAME
- local_instance._createtime = date_str
- local_instance._elapsed_time = _GetElapsedTime(date_str)
- local_instance._fullname = (_FULL_NAME_STRING %
- {"device_serial": "127.0.0.1:%d" %
- constants.CF_ADB_PORT,
- "instance_name": local_instance._name,
- "elapsed_time": local_instance._elapsed_time})
- local_instance._avd_type = constants.TYPE_CF
- local_instance._ip = "127.0.0.1"
- local_instance._status = constants.INS_STATUS_RUNNING
- local_instance._adb_port = constants.CF_ADB_PORT
- local_instance._vnc_port = constants.CF_VNC_PORT
- local_instance._display = ("%sx%s (%s)" % (x_res, y_res, dpi))
- local_instance._is_local = True
- local_instance._ssh_tunnel_is_connected = True
+ super(LocalInstance, self).__init__(
+ name=name, fullname=fullname, display=display, ip="127.0.0.1",
+ status=constants.INS_STATUS_RUNNING, adb_port=local_ports.adb_port,
+ vnc_port=local_ports.vnc_port, createtime=create_time,
+ elapsed_time=elapsed_time, avd_type=constants.TYPE_CF,
+ is_local=True, device_information=device_information)
- adb_device = AdbTools(constants.CF_ADB_PORT)
- if adb_device.IsAdbConnected():
- local_instance._device_information = adb_device.device_information
- return local_instance
- return None
+ # LocalInstance class properties
+ self._instance_dir = ins_dir
-def GetCuttlefishRuntimeConfig():
- """Get and parse cuttlefish_config.json.
+ @property
+ def instance_dir(self):
+ """Return _instance_dir."""
+ return self._instance_dir
- Returns:
- Dict parsing json file from cuttlefish runtime config.
-
- Raises:
- errors.ConfigError: if file not found or config load failed.
- """
- runtime_cf_config_path = os.path.join(os.path.expanduser("~"),
- "cuttlefish_runtime",
- "cuttlefish_config.json")
- if os.path.exists(runtime_cf_config_path):
- with open(runtime_cf_config_path, "r") as cf_config:
- return json.load(cf_config)
- else:
- raise errors.ConfigError("file does not exist: %s" % runtime_cf_config_path)
- raise errors.ConfigError("Could not load cuttlefish_config.json.")
class RemoteInstance(Instance):
"""Class to store data of remote instance."""
+ # pylint: disable=too-many-locals
def __init__(self, gce_instance):
"""Process the args into class vars.
- RemoteInstace initialized by gce dict object.
+ RemoteInstace initialized by gce dict object. We parse the required data
+ from gce_instance to local variables.
Reference:
https://cloud.google.com/compute/docs/reference/rest/v1/instances/get
- Args:
- gce_instance: dict object queried from gce.
- """
- super(RemoteInstance, self).__init__()
- self._ProcessGceInstance(gce_instance)
- self._is_local = False
-
- def _ProcessGceInstance(self, gce_instance):
- """Parse the required data from gce_instance to local variables.
-
We also gather more details on client side including the forwarding adb
port and vnc port which will be used to determine the status of ssh
tunnel connection.
@@ -314,13 +347,13 @@
- Terminated: If we can't retrieve the public ip from gce instance.
Args:
- gce_instance: dict object queried from gce.
+ gce_instance: dict object queried from gce.
"""
- self._name = gce_instance.get(constants.INS_KEY_NAME)
+ name = gce_instance.get(constants.INS_KEY_NAME)
- self._createtime = gce_instance.get(constants.INS_KEY_CREATETIME)
- self._elapsed_time = _GetElapsedTime(self._createtime)
- self._status = gce_instance.get(constants.INS_KEY_STATUS)
+ create_time = gce_instance.get(constants.INS_KEY_CREATETIME)
+ elapsed_time = _GetElapsedTime(create_time)
+ status = gce_instance.get(constants.INS_KEY_STATUS)
ip = None
for network_interface in gce_instance.get("networkInterfaces"):
@@ -328,44 +361,56 @@
ip = access_config.get("natIP")
# Get metadata
+ display = None
+ avd_type = None
+ avd_flavor = None
for metadata in gce_instance.get("metadata", {}).get("items", []):
key = metadata["key"]
value = metadata["value"]
if key == constants.INS_KEY_DISPLAY:
- self._display = value
+ display = value
elif key == constants.INS_KEY_AVD_TYPE:
- self._avd_type = value
+ avd_type = value
elif key == constants.INS_KEY_AVD_FLAVOR:
- self._avd_flavor = value
+ avd_flavor = value
# Find ssl tunnel info.
+ adb_port = None
+ vnc_port = None
+ device_information = None
if ip:
- forwarded_ports = self.GetAdbVncPortFromSSHTunnel(ip,
- self._avd_type)
- self._ip = ip
- self._adb_port = forwarded_ports.adb_port
- self._vnc_port = forwarded_ports.vnc_port
- self._ssh_tunnel_is_connected = self._adb_port is not None
+ forwarded_ports = self.GetAdbVncPortFromSSHTunnel(ip, avd_type)
+ adb_port = forwarded_ports.adb_port
+ vnc_port = forwarded_ports.vnc_port
+ ssh_tunnel_is_connected = adb_port is not None
- adb_device = AdbTools(self._adb_port)
+ adb_device = AdbTools(adb_port)
if adb_device.IsAdbConnected():
- self._device_information = adb_device.device_information
- self._fullname = (_FULL_NAME_STRING %
- {"device_serial": "127.0.0.1:%d" % self._adb_port,
- "instance_name": self._name,
- "elapsed_time": self._elapsed_time})
+ device_information = adb_device.device_information
+ fullname = (_FULL_NAME_STRING %
+ {"device_serial": "127.0.0.1:%d" % adb_port,
+ "instance_name": name,
+ "elapsed_time": elapsed_time})
else:
- self._fullname = (_FULL_NAME_STRING %
- {"device_serial": "not connected",
- "instance_name": self._name,
- "elapsed_time": self._elapsed_time})
+ fullname = (_FULL_NAME_STRING %
+ {"device_serial": "not connected",
+ "instance_name": name,
+ "elapsed_time": elapsed_time})
# If instance is terminated, its ip is None.
else:
- self._ssh_tunnel_is_connected = False
- self._fullname = (_FULL_NAME_STRING %
- {"device_serial": "terminated",
- "instance_name": self._name,
- "elapsed_time": self._elapsed_time})
+ ssh_tunnel_is_connected = False
+ fullname = (_FULL_NAME_STRING %
+ {"device_serial": "terminated",
+ "instance_name": name,
+ "elapsed_time": elapsed_time})
+
+ super(RemoteInstance, self).__init__(
+ name=name, fullname=fullname, display=display, ip=ip, status=status,
+ adb_port=adb_port, vnc_port=vnc_port,
+ ssh_tunnel_is_connected=ssh_tunnel_is_connected,
+ createtime=create_time, elapsed_time=elapsed_time, avd_type=avd_type,
+ avd_flavor=avd_flavor, is_local=False,
+ device_information=device_information)
@staticmethod
def GetAdbVncPortFromSSHTunnel(ip, avd_type):
diff --git a/list/instance_test.py b/list/instance_test.py
index af1960b..8c9e1ca 100644
--- a/list/instance_test.py
+++ b/list/instance_test.py
@@ -61,21 +61,23 @@
""""Test get local instance info from launch_cvd process."""
self.Patch(subprocess, "check_output", return_value=self.PS_LAUNCH_CVD)
self.Patch(instance, "_GetElapsedTime", return_value="fake_time")
- self.Patch(instance, "GetCuttlefishRuntimeConfig",
- return_value=self.PS_RUNTIME_CF_CONFIG)
- local_instance = instance.LocalInstance()
- self.assertEqual(constants.LOCAL_INS_NAME, local_instance.name)
+ local_instance = instance.LocalInstance(2,
+ "1080",
+ "1920",
+ "480",
+ "Sat Nov 10 21:55:10 2018",
+ "fake_instance_dir")
+ self.assertEqual(constants.LOCAL_INS_NAME + "-2", local_instance.name)
self.assertEqual(True, local_instance.islocal)
self.assertEqual("1080x1920 (480)", local_instance.display)
self.assertEqual("Sat Nov 10 21:55:10 2018", local_instance.createtime)
- expected_full_name = "device serial: 127.0.0.1:%s (%s) elapsed time: %s" % (
- constants.CF_ADB_PORT, constants.LOCAL_INS_NAME, "fake_time")
+ expected_full_name = ("device serial: 127.0.0.1:%s (%s) elapsed time: %s"
+ % ("6521",
+ constants.LOCAL_INS_NAME + "-2",
+ "fake_time"))
self.assertEqual(expected_full_name, local_instance.fullname)
-
- # test return None if no launch_cvd process found
- self.Patch(subprocess, "check_output", return_value="no launch_cvd "
- "found")
- self.assertEqual(None, instance.LocalInstance())
+ self.assertEqual(6521, local_instance.forwarding_adb_port)
+ self.assertEqual(6445, local_instance.forwarding_vnc_port)
def testGetElapsedTime(self):
"""Test _GetElapsedTime"""
diff --git a/list/list.py b/list/list.py
index ce45c8c..05596df 100644
--- a/list/list.py
+++ b/list/list.py
@@ -20,6 +20,8 @@
from __future__ import print_function
import getpass
import logging
+import re
+import subprocess
from acloud import errors
from acloud.internal import constants
@@ -32,6 +34,31 @@
logger = logging.getLogger(__name__)
+_COMMAND_PS_LAUNCH_CVD = ["ps", "-wweo", "lstart,cmd"]
+_RE_LOCAL_INSTANCE_ID = re.compile(r".+instance_home_(?P<ins_id>\d+).+")
+_RE_LOCAL_CVD_PORT = re.compile(r"^127\.0\.0\.1:65(?P<cvd_port_suffix>\d{2})\s+")
+
+
+def GetActiveCVDIds():
+ """Get active local cvd ids from adb devices.
+
+ The adb port of local instance will be decided according to instance id.
+ The rule of adb port will be '6520 + [instance id] - 1'. So we grep last
+ two digits of port and calculate the instance id.
+
+ Return:
+ List of cvd id.
+ """
+ local_cvd_ids = []
+ adb_cmd = [constants.ADB_BIN, "devices"]
+ device_info = subprocess.check_output(adb_cmd)
+ for device in device_info.splitlines():
+ match = _RE_LOCAL_CVD_PORT.match(device)
+ if match:
+ cvd_serial = match.group("cvd_port_suffix")
+ local_cvd_ids.append(int(cvd_serial) - 19)
+ return local_cvd_ids
+
def _ProcessInstances(instance_list):
"""Get more details of remote instances.
@@ -110,6 +137,64 @@
return _ProcessInstances(all_instances)
+def GetLocalInstances():
+ """Look for local instances.
+
+ Gather local instances information from cuttlefish runtime config.
+
+ Returns:
+ instance_list: List of local instances.
+ """
+ # Running instances on local is not supported on all OS.
+ if not utils.IsSupportedPlatform():
+ return None
+
+ local_cvd_ids = GetActiveCVDIds()
+ local_instance_list = []
+ for cvd_id in local_cvd_ids:
+ ins_dir = x_res = y_res = dpi = cf_runtime_config_dict = None
+ try:
+ cf_runtime_config_dict = instance.GetCuttlefishRuntimeConfig(cvd_id)
+ except errors.ConfigError:
+ logger.error("Instance[id:%d] dir not found!", cvd_id)
+
+ if cf_runtime_config_dict:
+ ins_dir = instance.GetLocalInstanceRuntimeDir(cvd_id)
+ x_res = cf_runtime_config_dict["x_res"]
+ y_res = cf_runtime_config_dict["y_res"]
+ dpi = cf_runtime_config_dict["dpi"]
+ # TODO(143063678), there's no createtime info in
+ # cuttlefish_config.json so far.
+ local_instance_list.append(instance.LocalInstance(cvd_id,
+ x_res,
+ y_res,
+ dpi,
+ None,
+ ins_dir))
+ return local_instance_list
+
+
+def _GetIdFromInstanceDirStr(instance_dir):
+ """Look for instance id from the path of instance dir.
+
+ Args:
+ instance_dir: String, path of instance_dir.
+
+ Returns:
+ Integer of instance id.
+
+ Raises:
+ errors.InvalidInstanceDir: Invalid instance idr.
+ """
+ match = _RE_LOCAL_INSTANCE_ID.match(instance_dir)
+ if match:
+ return int(match.group("ins_id"))
+
+ raise errors.InvalidInstanceDir("Instance dir is invalid:%s. local AVD "
+ "launched outside acloud is not supported"
+ % instance_dir)
+
+
def GetInstances(cfg):
"""Look for remote/local instances.
@@ -120,9 +205,9 @@
instance_list: List of instances.
"""
instances_list = GetRemoteInstances(cfg)
- local_instance = instance.LocalInstance()
- if local_instance:
- instances_list.append(local_instance)
+ local_instances = GetLocalInstances()
+ if local_instances:
+ instances_list.extend(local_instances)
return instances_list
diff --git a/public/acloud_main.py b/public/acloud_main.py
index 65e649b..c80b995 100644
--- a/public/acloud_main.py
+++ b/public/acloud_main.py
@@ -403,6 +403,7 @@
emulator_branch=args.emulator_branch,
kernel_build_id=args.kernel_build_id,
kernel_branch=args.kernel_branch,
+ kernel_build_target=args.kernel_build_target,
gpu=args.gpu,
num=args.num,
serial_log_file=args.serial_log_file,
diff --git a/public/actions/create_goldfish_action.py b/public/actions/create_goldfish_action.py
index 36124f8..c5b942a 100644
--- a/public/actions/create_goldfish_action.py
+++ b/public/actions/create_goldfish_action.py
@@ -67,6 +67,7 @@
emulator_build_id,
kernel_build_id=None,
kernel_branch=None,
+ kernel_build_target=None,
gpu=None,
avd_spec=None,
tags=None,
@@ -113,7 +114,8 @@
self.emulator_build_info = self._build_client.GetBuildInfo(
emulator_build_target, emulator_build_id, emulator_branch)
self.kernel_build_info = self._build_client.GetBuildInfo(
- cfg.kernel_build_target, kernel_build_id, kernel_branch)
+ kernel_build_target or cfg.kernel_build_target, kernel_build_id,
+ kernel_branch)
def GetBuildInfoDict(self):
"""Get build info dictionary.
@@ -159,6 +161,7 @@
emulator_build_id=self.emulator_build_info.build_id,
kernel_branch=self.kernel_build_info.branch,
kernel_build_id=self.kernel_build_info.build_id,
+ kernel_build_target=self.kernel_build_info.build_target,
gpu=self._gpu,
blank_data_disk_size_gb=self._blank_data_disk_size_gb,
avd_spec=self._avd_spec,
@@ -232,6 +235,7 @@
emulator_branch=None,
kernel_build_id=None,
kernel_branch=None,
+ kernel_build_target=None,
gpu=None,
num=1,
serial_log_file=None,
@@ -252,6 +256,7 @@
gpu: String, GPU to attach to the device or None. e.g. "nvidia-k80"
kernel_build_id: Kernel build id, a string.
kernel_branch: Kernel branch name, a string.
+ kernel_build_target: Kernel build artifact, a string.
num: Integer, Number of devices to create.
serial_log_file: String, A path to a file where serial output should
be saved to.
@@ -313,20 +318,22 @@
logger.info(
"Creating a goldfish device in project %s, build_target: %s, "
"build_id: %s, emulator_bid: %s, kernel_build_id: %s, "
- "kernel_branh: %s, GPU: %s, num: %s, "
+ "kernel_branch: %s, kernel_build_target: %s, GPU: %s, num: %s, "
"serial_log_file: %s, "
"autoconnect: %s", cfg.project, build_target, build_id,
- emulator_build_id, kernel_build_id, kernel_branch, gpu, num,
- serial_log_file, autoconnect)
+ emulator_build_id, kernel_build_id, kernel_branch, kernel_build_target,
+ gpu, num, serial_log_file, autoconnect)
- device_factory = GoldfishDeviceFactory(cfg, build_target, build_id,
- cfg.emulator_build_target,
- emulator_build_id, gpu=gpu,
- avd_spec=avd_spec, tags=tags,
- branch=branch,
- emulator_branch=emulator_branch,
- kernel_build_id=kernel_build_id,
- kernel_branch=kernel_branch)
+ device_factory = GoldfishDeviceFactory(
+ cfg, build_target, build_id,
+ cfg.emulator_build_target,
+ emulator_build_id, gpu=gpu,
+ avd_spec=avd_spec, tags=tags,
+ branch=branch,
+ emulator_branch=emulator_branch,
+ kernel_build_id=kernel_build_id,
+ kernel_branch=kernel_branch,
+ kernel_build_target=kernel_build_target)
return common_operations.CreateDevices("create_gf", cfg, device_factory,
num, constants.TYPE_GF,
diff --git a/public/actions/create_goldfish_action_test.py b/public/actions/create_goldfish_action_test.py
index fa04ee2..d031167 100644
--- a/public/actions/create_goldfish_action_test.py
+++ b/public/actions/create_goldfish_action_test.py
@@ -123,7 +123,10 @@
report = create_goldfish_action.CreateDevices(
none_avd_spec, cfg, build_target=self.BUILD_TARGET,
build_id=self.BUILD_ID, emulator_build_id=self.EMULATOR_BUILD_ID,
- gpu=self.GPU, kernel_build_id=self.KERNEL_BUILD_ID)
+ gpu=self.GPU,
+ kernel_branch=self.KERNEL_BRANCH,
+ kernel_build_id=self.KERNEL_BUILD_ID,
+ kernel_build_target=self.KERNEL_BUILD_TARGET)
# Verify
self.compute_client.CreateInstance.assert_called_with(
@@ -138,6 +141,7 @@
emulator_build_id=self.EMULATOR_BUILD_ID,
kernel_branch=self.KERNEL_BRANCH,
kernel_build_id=self.KERNEL_BUILD_ID,
+ kernel_build_target=self.KERNEL_BUILD_TARGET,
gpu=self.GPU,
avd_spec=none_avd_spec,
extra_scopes=self.EXTRA_SCOPES,
@@ -193,6 +197,7 @@
emulator_build_id=self.EMULATOR_BUILD_ID,
kernel_branch=self.KERNEL_BRANCH,
kernel_build_id=self.KERNEL_BUILD_ID,
+ kernel_build_target=self.KERNEL_BUILD_TARGET,
gpu=self.GPU,
avd_spec=self.avd_spec,
extra_scopes=self.EXTRA_SCOPES,
@@ -239,7 +244,9 @@
emulator_branch=None,
gpu=self.GPU,
branch=None,
- kernel_build_id=self.KERNEL_BUILD_ID)
+ kernel_branch=self.KERNEL_BRANCH,
+ kernel_build_id=self.KERNEL_BUILD_ID,
+ kernel_build_target=self.KERNEL_BUILD_TARGET)
# Verify
self.compute_client.CreateInstance.assert_called_with(
@@ -254,6 +261,7 @@
emulator_build_id=self.EMULATOR_BUILD_ID,
kernel_branch=self.KERNEL_BRANCH,
kernel_build_id=self.KERNEL_BUILD_ID,
+ kernel_build_target=self.KERNEL_BUILD_TARGET,
gpu=self.GPU,
avd_spec=none_avd_spec,
extra_scopes=self.EXTRA_SCOPES,
@@ -307,6 +315,7 @@
emulator_build_id=self.EMULATOR_BUILD_ID,
kernel_branch=self.KERNEL_BRANCH,
kernel_build_id=self.KERNEL_BUILD_ID,
+ kernel_build_target=self.KERNEL_BUILD_TARGET,
gpu=self.GPU,
avd_spec=self.avd_spec,
extra_scopes=self.EXTRA_SCOPES,
@@ -363,6 +372,7 @@
emulator_build_id=self.EMULATOR_BUILD_ID,
kernel_branch=self.KERNEL_BRANCH,
kernel_build_id=self.KERNEL_BUILD_ID,
+ kernel_build_target=self.KERNEL_BUILD_TARGET,
gpu=self.GPU,
avd_spec=none_avd_spec,
extra_scopes=self.EXTRA_SCOPES,
@@ -416,6 +426,7 @@
emulator_build_id=self.EMULATOR_BUILD_ID,
kernel_branch=self.KERNEL_BRANCH,
kernel_build_id=self.KERNEL_BUILD_ID,
+ kernel_build_target=self.KERNEL_BUILD_TARGET,
gpu=self.GPU,
avd_spec=self.avd_spec,
extra_scopes=self.EXTRA_SCOPES,
diff --git a/public/actions/remote_instance_cf_device_factory.py b/public/actions/remote_instance_cf_device_factory.py
index 8a539c1..74f5ca7 100644
--- a/public/actions/remote_instance_cf_device_factory.py
+++ b/public/actions/remote_instance_cf_device_factory.py
@@ -250,3 +250,26 @@
and the value is an errors.DeviceBootError object.
"""
return self._compute_client.all_failures
+
+ def GetBuildInfoDict(self):
+ """Get build info dictionary.
+
+ Returns:
+ A build info dictionary.
+ """
+ build_info_dict = {
+ key: val for key, val in self._avd_spec.remote_image.items() if val}
+
+ # kernel_target have default value "kernel". If user provide kernel_build_id
+ # or kernel_branch, then start to process kernel image.
+ if (self._avd_spec.kernel_build_info[constants.BUILD_ID]
+ or self._avd_spec.kernel_build_info[constants.BUILD_BRANCH]):
+ build_info_dict.update(
+ {"kernel_%s" % key: val
+ for key, val in self._avd_spec.kernel_build_info.items() if val}
+ )
+ build_info_dict.update(
+ {"system_%s" % key: val
+ for key, val in self._avd_spec.system_build_info.items() if val}
+ )
+ return build_info_dict