Merge commit '4cd68a39efe4b6f17a1a4132dd23a8b05863382b' into HEAD
Bug: 131249906
Test: None
Change-Id: I42ccc29dd05218e291a6cda3296cead52f9a7ff3
diff --git a/Android.bp b/Android.bp
index 41c2390..65b7b79 100644
--- a/Android.bp
+++ b/Android.bp
@@ -29,6 +29,8 @@
python_binary_host {
name: "acloud",
+ // Make acloud's built name to acloud-dev
+ stem: "acloud-dev",
defaults: ["acloud_default"],
main: "public/acloud_main.py",
srcs: [
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100644
index 0000000..135fa2d
--- /dev/null
+++ b/CleanSpec.mk
@@ -0,0 +1,47 @@
+# Copyright (C) 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# Discard the original naming "acloud", which is going to be replaced with "acloud-dev".
+$(call add-clean-step, rm -f $(HOST_OUT_EXECUTABLES)/acloud)
+$(call add-clean-step, rm -f $(SOONG_HOST_OUT_EXECUTABLES)/acloud)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/create/base_avd_create.py b/create/base_avd_create.py
index a837c03..109f0cf 100644
--- a/create/base_avd_create.py
+++ b/create/base_avd_create.py
@@ -25,22 +25,24 @@
class BaseAVDCreate(object):
"""Base class for all AVD intance creation classes."""
- def _CreateAVD(self, avd_spec):
+ def _CreateAVD(self, avd_spec, no_prompts):
"""Do the actual creation work, should be overridden by child classes.
Args:
avd_spec: AVDSpec object that tells us what we're going to create.
+ no_prompts: Boolean, True to skip all prompts.
"""
raise NotImplementedError
- def Create(self, avd_spec):
+ def Create(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.
"""
self.PrintAvdDetails(avd_spec)
- results = self._CreateAVD(avd_spec)
+ results = self._CreateAVD(avd_spec, no_prompts)
utils.PrintDeviceSummary(results)
return results
diff --git a/create/cheeps_remote_image_remote_instance.py b/create/cheeps_remote_image_remote_instance.py
index 86a11c8..ef3b260 100644
--- a/create/cheeps_remote_image_remote_instance.py
+++ b/create/cheeps_remote_image_remote_instance.py
@@ -33,11 +33,12 @@
@utils.TimeExecute(function_description="Total time: ",
print_before_call=False, print_status=False)
- def _CreateAVD(self, avd_spec):
+ 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.
@@ -60,7 +61,7 @@
# Launch vnc client if we're auto-connecting.
if avd_spec.autoconnect:
- utils.LaunchVNCFromReport(report, avd_spec)
+ utils.LaunchVNCFromReport(report, avd_spec, no_prompts)
return report
diff --git a/create/cheeps_remote_image_remote_instance_test.py b/create/cheeps_remote_image_remote_instance_test.py
index fac4d81..473838d 100644
--- a/create/cheeps_remote_image_remote_instance_test.py
+++ b/create/cheeps_remote_image_remote_instance_test.py
@@ -73,7 +73,7 @@
avd_spec.remote_image = {constants.BUILD_ID: self.ANDROID_BUILD_ID}
avd_spec.autoconnect = False
instance = cheeps_remote_image_remote_instance.CheepsRemoteImageRemoteInstance()
- report = instance.Create(avd_spec)
+ report = instance.Create(avd_spec, no_prompts=False)
# Verify
self.compute_client.CreateInstance.assert_called_with(
diff --git a/create/create.py b/create/create.py
index 623124d..011eb8b 100644
--- a/create/create.py
+++ b/create/create.py
@@ -204,6 +204,6 @@
spec.instance_type,
spec.image_source)
avd_creator = avd_creator_class()
- report = avd_creator.Create(spec)
+ report = avd_creator.Create(spec, args.no_prompt)
if report and args.report_file:
report.Dump(args.report_file)
diff --git a/create/create_args.py b/create/create_args.py
index 8273a08..638e2ea 100644
--- a/create/create_args.py
+++ b/create/create_args.py
@@ -184,6 +184,13 @@
dest="image_download_dir",
required=False,
help="Define remote image download directory, e.g. /usr/local/dl.")
+ create_parser.add_argument(
+ "--yes", "-y",
+ action="store_true",
+ dest="no_prompt",
+ required=False,
+ help=("Automatic yes to prompts. Assume 'yes' as answer to all prompts "
+ "and run non-interactively."))
# User should not specify --spec and --hw_property at the same time.
hw_spec_group = create_parser.add_mutually_exclusive_group()
hw_spec_group.add_argument(
diff --git a/create/gce_local_image_remote_instance.py b/create/gce_local_image_remote_instance.py
index 8c3395e..84c0030 100644
--- a/create/gce_local_image_remote_instance.py
+++ b/create/gce_local_image_remote_instance.py
@@ -36,11 +36,12 @@
@utils.TimeExecute(function_description="Total time: ",
print_before_call=False, print_status=False)
- def _CreateAVD(self, avd_spec):
+ 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.
@@ -58,7 +59,7 @@
# Launch vnc client if we're auto-connecting.
if avd_spec.autoconnect:
- utils.LaunchVNCFromReport(report, avd_spec)
+ utils.LaunchVNCFromReport(report, avd_spec, no_prompts)
return report
diff --git a/create/gce_remote_image_remote_instance.py b/create/gce_remote_image_remote_instance.py
index f61b882..70836a8 100644
--- a/create/gce_remote_image_remote_instance.py
+++ b/create/gce_remote_image_remote_instance.py
@@ -32,11 +32,12 @@
@utils.TimeExecute(function_description="Total time: ",
print_before_call=False, print_status=False)
- def _CreateAVD(self, avd_spec):
+ 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.
@@ -52,6 +53,6 @@
# Launch vnc client if we're auto-connecting.
if avd_spec.autoconnect:
- utils.LaunchVNCFromReport(report, avd_spec)
+ utils.LaunchVNCFromReport(report, avd_spec, no_prompts)
return report
diff --git a/create/local_image_local_instance.py b/create/local_image_local_instance.py
index 75ca0de..147cd3a 100644
--- a/create/local_image_local_instance.py
+++ b/create/local_image_local_instance.py
@@ -27,6 +27,7 @@
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.public import report
@@ -51,11 +52,12 @@
@utils.TimeExecute(function_description="Total time: ",
print_before_call=False, print_status=False)
- def _CreateAVD(self, avd_spec):
+ 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.
"""
# Running instances on local is not supported on all OS.
if not utils.IsSupportedPlatform(print_warning=True):
@@ -72,7 +74,7 @@
avd_spec.hw_property,
local_image_path)
try:
- self.CheckLaunchCVD(cmd, host_bins_path)
+ self.CheckLaunchCVD(cmd, host_bins_path, no_prompts)
except errors.LaunchCVDFail as launch_error:
raise launch_error
@@ -84,7 +86,7 @@
constants.VNC_PORT: constants.DEFAULT_VNC_PORT})
# Launch vnc client if we're auto-connecting.
if avd_spec.autoconnect:
- utils.LaunchVNCFromReport(result_report, avd_spec)
+ utils.LaunchVNCFromReport(result_report, avd_spec, no_prompts)
return result_report
@staticmethod
@@ -137,12 +139,13 @@
logger.debug("launch_cvd cmd:\n %s", launch_cmd)
return launch_cmd
- def CheckLaunchCVD(self, cmd, host_bins_path):
+ def CheckLaunchCVD(self, cmd, host_bins_path, no_prompts=False):
"""Execute launch_cvd command and wait for boot up completed.
Args:
cmd: String, launch_cvd command.
host_bins_path: String of host package directory.
+ no_prompts: Boolean, True to skip all prompts.
"""
# launch_cvd assumes host bins are in $ANDROID_HOST_OUT, let's overwrite
# it to wherever we're running launch_cvd since they could be in a
@@ -151,7 +154,7 @@
# Cuttlefish support launch single AVD at one time currently.
if utils.IsCommandRunning(constants.CMD_LAUNCH_CVD):
logger.info("Cuttlefish AVD is already running.")
- if utils.GetUserAnswerYes(_CONFIRM_RELAUNCH):
+ if no_prompts or utils.GetUserAnswerYes(_CONFIRM_RELAUNCH):
stop_cvd_cmd = os.path.join(host_bins_path,
"bin",
constants.CMD_STOP_CVD)
@@ -160,6 +163,10 @@
utils.AddUserGroupsToCmd(
stop_cvd_cmd, constants.LIST_CF_USER_GROUPS),
stderr=dev_null, stdout=dev_null, shell=True)
+
+ # Delete ssvnc viewer
+ delete.CleanupSSVncviewer(constants.CF_TARGET_VNC_PORT)
+
else:
print("Exiting out")
sys.exit()
diff --git a/create/local_image_remote_instance.py b/create/local_image_remote_instance.py
index 87b9ce6..4d247ac 100644
--- a/create/local_image_remote_instance.py
+++ b/create/local_image_remote_instance.py
@@ -275,11 +275,12 @@
@utils.TimeExecute(function_description="Total time: ",
print_before_call=False, print_status=False)
- def _CreateAVD(self, avd_spec):
+ 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.
"""
self.VerifyArtifactsExist(avd_spec.local_image_dir)
device_factory = RemoteInstanceDeviceFactory(
@@ -294,5 +295,5 @@
adb_port=constants.CF_TARGET_ADB_PORT)
# Launch vnc client if we're auto-connecting.
if avd_spec.autoconnect:
- utils.LaunchVNCFromReport(report, avd_spec)
+ utils.LaunchVNCFromReport(report, avd_spec, no_prompts)
return report
diff --git a/create/remote_image_remote_instance.py b/create/remote_image_remote_instance.py
index 68a8dde..18ec9f6 100644
--- a/create/remote_image_remote_instance.py
+++ b/create/remote_image_remote_instance.py
@@ -29,11 +29,12 @@
@utils.TimeExecute(function_description="Total time: ",
print_before_call=False, print_status=False)
- def _CreateAVD(self, avd_spec):
+ 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.
@@ -41,6 +42,6 @@
report = create_cuttlefish_action.CreateDevices(avd_spec=avd_spec)
# Launch vnc client if we're auto-connecting.
if avd_spec.autoconnect:
- utils.LaunchVNCFromReport(report, avd_spec)
+ utils.LaunchVNCFromReport(report, avd_spec, no_prompts)
return report
diff --git a/internal/lib/cheeps_compute_client.py b/internal/lib/cheeps_compute_client.py
index ffa62a3..5ef344a 100644
--- a/internal/lib/cheeps_compute_client.py
+++ b/internal/lib/cheeps_compute_client.py
@@ -37,6 +37,7 @@
import getpass
import logging
+from acloud import errors
from acloud.internal.lib import android_compute_client
from acloud.internal.lib import gcompute_client
@@ -49,7 +50,15 @@
"""
# This is the timeout for betty to start.
BOOT_TIMEOUT_SECS = 10*60
+ # This is printed by betty.sh.
BOOT_COMPLETED_MSG = "VM successfully started"
+ # systemd prints this if betty.sh returns nonzero status code.
+ BOOT_FAILED_MSG = "betty.service: Failed with result 'exit-code'"
+
+ def CheckBootFailure(self, serial_out, instance):
+ """Overrides superclass. Determines if there's a boot failure."""
+ if self.BOOT_FAILED_MSG in serial_out:
+ raise errors.DeviceBootError("Betty failed to start")
# pylint: disable=too-many-locals,arguments-differ
def CreateInstance(self, instance, image_name, image_project,
diff --git a/internal/lib/utils.py b/internal/lib/utils.py
index 11cfa4f..0f19078 100755
--- a/internal/lib/utils.py
+++ b/internal/lib/utils.py
@@ -880,30 +880,33 @@
return [answer_list[choice-start_index]]
-def LaunchVNCFromReport(report, avd_spec):
+def LaunchVNCFromReport(report, avd_spec, no_prompts=False):
"""Launch vnc client according to the instances report.
Args:
report: Report object, that stores and generates report.
avd_spec: AVDSpec object that tells us what we're going to create.
+ no_prompts: Boolean, True to skip all prompts.
"""
for device in report.data.get("devices", []):
if device.get(constants.VNC_PORT):
LaunchVncClient(device.get(constants.VNC_PORT),
avd_width=avd_spec.hw_property["x_res"],
- avd_height=avd_spec.hw_property["y_res"])
+ avd_height=avd_spec.hw_property["y_res"],
+ no_prompts=no_prompts)
else:
PrintColorString("No VNC port specified, skipping VNC startup.",
TextColors.FAIL)
def LaunchVncClient(port=constants.DEFAULT_VNC_PORT, avd_width=None,
- avd_height=None):
+ avd_height=None, no_prompts=False):
"""Launch ssvnc.
Args:
port: Integer, port number.
avd_width: String, the width of avd.
avd_height: String, the height of avd.
+ no_prompts: Boolean, True to skip all prompts.
"""
try:
os.environ[_ENV_DISPLAY]
@@ -913,7 +916,7 @@
return
if not find_executable(_VNC_BIN):
- if GetUserAnswerYes(_CONFIRM_CONTINUE):
+ if no_prompts or GetUserAnswerYes(_CONFIRM_CONTINUE):
try:
PrintColorString("Installing ssvnc vnc client... ", end="")
sys.stdout.flush()
diff --git a/list/instance.py b/list/instance.py
index d726839..4cc64a7 100644
--- a/list/instance.py
+++ b/list/instance.py
@@ -50,7 +50,7 @@
r"(.+%s)")
_RE_TIMEZONE = re.compile(r"^(?P<time>[0-9\-\.:T]*)(?P<timezone>[+-]\d+:\d+)$")
-_COMMAND_PS_LAUNCH_CVD = ["ps", "-eo", "lstart,cmd"]
+_COMMAND_PS_LAUNCH_CVD = ["ps", "-wweo", "lstart,cmd"]
_RE_LAUNCH_CVD = re.compile(r"(?P<date_str>^[^/]+)(.*launch_cvd --daemon )+"
r"((.*\s*-cpus\s)(?P<cpu>\d+))?"
r"((.*\s*-x_res\s)(?P<x_res>\d+))?"