aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Chiu <samchiu@google.com>2020-02-15 13:15:55 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2020-02-15 13:15:55 +0000
commit1771e3a12d2dab5f2ca95fdf8c77ea760adf82a7 (patch)
tree42817259b16d2a564487581d77c8aa007166d4eb
parent9a4962774d60c7711b779e7c81828f146e449066 (diff)
parentdd6ce36d016311c52fef33d6ca4051edc63e8756 (diff)
downloadacloud-1771e3a12d2dab5f2ca95fdf8c77ea760adf82a7.tar.gz
Merge "Query cf local instance according to the result of cvd_status"
-rw-r--r--create/local_image_local_instance.py103
-rw-r--r--create/local_image_local_instance_test.py38
-rw-r--r--delete/delete.py72
-rw-r--r--delete/delete_test.py31
-rwxr-xr-xinternal/constants.py2
-rw-r--r--internal/lib/cvd_runtime_config.py13
-rwxr-xr-xinternal/lib/utils.py11
-rw-r--r--internal/lib/utils_test.py16
-rw-r--r--list/instance.py235
-rw-r--r--list/instance_test.py18
-rw-r--r--list/list.py65
-rw-r--r--list/list_test.py38
-rwxr-xr-xpublic/report.py12
-rw-r--r--public/report_test.py5
-rw-r--r--reconnect/reconnect.py9
-rw-r--r--reconnect/reconnect_test.py12
16 files changed, 352 insertions, 328 deletions
diff --git a/create/local_image_local_instance.py b/create/local_image_local_instance.py
index d40dd5e7..43bb1684 100644
--- a/create/local_image_local_instance.py
+++ b/create/local_image_local_instance.py
@@ -34,7 +34,6 @@ To delete the local instance, we will call stop_cvd with the environment variabl
[CUTTLEFISH_CONFIG_FILE] which is pointing to the runtime cuttlefish json.
"""
-import json
import logging
import os
import shutil
@@ -44,7 +43,6 @@ import sys
from acloud import errors
from acloud.create import base_avd_create
-from acloud.delete import delete
from acloud.internal import constants
from acloud.internal.lib import utils
from acloud.internal.lib.adb_tools import AdbTools
@@ -63,8 +61,6 @@ _CMD_LAUNCH_CVD_DISK_ARGS = (" -blank_data_image_mb %s "
_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]: ")
-_ENV_CVD_HOME = "HOME"
-_ENV_CUTTLEFISH_INSTANCE = "CUTTLEFISH_INSTANCE"
_LAUNCH_CVD_TIMEOUT_SECS = 120 # default timeout as 120 seconds
_LAUNCH_CVD_TIMEOUT_ERROR = ("Cuttlefish AVD launch timeout, did not complete "
"within %d secs.")
@@ -108,7 +104,6 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
result_report = report.Report(command="create")
instance_name = instance.GetLocalInstanceName(
avd_spec.local_instance_id)
- local_ports = instance.GetLocalPortsbyInsId(avd_spec.local_instance_id)
try:
self.CheckLaunchCVD(
cmd, host_bins_path, avd_spec.local_instance_id, local_image_path,
@@ -116,18 +111,27 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
except errors.LaunchCVDFail as launch_error:
result_report.SetStatus(report.Status.BOOT_FAIL)
result_report.AddDeviceBootFailure(
- instance_name, constants.LOCALHOST, local_ports.adb_port,
- local_ports.vnc_port, str(launch_error))
+ instance_name, constants.LOCALHOST, None, None,
+ error=str(launch_error))
return result_report
- result_report.SetStatus(report.Status.SUCCESS)
- result_report.AddDevice(instance_name, constants.LOCALHOST,
- local_ports.adb_port, local_ports.vnc_port)
- # Launch vnc client if we're auto-connecting.
- if avd_spec.connect_vnc:
- utils.LaunchVNCFromReport(result_report, avd_spec, no_prompts)
- if avd_spec.unlock_screen:
- AdbTools(local_ports.adb_port).AutoUnlockScreen()
+ active_ins = list_instance.GetActiveCVD(avd_spec.local_instance_id)
+ if active_ins:
+ result_report.SetStatus(report.Status.SUCCESS)
+ result_report.AddDevice(instance_name, constants.LOCALHOST,
+ active_ins.adb_port, active_ins.vnc_port)
+ # Launch vnc client if we're auto-connecting.
+ if avd_spec.connect_vnc:
+ utils.LaunchVNCFromReport(result_report, avd_spec, no_prompts)
+ if avd_spec.unlock_screen:
+ AdbTools(active_ins.adb_port).AutoUnlockScreen()
+ else:
+ err_msg = "cvd_status return non-zero after launch_cvd"
+ logger.error(err_msg)
+ result_report.SetStatus(report.Status.BOOT_FAIL)
+ result_report.AddDeviceBootFailure(
+ instance_name, constants.LOCALHOST, None, None, error=err_msg)
+
return result_report
@staticmethod
@@ -218,10 +222,11 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
# different dir (e.g. downloaded image).
os.environ[constants.ENV_ANDROID_HOST_OUT] = host_bins_path
# Check if the instance with same id is running.
- if self.IsLocalCVDRunning(local_instance_id):
+ existing_ins = list_instance.GetActiveCVD(local_instance_id)
+ if existing_ins:
if no_prompts or utils.GetUserAnswerYes(_CONFIRM_RELAUNCH %
local_instance_id):
- self._StopCvd(host_bins_path, local_instance_id)
+ existing_ins.Delete()
else:
sys.exit(constants.EXIT_BY_USER)
else:
@@ -239,36 +244,6 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
self._LaunchCvd(cmd, local_instance_id, timeout=timeout_secs)
@staticmethod
- def _StopCvd(host_bins_path, local_instance_id):
- """Execute stop_cvd to stop cuttlefish instance.
-
- Args:
- host_bins_path: String of host package directory.
- local_instance_id: Integer of instance id.
- """
- stop_cvd_cmd = os.path.join(host_bins_path,
- "bin",
- constants.CMD_STOP_CVD)
- with open(os.devnull, "w") as dev_null:
- cvd_env = os.environ.copy()
- cvd_env[constants.ENV_CUTTLEFISH_CONFIG_FILE] = os.path.join(
- instance.GetLocalInstanceRuntimeDir(local_instance_id),
- constants.CUTTLEFISH_CONFIG_FILE)
- subprocess.check_call(
- utils.AddUserGroupsToCmd(
- stop_cvd_cmd, constants.LIST_CF_USER_GROUPS),
- stderr=dev_null, stdout=dev_null, shell=True, env=cvd_env)
-
- # Delete ssvnc viewer
- local_ports = instance.GetLocalPortsbyInsId(local_instance_id)
- delete.CleanupSSVncviewer(local_ports.vnc_port)
- # Disconnect adb device
- adb_cmd = AdbTools(local_ports.adb_port)
- # When relaunch a local instance, we need to pass in retry=True to make
- # 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(cmd, local_instance_id, timeout=None):
"""Execute Launch CVD.
@@ -291,8 +266,8 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
os.makedirs(cvd_runtime_dir)
cvd_env = os.environ.copy()
- cvd_env[_ENV_CVD_HOME] = cvd_home_dir
- cvd_env[_ENV_CUTTLEFISH_INSTANCE] = str(local_instance_id)
+ cvd_env[constants.ENV_CVD_HOME] = cvd_home_dir
+ cvd_env[constants.ENV_CUTTLEFISH_INSTANCE] = str(local_instance_id)
# Check the result of launch_cvd command.
# An exit code of 0 is equivalent to VIRTUAL_DEVICE_BOOT_COMPLETED
process = subprocess.Popen(cmd, shell=True, stderr=subprocess.STDOUT,
@@ -318,19 +293,6 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
utils.TextColors.WARNING)
@staticmethod
- def IsLocalCVDRunning(local_instance_id):
- """Check if the AVD with specific instance id is running
-
- Args:
- local_instance_id: Integer of instance id.
-
- Return:
- Boolean, True if AVD is running.
- """
- local_ports = instance.GetLocalPortsbyInsId(local_instance_id)
- return AdbTools(local_ports.adb_port).IsAdbConnected()
-
- @staticmethod
def IsLocalImageOccupied(local_image_dir):
"""Check if the given image path is being used by a running CVD process.
@@ -340,15 +302,12 @@ class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
Return:
Integer of instance id which using the same image path.
"""
- local_cvd_ids = list_instance.GetActiveCVDIds()
- for cvd_id in local_cvd_ids:
- 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:
- json_array = json.load(config_file)
- for disk_path in json_array[_VIRTUAL_DISK_PATHS]:
+ # TODO(149602560): Remove occupied image checking after after cf disk
+ # overlay is stable
+ for cf_runtime_config_path in instance.GetAllLocalInstanceConfigs():
+ ins = instance.LocalInstance(cf_runtime_config_path)
+ if ins.CvdStatus():
+ for disk_path in ins.virtual_disk_paths:
if local_image_dir in disk_path:
- return cvd_id
+ return ins.instance_id
return None
diff --git a/create/local_image_local_instance_test.py b/create/local_image_local_instance_test.py
index eaa43a5f..e5204709 100644
--- a/create/local_image_local_instance_test.py
+++ b/create/local_image_local_instance_test.py
@@ -24,6 +24,7 @@ import mock
from acloud import errors
from acloud.create import local_image_local_instance
from acloud.list import instance
+from acloud.list import list as list_instance
from acloud.internal import constants
from acloud.internal.lib import driver_test_lib
from acloud.internal.lib import utils
@@ -51,6 +52,13 @@ EOF"""
}
]
+ _EXPECTED_DEVICES_IN_FAILED_REPORT = [
+ {
+ "instance_name": "local-instance-1",
+ "ip": "127.0.0.1"
+ }
+ ]
+
def setUp(self):
"""Initialize new LocalImageLocalInstance."""
super(LocalImageLocalInstanceTest, self).setUp()
@@ -58,7 +66,6 @@ EOF"""
# pylint: disable=protected-access
@mock.patch("acloud.create.local_image_local_instance.utils")
- @mock.patch("acloud.create.local_image_local_instance.instance")
@mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
"PrepareLaunchCVDCmd")
@mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
@@ -66,17 +73,23 @@ EOF"""
@mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
"CheckLaunchCVD")
def testCreateAVD(self, mock_check_launch_cvd, mock_get_image,
- _mock_prepare, mock_instance, mock_utils):
+ _mock_prepare, mock_utils):
"""Test the report returned by _CreateAVD."""
mock_utils.IsSupportedPlatform.return_value = True
-
- mock_instance.GetLocalInstanceName.return_value = "local-instance-1"
- mock_instance.GetLocalPortsbyInsId.return_value = mock.Mock(
- adb_port=6520, vnc_port=6444)
-
mock_get_image.return_value = ("/image/path", "/host/bin/path")
-
mock_avd_spec = mock.Mock(autoconnect=False, unlock_screen=False)
+ self.Patch(instance, "GetLocalInstanceName",
+ return_value="local-instance-1")
+ local_ins = mock.MagicMock(
+ adb_port=6520,
+ vnc_port=6444
+ )
+ local_ins.CvdStatus.return_value = True
+ self.Patch(instance, "LocalInstance",
+ return_value=local_ins)
+ self.Patch(list_instance, "GetActiveCVD",
+ return_value=local_ins)
+
# Success
report = self.local_image_local_instance._CreateAVD(
mock_avd_spec, no_prompts=True)
@@ -90,7 +103,7 @@ EOF"""
mock_avd_spec, no_prompts=True)
self.assertEqual(report.data.get("devices_failing_boot"),
- self._EXPECTED_DEVICES_IN_REPORT)
+ self._EXPECTED_DEVICES_IN_FAILED_REPORT)
self.assertEqual(report.errors, ["timeout"])
# pylint: disable=protected-access
@@ -147,8 +160,7 @@ EOF"""
@mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
"_LaunchCvd")
@mock.patch.object(utils, "GetUserAnswerYes")
- @mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
- "IsLocalCVDRunning")
+ @mock.patch.object(list_instance, "GetActiveCVD")
@mock.patch.object(local_image_local_instance.LocalImageLocalInstance,
"IsLocalImageOccupied")
def testCheckLaunchCVD(self, mock_image_occupied, mock_cvd_running,
@@ -195,8 +207,8 @@ EOF"""
local_instance_id = 3
launch_cvd_cmd = "launch_cvd"
cvd_env = {}
- cvd_env[local_image_local_instance._ENV_CVD_HOME] = "fake_home"
- cvd_env[local_image_local_instance._ENV_CUTTLEFISH_INSTANCE] = str(
+ cvd_env[constants.ENV_CVD_HOME] = "fake_home"
+ cvd_env[constants.ENV_CUTTLEFISH_INSTANCE] = str(
local_instance_id)
process = mock.MagicMock()
process.wait.return_value = True
diff --git a/delete/delete.py b/delete/delete.py
index 86b0a422..02ee4841 100644
--- a/delete/delete.py
+++ b/delete/delete.py
@@ -20,7 +20,6 @@ of an Android Virtual Device.
from __future__ import print_function
import logging
-import os
import re
import subprocess
@@ -42,53 +41,9 @@ logger = logging.getLogger(__name__)
_COMMAND_GET_PROCESS_ID = ["pgrep", "run_cvd"]
_COMMAND_GET_PROCESS_COMMAND = ["ps", "-o", "command", "-p"]
_RE_RUN_CVD = re.compile(r"^(?P<run_cvd>.+run_cvd)")
-_SSVNC_VIEWER_PATTERN = "vnc://127.0.0.1:%(vnc_port)d"
_LOCAL_INSTANCE_PREFIX = "local-"
-def _GetStopCvd():
- """Get stop_cvd path.
-
- "stop_cvd" and "run_cvd" are in the same folder(host package folder).
- Try to get directory of "run_cvd" by "ps -o command -p <pid>." command.
- For example: "/tmp/bin/run_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(
- _COMMAND_GET_PROCESS_COMMAND + process_id.splitlines())
- for process in process_info.splitlines():
- match = _RE_RUN_CVD.match(process)
- if match:
- run_cvd_path = match.group("run_cvd")
- stop_cvd_cmd = os.path.join(os.path.dirname(run_cvd_path),
- constants.CMD_STOP_CVD)
- if os.path.exists(stop_cvd_cmd):
- logger.debug("stop_cvd command: %s", stop_cvd_cmd)
- return stop_cvd_cmd
-
- default_stop_cvd = utils.FindExecutable(constants.CMD_STOP_CVD)
- if default_stop_cvd:
- return default_stop_cvd
-
- raise errors.NoExecuteCmd("Cannot find stop_cvd binary.")
-
-
-def CleanupSSVncviewer(vnc_port):
- """Cleanup the old disconnected ssvnc viewer.
-
- Args:
- vnc_port: Integer, port number of vnc.
- """
- ssvnc_viewer_pattern = _SSVNC_VIEWER_PATTERN % {"vnc_port":vnc_port}
- utils.CleanupProcess(ssvnc_viewer_pattern)
-
-
def DeleteInstances(cfg, instances_to_delete):
"""Delete instances according to instances_to_delete.
@@ -118,8 +73,8 @@ def DeleteInstances(cfg, instances_to_delete):
else:
remote_instance_list.append(instance.name)
# Delete ssvnc viewer
- if instance.forwarding_vnc_port:
- CleanupSSVncviewer(instance.forwarding_vnc_port)
+ if instance.vnc_port:
+ utils.CleanupSSVncviewer(instance.vnc_port)
if remote_instance_list:
# TODO(119283708): We should move DeleteAndroidVirtualDevices into
@@ -171,7 +126,7 @@ def DeleteRemoteInstances(cfg, instances_to_delete, delete_report=None):
def DeleteLocalCuttlefishInstance(instance, delete_report):
"""Delete a local cuttlefish instance.
- Delete local instance with stop_cvd command and write delete instance
+ Delete local instance and write delete instance
information to report.
Args:
@@ -182,21 +137,12 @@ def DeleteLocalCuttlefishInstance(instance, delete_report):
delete_report.
"""
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, env=cvd_env)
- delete_report.SetStatus(report.Status.SUCCESS)
- device_driver.AddDeletionResultToReport(
- delete_report, [instance.name], failed=[],
- error_msgs=[],
- resource_name="instance")
- CleanupSSVncviewer(instance.vnc_port)
+ instance.Delete()
+ delete_report.SetStatus(report.Status.SUCCESS)
+ device_driver.AddDeletionResultToReport(
+ delete_report, [instance.name], failed=[],
+ error_msgs=[],
+ resource_name="instance")
except subprocess.CalledProcessError as e:
delete_report.AddError(str(e))
delete_report.SetStatus(report.Status.FAIL)
diff --git a/delete/delete_test.py b/delete/delete_test.py
index 49cef1cb..829ab7b6 100644
--- a/delete/delete_test.py
+++ b/delete/delete_test.py
@@ -14,12 +14,10 @@
"""Tests for delete."""
import unittest
-import subprocess
import mock
from acloud.delete import delete
from acloud.internal.lib import driver_test_lib
-from acloud.internal.lib import utils
from acloud.list import list as list_instances
from acloud.public import report
@@ -28,20 +26,8 @@ from acloud.public import report
class DeleteTest(driver_test_lib.BaseDriverTest):
"""Test delete functions."""
- # pylint: disable=protected-access
- @mock.patch("os.path.exists", return_value=True)
- @mock.patch("subprocess.check_output")
- def testGetStopcvd(self, mock_subprocess, mock_path_exist):
- """Test _GetStopCvd."""
- mock_subprocess.side_effect = ["fake_id",
- "/tmp/bin/run_cvd"]
- expected_value = "/tmp/bin/stop_cvd"
- self.assertEqual(expected_value, delete._GetStopCvd())
-
- @mock.patch.object(delete, "_GetStopCvd", return_value="")
@mock.patch("subprocess.check_call")
- def testDeleteLocalCuttlefishInstance(self, mock_subprocess,
- mock_get_stopcvd):
+ def testDeleteLocalCuttlefishInstance(self, mock_subprocess):
"""Test DeleteLocalCuttlefishInstance."""
mock_subprocess.return_value = True
instance_object = mock.MagicMock()
@@ -108,21 +94,6 @@ class DeleteTest(driver_test_lib.BaseDriverTest):
self.assertTrue(len(delete_report.errors) > 0)
self.assertEqual(delete_report.status, "FAIL")
- # pylint: disable=protected-access, no-member
- def testCleanupSSVncviwer(self):
- """test cleanup ssvnc viewer."""
- fake_vnc_port = 9999
- fake_ss_vncviewer_pattern = delete._SSVNC_VIEWER_PATTERN % {
- "vnc_port": fake_vnc_port}
- self.Patch(utils, "IsCommandRunning", return_value=True)
- self.Patch(subprocess, "check_call", return_value=True)
- delete.CleanupSSVncviewer(fake_vnc_port)
- subprocess.check_call.assert_called_with(["pkill", "-9", "-f", fake_ss_vncviewer_pattern])
-
- subprocess.check_call.call_count = 0
- self.Patch(utils, "IsCommandRunning", return_value=False)
- subprocess.check_call.assert_not_called()
-
@mock.patch.object(delete, "DeleteInstances", return_value="")
@mock.patch.object(delete, "DeleteRemoteInstances", return_value="")
def testDeleteInstanceByNames(self, mock_delete_remote_ins,
diff --git a/internal/constants.py b/internal/constants.py
index fb95d44b..c5302444 100755
--- a/internal/constants.py
+++ b/internal/constants.py
@@ -150,6 +150,8 @@ INS_KEY_ZONE = "zone"
INS_STATUS_RUNNING = "RUNNING"
LOCAL_INS_NAME = "local-instance"
ENV_CUTTLEFISH_CONFIG_FILE = "CUTTLEFISH_CONFIG_FILE"
+ENV_CUTTLEFISH_INSTANCE = "CUTTLEFISH_INSTANCE"
+ENV_CVD_HOME = "HOME"
CUTTLEFISH_CONFIG_FILE = "cuttlefish_config.json"
TEMP_ARTIFACTS_FOLDER = "acloud_image_artifacts"
diff --git a/internal/lib/cvd_runtime_config.py b/internal/lib/cvd_runtime_config.py
index f15af2ee..fd5bba68 100644
--- a/internal/lib/cvd_runtime_config.py
+++ b/internal/lib/cvd_runtime_config.py
@@ -75,16 +75,16 @@ class CvdRuntimeConfig(object):
"memory_mb" : 4096,
"cpus" : 2,
"dpi" : 320,
- "virtual_disk_paths" :
- [
- "/path-to-image"
- ],
"instances" :
{
"1" :
{
"adb_ip_and_port" : "127.0.0.1:6520",
"instance_dir" : "/path-to-instance-dir",
+ "virtual_disk_paths" :
+ [
+ "/path-to-image"
+ ],
}
}
}
@@ -101,8 +101,6 @@ class CvdRuntimeConfig(object):
adb_connector = self._config_dict.get(_CFG_KEY_ADB_CONNECTOR_BINARY)
self._cvd_tools_path = (os.path.dirname(adb_connector)
if adb_connector else None)
- self._virtual_disk_paths = self._config_dict.get(
- _CFG_KEY_VIRTUAL_DISK_PATHS)
# Below properties will be collected inside of instance id node if there
# are more than one instance.
@@ -110,6 +108,8 @@ class CvdRuntimeConfig(object):
self._vnc_port = self._config_dict.get(_CFG_KEY_VNC_PORT)
self._adb_port = self._config_dict.get(_CFG_KEY_ADB_PORT)
self._adb_ip_port = self._config_dict.get(_CFG_KEY_ADB_IP_PORT)
+ self._virtual_disk_paths = self._config_dict.get(
+ _CFG_KEY_VIRTUAL_DISK_PATHS)
if not self._instance_dir:
ins_cfg = self._config_dict.get(_CFG_KEY_INSTANCES)
ins_dict = ins_cfg.get(self._instance_id)
@@ -121,6 +121,7 @@ class CvdRuntimeConfig(object):
self._vnc_port = ins_dict.get(_CFG_KEY_VNC_PORT)
self._adb_port = ins_dict.get(_CFG_KEY_ADB_PORT)
self._adb_ip_port = ins_dict.get(_CFG_KEY_ADB_IP_PORT)
+ self._virtual_disk_paths = ins_dict.get(_CFG_KEY_VIRTUAL_DISK_PATHS)
@staticmethod
def _GetCuttlefishRuntimeConfig(runtime_cf_config_path):
diff --git a/internal/lib/utils.py b/internal/lib/utils.py
index e6790d33..f248f544 100755
--- a/internal/lib/utils.py
+++ b/internal/lib/utils.py
@@ -100,6 +100,7 @@ _EvaluatedResult = collections.namedtuple("EvaluatedResult",
# dict of supported system and their distributions.
_SUPPORTED_SYSTEMS_AND_DISTS = {"Linux": ["Ubuntu", "Debian"]}
_DEFAULT_TIMEOUT_ERR = "Function did not complete within %d secs."
+_SSVNC_VIEWER_PATTERN = "vnc://127.0.0.1:%(vnc_port)d"
class TempDir(object):
@@ -1251,3 +1252,13 @@ def GetDictItems(namedtuple_object):
"""
return (namedtuple_object.__dict__.items() if six.PY2
else namedtuple_object._asdict().items())
+
+
+def CleanupSSVncviewer(vnc_port):
+ """Cleanup the old disconnected ssvnc viewer.
+
+ Args:
+ vnc_port: Integer, port number of vnc.
+ """
+ ssvnc_viewer_pattern = _SSVNC_VIEWER_PATTERN % {"vnc_port":vnc_port}
+ CleanupProcess(ssvnc_viewer_pattern)
diff --git a/internal/lib/utils_test.py b/internal/lib/utils_test.py
index 480b4d2d..169a36d7 100644
--- a/internal/lib/utils_test.py
+++ b/internal/lib/utils_test.py
@@ -411,6 +411,22 @@ class UtilsTest(driver_test_lib.BaseDriverTest):
first_call_args = utils._ExecuteCommand.call_args_list[0][0]
self.assertEqual(first_call_args[1], args_list)
+ # pylint: disable=protected-access, no-member
+ def testCleanupSSVncviwer(self):
+ """test cleanup ssvnc viewer."""
+ fake_vnc_port = 9999
+ fake_ss_vncviewer_pattern = utils._SSVNC_VIEWER_PATTERN % {
+ "vnc_port": fake_vnc_port}
+ self.Patch(utils, "IsCommandRunning", return_value=True)
+ self.Patch(subprocess, "check_call", return_value=True)
+ utils.CleanupSSVncviewer(fake_vnc_port)
+ subprocess.check_call.assert_called_with(["pkill", "-9", "-f", fake_ss_vncviewer_pattern])
+
+ subprocess.check_call.call_count = 0
+ self.Patch(utils, "IsCommandRunning", return_value=False)
+ utils.CleanupSSVncviewer(fake_vnc_port)
+ subprocess.check_call.assert_not_called()
+
if __name__ == "__main__":
unittest.main()
diff --git a/list/instance.py b/list/instance.py
index 8f912452..8e4d69a1 100644
--- a/list/instance.py
+++ b/list/instance.py
@@ -48,6 +48,7 @@ logger = logging.getLogger(__name__)
_ACLOUD_CVD_TEMP = os.path.join(tempfile.gettempdir(), "acloud_cvd_temp")
_CVD_RUNTIME_FOLDER_NAME = "cuttlefish_runtime"
+_CVD_STATUS_BIN = "cvd_status"
_MSG_UNABLE_TO_CALCULATE = "Unable to calculate"
_RE_GROUP_ADB = "local_adb_port"
_RE_GROUP_VNC = "local_vnc_port"
@@ -63,10 +64,21 @@ _RE_ZONE = re.compile(r".+/zones/(?P<zone>.+)$")
_LOCAL_ZONE = "local"
_FULL_NAME_STRING = ("device serial: %(device_serial)s (%(instance_name)s) "
"elapsed time: %(elapsed_time)s")
+_INDENT = " " * 3
LocalPorts = collections.namedtuple("LocalPorts", [constants.VNC_PORT,
constants.ADB_PORT])
+def GetDefaultCuttlefishConfig():
+ """Get the path of default cuttlefish instance config.
+
+ Return:
+ String, path of cf runtime config.
+ """
+ return os.path.join(os.path.expanduser("~"), _CVD_RUNTIME_FOLDER_NAME,
+ constants.CUTTLEFISH_CONFIG_FILE)
+
+
def GetLocalInstanceName(local_instance_id):
"""Get local cuttlefish instance name by instance id.
@@ -79,58 +91,70 @@ def GetLocalInstanceName(local_instance_id):
return "%s-%d" % (constants.LOCAL_INS_NAME, local_instance_id)
-def GetLocalInstanceHomeDir(local_instance_id):
- """Get local instance home dir accroding to instance id.
+def GetLocalInstanceConfig(local_instance_id):
+ """Get the path of instance config.
Args:
local_instance_id: Integer of instance id.
Return:
- String, path of instance home dir.
+ String, path of cf runtime config.
"""
- return os.path.join(_ACLOUD_CVD_TEMP,
- GetLocalInstanceName(local_instance_id))
+ cfg_path = os.path.join(GetLocalInstanceRuntimeDir(local_instance_id),
+ constants.CUTTLEFISH_CONFIG_FILE)
+ if os.path.isfile(cfg_path):
+ return cfg_path
+ return None
-def GetLocalInstanceRuntimeDir(local_instance_id):
- """Get instance runtime dir
-
- Args:
- local_instance_id: Integer of instance id.
+def GetAllLocalInstanceConfigs():
+ """Get the list of instance config.
Return:
- String, path of instance runtime dir.
+ List of instance config path.
"""
- return os.path.join(GetLocalInstanceHomeDir(local_instance_id),
- _CVD_RUNTIME_FOLDER_NAME)
+ cfg_list = []
+ # Check if any instance config is under home folder.
+ cfg_path = GetDefaultCuttlefishConfig()
+ if os.path.isfile(cfg_path):
+ cfg_list.append(cfg_path)
+
+ # Check if any instance config is under acloud cvd temp folder.
+ if os.path.exists(_ACLOUD_CVD_TEMP):
+ for ins_name in os.listdir(_ACLOUD_CVD_TEMP):
+ cfg_path = os.path.join(_ACLOUD_CVD_TEMP,
+ ins_name,
+ _CVD_RUNTIME_FOLDER_NAME,
+ constants.CUTTLEFISH_CONFIG_FILE)
+ if os.path.isfile(cfg_path):
+ cfg_list.append(cfg_path)
+ return cfg_list
-def GetCuttlefishRuntimeConfig(local_instance_id):
- """Get and parse cuttlefish_config.json.
+def GetLocalInstanceHomeDir(local_instance_id):
+ """Get local instance home dir according to instance id.
Args:
local_instance_id: Integer of instance id.
- Returns:
- A CvdRuntimeConfig instance.
+ Return:
+ String, path of instance home dir.
"""
- runtime_cf_config_path = os.path.join(GetLocalInstanceRuntimeDir(
- local_instance_id), constants.CUTTLEFISH_CONFIG_FILE)
- return cvd_runtime_config.CvdRuntimeConfig(runtime_cf_config_path)
+ return os.path.join(_ACLOUD_CVD_TEMP,
+ GetLocalInstanceName(local_instance_id))
-def GetLocalPortsbyInsId(local_instance_id):
- """Get vnc and adb port by local instance id.
+def GetLocalInstanceRuntimeDir(local_instance_id):
+ """Get instance runtime dir
Args:
- local_instance_id: local_instance_id: Integer of instance id.
+ local_instance_id: Integer of instance id.
- Returns:
- NamedTuple of (vnc_port, adb_port) used by local instance, both are
- integers.
+ Return:
+ String, path of instance runtime dir.
"""
- return LocalPorts(vnc_port=constants.CF_VNC_PORT + local_instance_id - 1,
- adb_port=constants.CF_ADB_PORT + local_instance_id - 1)
+ return os.path.join(GetLocalInstanceHomeDir(local_instance_id),
+ _CVD_RUNTIME_FOLDER_NAME)
def _GetCurrentLocalTime():
@@ -193,31 +217,30 @@ class Instance(object):
def Summary(self):
"""Let's make it easy to see what this class is holding."""
- indent = " " * 3
representation = []
representation.append(" name: %s" % self._name)
- representation.append("%s IP: %s" % (indent, self._ip))
- representation.append("%s create time: %s" % (indent, self._createtime))
- representation.append("%s elapse time: %s" % (indent, self._elapsed_time))
- representation.append("%s status: %s" % (indent, self._status))
- representation.append("%s avd type: %s" % (indent, self._avd_type))
- representation.append("%s display: %s" % (indent, self._display))
- representation.append("%s vnc: 127.0.0.1:%s" % (indent, self._vnc_port))
- representation.append("%s zone: %s" % (indent, self._zone))
-
- if self._adb_port:
+ representation.append("%s IP: %s" % (_INDENT, self._ip))
+ representation.append("%s create time: %s" % (_INDENT, self._createtime))
+ representation.append("%s elapse time: %s" % (_INDENT, self._elapsed_time))
+ representation.append("%s status: %s" % (_INDENT, self._status))
+ representation.append("%s avd type: %s" % (_INDENT, self._avd_type))
+ representation.append("%s display: %s" % (_INDENT, self._display))
+ representation.append("%s vnc: 127.0.0.1:%s" % (_INDENT, self._vnc_port))
+ representation.append("%s zone: %s" % (_INDENT, self._zone))
+
+ if self._adb_port and self._device_information:
representation.append("%s adb serial: 127.0.0.1:%s" %
- (indent, self._adb_port))
+ (_INDENT, self._adb_port))
representation.append("%s product: %s" % (
- indent, self._device_information["product"]))
+ _INDENT, self._device_information["product"]))
representation.append("%s model: %s" % (
- indent, self._device_information["model"]))
+ _INDENT, self._device_information["model"]))
representation.append("%s device: %s" % (
- indent, self._device_information["device"]))
+ _INDENT, self._device_information["device"]))
representation.append("%s transport_id: %s" % (
- indent, self._device_information["transport_id"]))
+ _INDENT, self._device_information["transport_id"]))
else:
- representation.append("%s adb serial: disconnected" % indent)
+ representation.append("%s adb serial: disconnected" % _INDENT)
return "\n".join(representation)
@@ -247,16 +270,6 @@ class Instance(object):
return self._display
@property
- def forwarding_adb_port(self):
- """Return the adb port."""
- return self._adb_port
-
- @property
- def forwarding_vnc_port(self):
- """Return the vnc port."""
- return self._vnc_port
-
- @property
def ssh_tunnel_is_connected(self):
"""Return the connect status."""
return self._ssh_tunnel_is_connected
@@ -299,25 +312,28 @@ class Instance(object):
class LocalInstance(Instance):
"""Class to store data of local cuttlefish instance."""
-
- def __init__(self, local_instance_id, cf_runtime_cfg):
+ def __init__(self, cf_config_path):
"""Initialize a localInstance object.
Args:
- local_instance_id: Integer of instance id.
- cf_runtime_cfg: A CvdRuntimeConfig instance.
+ cf_config_path: String, path to the cf runtime config.
"""
- display = _DISPLAY_STRING % {"x_res": cf_runtime_cfg.x_res,
- "y_res": cf_runtime_cfg.y_res,
- "dpi": cf_runtime_cfg.dpi}
+ self._cf_runtime_cfg = cvd_runtime_config.CvdRuntimeConfig(cf_config_path)
+ self._instance_dir = self._cf_runtime_cfg.instance_dir
+ self._virtual_disk_paths = self._cf_runtime_cfg.virtual_disk_paths
+ self._local_instance_id = int(self._cf_runtime_cfg.instance_id)
+
+ display = _DISPLAY_STRING % {"x_res": self._cf_runtime_cfg.x_res,
+ "y_res": self._cf_runtime_cfg.y_res,
+ "dpi": self._cf_runtime_cfg.dpi}
# TODO(143063678), there's no createtime info in
# cuttlefish_config.json so far.
- name = GetLocalInstanceName(local_instance_id)
+ name = GetLocalInstanceName(self._local_instance_id)
fullname = (_FULL_NAME_STRING %
- {"device_serial": "127.0.0.1:%d" % cf_runtime_cfg.adb_port,
+ {"device_serial": "127.0.0.1:%d" % self._cf_runtime_cfg.adb_port,
"instance_name": name,
"elapsed_time": None})
- adb_device = AdbTools(cf_runtime_cfg.adb_port)
+ adb_device = AdbTools(self._cf_runtime_cfg.adb_port)
device_information = None
if adb_device.IsAdbConnected():
device_information = adb_device.device_information
@@ -325,19 +341,102 @@ class LocalInstance(Instance):
super(LocalInstance, self).__init__(
name=name, fullname=fullname, display=display, ip="127.0.0.1",
status=constants.INS_STATUS_RUNNING,
- adb_port=cf_runtime_cfg.adb_port, vnc_port=cf_runtime_cfg.vnc_port,
+ adb_port=self._cf_runtime_cfg.adb_port,
+ vnc_port=self._cf_runtime_cfg.vnc_port,
createtime=None, elapsed_time=None, avd_type=constants.TYPE_CF,
is_local=True, device_information=device_information,
zone=_LOCAL_ZONE)
- # LocalInstance class properties
- self._instance_dir = cf_runtime_cfg.instance_dir
+ def Summary(self):
+ """Return the string that this class is holding."""
+ instance_home = "%s instance home: %s" % (_INDENT, self._instance_dir)
+ return "%s\n%s" % (super(LocalInstance, self).Summary(), instance_home)
+
+ def CvdStatus(self):
+ """check if local instance is active.
+
+ Execute cvd_status cmd to check if it exit without error.
+
+ Returns
+ True if instance is active.
+ """
+ cvd_env = os.environ.copy()
+ cvd_env[constants.ENV_CUTTLEFISH_CONFIG_FILE] = self._cf_runtime_cfg.config_path
+ cvd_env[constants.ENV_CVD_HOME] = GetLocalInstanceHomeDir(self._local_instance_id)
+ cvd_env[constants.ENV_CUTTLEFISH_INSTANCE] = str(self._local_instance_id)
+ try:
+ cvd_status_cmd = os.path.join(self._cf_runtime_cfg.cvd_tools_path,
+ _CVD_STATUS_BIN)
+ logger.debug("Running cmd[%s] to check cvd status.", cvd_status_cmd)
+ process = subprocess.Popen(cvd_status_cmd,
+ stdin=None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ env=cvd_env)
+ stdout, _ = process.communicate()
+ if process.returncode != 0:
+ if stdout:
+ logger.debug("Local instance[%s] is not active: %s",
+ self.name, stdout.strip())
+ return False
+ return True
+ except subprocess.CalledProcessError as cpe:
+ logger.error("Failed to run cvd_status: %s", cpe.output)
+ return False
+
+ def Delete(self):
+ """Execute stop_cvd to stop local cuttlefish instance.
+
+ - We should get the same host tool used to launch cvd to delete instance
+ , So get stop_cvd bin from the cvd runtime config.
+ - Add CUTTLEFISH_CONFIG_FILE env variable to tell stop_cvd which cvd
+ need to be deleted.
+ - Stop adb since local instance use the fixed adb port and could be
+ reused again soon.
+ """
+ stop_cvd_cmd = os.path.join(self.cf_runtime_cfg.cvd_tools_path,
+ constants.CMD_STOP_CVD)
+ logger.debug("Running cmd[%s] to delete local cvd", stop_cvd_cmd)
+ with open(os.devnull, "w") as dev_null:
+ cvd_env = os.environ.copy()
+ if self.instance_dir:
+ cvd_env[constants.ENV_CUTTLEFISH_CONFIG_FILE] = self._cf_runtime_cfg.config_path
+ cvd_env[constants.ENV_CVD_HOME] = GetLocalInstanceHomeDir(
+ self._local_instance_id)
+ cvd_env[constants.ENV_CUTTLEFISH_INSTANCE] = str(self._local_instance_id)
+ else:
+ logger.error("instance_dir is null!! instance[%d] might not be"
+ " deleted", self._local_instance_id)
+ subprocess.check_call(
+ utils.AddUserGroupsToCmd(stop_cvd_cmd,
+ constants.LIST_CF_USER_GROUPS),
+ stderr=dev_null, stdout=dev_null, shell=True, env=cvd_env)
+
+ adb_cmd = AdbTools(self.adb_port)
+ # When relaunch a local instance, we need to pass in retry=True to make
+ # sure adb device is completely gone since it will use the same adb port
+ adb_cmd.DisconnectAdb(retry=True)
@property
def instance_dir(self):
"""Return _instance_dir."""
return self._instance_dir
+ @property
+ def instance_id(self):
+ """Return _local_instance_id."""
+ return self._local_instance_id
+
+ @property
+ def virtual_disk_paths(self):
+ """Return virtual_disk_paths"""
+ return self._virtual_disk_paths
+
+ @property
+ def cf_runtime_cfg(self):
+ """Return _cf_runtime_cfg"""
+ return self._cf_runtime_cfg
+
class LocalGoldfishInstance(Instance):
"""Class to store data of local goldfish instance."""
diff --git a/list/instance_test.py b/list/instance_test.py
index 9832c808..a2c79224 100644
--- a/list/instance_test.py
+++ b/list/instance_test.py
@@ -27,6 +27,7 @@ import dateutil.parser
import dateutil.tz
from acloud.internal import constants
+from acloud.internal.lib import cvd_runtime_config
from acloud.internal.lib import driver_test_lib
from acloud.internal.lib.adb_tools import AdbTools
from acloud.list import instance
@@ -62,15 +63,18 @@ class InstanceTest(driver_test_lib.BaseDriverTest):
""""Test get local instance info from launch_cvd process."""
self.Patch(subprocess, "check_output", return_value=self.PS_LAUNCH_CVD)
cf_config = mock.MagicMock(
+ instance_id=2,
x_res=1080,
y_res=1920,
dpi=480,
instance_dir="fake_instance_dir",
adb_port=6521,
- vnc_port=6445
+ vnc_port=6445,
+ adb_ip_port="127.0.0.1:6521",
)
-
- local_instance = instance.LocalInstance(2, cf_config)
+ self.Patch(cvd_runtime_config, "CvdRuntimeConfig",
+ return_value=cf_config)
+ local_instance = instance.LocalInstance(cf_config)
self.assertEqual(constants.LOCAL_INS_NAME + "-2", local_instance.name)
self.assertEqual(True, local_instance.islocal)
@@ -80,8 +84,8 @@ class InstanceTest(driver_test_lib.BaseDriverTest):
constants.LOCAL_INS_NAME + "-2",
"None"))
self.assertEqual(expected_full_name, local_instance.fullname)
- self.assertEqual(6521, local_instance.forwarding_adb_port)
- self.assertEqual(6445, local_instance.forwarding_vnc_port)
+ self.assertEqual(6521, local_instance.adb_port)
+ self.assertEqual(6445, local_instance.vnc_port)
@mock.patch("acloud.list.instance.tempfile")
@mock.patch("acloud.list.instance.AdbTools")
@@ -214,8 +218,8 @@ class InstanceTest(driver_test_lib.BaseDriverTest):
# test ssh_tunnel_is_connected will be true if ssh tunnel connection is found
instance_info = instance.RemoteInstance(self.GCE_INSTANCE)
self.assertTrue(instance_info.ssh_tunnel_is_connected)
- self.assertEqual(instance_info.forwarding_adb_port, fake_adb)
- self.assertEqual(instance_info.forwarding_vnc_port, fake_vnc)
+ self.assertEqual(instance_info.adb_port, fake_adb)
+ self.assertEqual(instance_info.vnc_port, fake_vnc)
self.assertEqual("1.1.1.1", instance_info.ip)
self.assertEqual("fake_status", instance_info.status)
self.assertEqual("fake_type", instance_info.avd_type)
diff --git a/list/list.py b/list/list.py
index 6afaf0af..febd6f39 100644
--- a/list/list.py
+++ b/list/list.py
@@ -20,8 +20,7 @@ of an Android Virtual Device.
from __future__ import print_function
import getpass
import logging
-import re
-import subprocess
+import os
from acloud import errors
from acloud.internal import constants
@@ -35,28 +34,6 @@ from acloud.public import config
logger = logging.getLogger(__name__)
_COMMAND_PS_LAUNCH_CVD = ["ps", "-wweo", "lstart,cmd"]
-_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):
@@ -144,19 +121,39 @@ def _GetLocalCuttlefishInstances():
Returns:
instance_list: List of local instances.
"""
- local_cvd_ids = GetActiveCVDIds()
local_instance_list = []
- for cvd_id in local_cvd_ids:
- try:
- cf_runtime_cfg = instance.GetCuttlefishRuntimeConfig(cvd_id)
- local_instance_list.append(
- instance.LocalInstance(cvd_id, cf_runtime_cfg))
- except errors.ConfigError:
- logger.error("Instance[id:%d] dir not found!", cvd_id)
-
+ for cf_runtime_config_path in instance.GetAllLocalInstanceConfigs():
+ ins = instance.LocalInstance(cf_runtime_config_path)
+ if ins.CvdStatus():
+ local_instance_list.append(ins)
+ else:
+ logger.info("cvd runtime config found but instance is not active:%s"
+ , cf_runtime_config_path)
return local_instance_list
+def GetActiveCVD(local_instance_id):
+ """Check if the local AVD with specific instance id is running
+
+ Args:
+ local_instance_id: Integer of instance id.
+
+ Return:
+ LocalInstance object.
+ """
+ cfg_path = instance.GetLocalInstanceConfig(local_instance_id)
+ if cfg_path:
+ ins = instance.LocalInstance(cfg_path)
+ if ins.CvdStatus():
+ return ins
+ cfg_path = instance.GetDefaultCuttlefishConfig()
+ if local_instance_id == 1 and os.path.isfile(cfg_path):
+ ins = instance.LocalInstance(cfg_path)
+ if ins.CvdStatus():
+ return ins
+ return None
+
+
def GetLocalInstances():
"""Look for local cuttleifsh and goldfish instances.
@@ -308,7 +305,7 @@ def FilterInstancesByAdbPort(instances, adb_port):
"""
all_instance_info = []
for instance_object in instances:
- if instance_object.forwarding_adb_port == adb_port:
+ if instance_object.adb_port == adb_port:
return [instance_object]
all_instance_info.append(instance_object.fullname)
diff --git a/list/list_test.py b/list/list_test.py
index 12f7ce45..a4b466c0 100644
--- a/list/list_test.py
+++ b/list/list_test.py
@@ -12,12 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for list."""
-import subprocess
+
import unittest
import mock
from acloud import errors
+from acloud.internal.lib import cvd_runtime_config
from acloud.internal.lib import driver_test_lib
from acloud.internal.lib import utils
from acloud.list import list as list_instance
@@ -91,7 +92,7 @@ class ListTest(driver_test_lib.BaseDriverTest):
def testFilterInstancesByAdbPort(self):
"""test FilterInstancesByAdbPort."""
alive_instance1 = InstanceObject("alive_instance1")
- alive_instance1.forwarding_adb_port = 1111
+ alive_instance1.adb_port = 1111
alive_instance1.fullname = "device serial: 127.0.0.1:1111 alive_instance1"
expected_instance = [alive_instance1]
# Test to find instance by adb port number.
@@ -105,17 +106,24 @@ class ListTest(driver_test_lib.BaseDriverTest):
# pylint: disable=protected-access
def testGetLocalCuttlefishInstances(self):
"""test _GetLocalCuttlefishInstances."""
- cf_config = mock.MagicMock()
-
# Test getting two instance case
- self.Patch(list_instance, "GetActiveCVDIds", return_value=[1, 2])
- self.Patch(instance, "GetCuttlefishRuntimeConfig", return_value=cf_config)
+ self.Patch(instance, "GetAllLocalInstanceConfigs",
+ return_value=["fake_path1", "fake_path2"])
self.Patch(instance, "GetLocalInstanceRuntimeDir")
- self.Patch(instance, "LocalInstance")
+
+ local_ins = mock.MagicMock()
+ local_ins.CvdStatus.return_value = True
+ self.Patch(instance, "LocalInstance", return_value=local_ins)
ins_list = list_instance._GetLocalCuttlefishInstances()
self.assertEqual(2, len(ins_list))
+ local_ins = mock.MagicMock()
+ local_ins.CvdStatus.return_value = False
+ self.Patch(instance, "LocalInstance", return_value=local_ins)
+ ins_list = list_instance._GetLocalCuttlefishInstances()
+ self.assertEqual(0, len(ins_list))
+
# pylint: disable=no-member
def testPrintInstancesDetails(self):
"""test PrintInstancesDetails."""
@@ -125,10 +133,13 @@ class ListTest(driver_test_lib.BaseDriverTest):
x_res=728,
y_res=728,
dpi=240,
- instance_dir="fake_dir"
+ instance_dir="fake_dir",
+ adb_ip_port="127.0.0.1:6520"
)
+ self.Patch(cvd_runtime_config, "CvdRuntimeConfig",
+ return_value=cf_config)
- ins = instance.LocalInstance(1, cf_config)
+ ins = instance.LocalInstance("fake_cf_path")
list_instance.PrintInstancesDetails([ins], verbose=True)
instance.Instance.Summary.assert_called_once()
@@ -141,15 +152,6 @@ class ListTest(driver_test_lib.BaseDriverTest):
list_instance.PrintInstancesDetails([], verbose=True)
instance.Instance.Summary.assert_not_called()
- # pylint: disable=no-member
- def testGetActiveCVDIds(self):
- """test GetActiveCVDIds."""
- # Test getting two local devices
- adb_output = "127.0.0.1:6520 device\n127.0.0.1:6521 device"
- expected_result = [1, 2]
- self.Patch(subprocess, "check_output", return_value=adb_output)
- self.assertEqual(list_instance.GetActiveCVDIds(), expected_result)
-
if __name__ == "__main__":
unittest.main()
diff --git a/public/report.py b/public/report.py
index 5f5a07a4..dd95c4e4 100755
--- a/public/report.py
+++ b/public/report.py
@@ -150,7 +150,7 @@ class Report(object):
"requested to update to a status with lower severity %s, ignored.",
self.status, status)
- def AddDevice(self, instance_name, ip_address, adb_port, vnc_port=None,
+ def AddDevice(self, instance_name, ip_address, adb_port, vnc_port,
key="devices"):
"""Add a record of a device.
@@ -161,9 +161,13 @@ class Report(object):
vnc_port: An integer.
key: A string, the data entry where the record is added.
"""
- device = {constants.INSTANCE_NAME: instance_name,
- constants.IP: "%s:%d" % (ip_address, adb_port),
- constants.ADB_PORT: adb_port}
+ device = {constants.INSTANCE_NAME: instance_name}
+ if adb_port:
+ device[constants.ADB_PORT] = adb_port
+ device[constants.IP] = "%s:%d" % (ip_address, adb_port)
+ else:
+ device[constants.IP] = ip_address
+
if vnc_port:
device[constants.VNC_PORT] = vnc_port
self.AddData(key=key, value=device)
diff --git a/public/report_test.py b/public/report_test.py
index 772c9875..d3987c80 100644
--- a/public/report_test.py
+++ b/public/report_test.py
@@ -63,12 +63,13 @@ class ReportTest(unittest.TestCase):
def testAddDevice(self):
"""test AddDevice."""
test_report = report.Report("create")
- test_report.AddDevice("instance_1", "127.0.0.1", 6520)
+ test_report.AddDevice("instance_1", "127.0.0.1", 6520, 6444)
expected = {
"devices": [{
"instance_name": "instance_1",
"ip": "127.0.0.1:6520",
- "adb_port": 6520
+ "adb_port": 6520,
+ "vnc_port": 6444
}]
}
self.assertEqual(test_report.data, expected)
diff --git a/reconnect/reconnect.py b/reconnect/reconnect.py
index 1be95676..d354b4e2 100644
--- a/reconnect/reconnect.py
+++ b/reconnect/reconnect.py
@@ -22,7 +22,6 @@ Reconnect will:
import re
from acloud import errors
-from acloud.delete import delete
from acloud.internal import constants
from acloud.internal.lib import auth
from acloud.internal.lib import android_compute_client
@@ -51,7 +50,7 @@ def StartVnc(vnc_port, display):
vnc_started_pattern = _VNC_STARTED_PATTERN % {"vnc_port": vnc_port}
if not utils.IsCommandRunning(vnc_started_pattern):
#clean old disconnect ssvnc viewer.
- delete.CleanupSSVncviewer(vnc_port)
+ utils.CleanupSSVncviewer(vnc_port)
match = _RE_DISPLAY.match(display)
if match:
@@ -110,9 +109,9 @@ def ReconnectInstance(ssh_private_key_path,
"unknown avd type: %s" %
(instance.name, instance.avd_type))
- adb_cmd = AdbTools(instance.forwarding_adb_port)
- vnc_port = instance.forwarding_vnc_port
- adb_port = instance.forwarding_adb_port
+ adb_cmd = AdbTools(instance.adb_port)
+ vnc_port = instance.vnc_port
+ adb_port = instance.adb_port
# ssh tunnel is up but device is disconnected on adb
if instance.ssh_tunnel_is_connected and not adb_cmd.IsAdbConnectionAlive():
adb_cmd.DisconnectAdb()
diff --git a/reconnect/reconnect_test.py b/reconnect/reconnect_test.py
index 493067b5..70ea801b 100644
--- a/reconnect/reconnect_test.py
+++ b/reconnect/reconnect_test.py
@@ -42,7 +42,7 @@ class ReconnectTest(driver_test_lib.BaseDriverTest):
instance_object = mock.MagicMock()
instance_object.ip = "1.1.1.1"
instance_object.islocal = False
- instance_object.forwarding_adb_port = "8686"
+ instance_object.adb_port = "8686"
instance_object.avd_type = "cuttlefish"
self.Patch(subprocess, "check_call", return_value=True)
self.Patch(utils, "LaunchVncClient")
@@ -52,7 +52,7 @@ class ReconnectTest(driver_test_lib.BaseDriverTest):
self.Patch(utils, "IsCommandRunning", return_value=False)
#test ssh tunnel not connected, remote instance.
- instance_object.forwarding_vnc_port = 6666
+ instance_object.vnc_port = 6666
instance_object.display = ""
utils.AutoConnect.call_count = 0
reconnect.ReconnectInstance(ssh_private_key_path, instance_object, fake_report)
@@ -69,7 +69,7 @@ class ReconnectTest(driver_test_lib.BaseDriverTest):
instance_object.ssh_tunnel_is_connected = False
instance_object.display = ""
utils.AutoConnect.call_count = 0
- instance_object.forwarding_vnc_port = 5555
+ instance_object.vnc_port = 5555
extra_args_ssh_tunnel = None
self.Patch(utils, "AutoConnect",
return_value=ForwardedPorts(vnc_port=11111, adb_port=22222))
@@ -100,7 +100,7 @@ class ReconnectTest(driver_test_lib.BaseDriverTest):
#test reconnect local instance.
instance_object.islocal = True
instance_object.display = ""
- instance_object.forwarding_vnc_port = 5555
+ instance_object.vnc_port = 5555
instance_object.ssh_tunnel_is_connected = False
utils.AutoConnect.call_count = 0
reconnect.ReconnectInstance(ssh_private_key_path,
@@ -115,8 +115,8 @@ class ReconnectTest(driver_test_lib.BaseDriverTest):
fake_report = mock.MagicMock()
instance_object = mock.MagicMock()
instance_object.ip = "1.1.1.1"
- instance_object.forwarding_vnc_port = 9999
- instance_object.forwarding_adb_port = "9999"
+ instance_object.vnc_port = 9999
+ instance_object.adb_port = "9999"
instance_object.islocal = False
instance_object.ssh_tunnel_is_connected = False
self.Patch(utils, "AutoConnect")