Merge "Make delete a little bit handier."
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..98bbce6
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+#
+# Copyright 2018 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+$(call dist-for-goals,droidcore,$(HOST_OUT_EXECUTABLES)/acloud)
diff --git a/create/local_image_local_instance.py b/create/local_image_local_instance.py
index b9c9a8d..a47606b 100644
--- a/create/local_image_local_instance.py
+++ b/create/local_image_local_instance.py
@@ -23,6 +23,7 @@
import logging
import os
import subprocess
+import sys
import time
from acloud import errors
@@ -35,7 +36,6 @@
logger = logging.getLogger(__name__)
_BOOT_COMPLETE = "VIRTUAL_DEVICE_BOOT_COMPLETED"
-_CMD_LAUNCH_CVD = "launch_cvd"
# TODO(b/117366819): Currently --serial_number is not working.
_CMD_LAUNCH_CVD_ARGS = (" --daemon --cpus %s --x_res %s --y_res %s --dpi %s "
"--memory_mb %s --blank_data_image_mb %s "
@@ -72,7 +72,7 @@
local_image_path,
avd_spec.flavor)
try:
- self.CheckLaunchCVD(cmd)
+ self.CheckLaunchCVD(cmd, os.path.dirname(launch_cvd_path))
except errors.LaunchCVDFail as launch_error:
raise launch_error
@@ -117,7 +117,7 @@
# Check if launch_cvd is exist.
launch_cvd_path = os.path.join(
- os.environ.get(_ENV_ANDROID_HOST_OUT), "bin", _CMD_LAUNCH_CVD)
+ os.environ.get(_ENV_ANDROID_HOST_OUT), "bin", constants.CMD_LAUNCH_CVD)
if not os.path.exists(launch_cvd_path):
raise errors.GetCvdLocalHostPackageError(
"No launch_cvd found. Please run \"m launch_cvd\" first")
@@ -177,28 +177,26 @@
logger.debug("launch_cvd cmd:\n %s", combined_launch_cmd)
return combined_launch_cmd
- def CheckLaunchCVD(self, cmd):
+ @utils.TimeExecute(function_description="Waiting for AVD(s) to boot up")
+ def CheckLaunchCVD(self, cmd, host_pack_dir):
"""Execute launch_cvd command and wait for boot up completed.
Args:
cmd: String, launch_cvd command.
+ host_pack_dir: String of host package directory.
"""
- start = time.time()
-
# Cuttlefish support launch single AVD at one time currently.
if self._IsLaunchCVDInUse():
logger.info("Cuttlefish AVD is already running.")
if utils.GetUserAnswerYes(_CONFIRM_RELAUNCH):
- stop_cvd_cmd = os.path.join(os.environ.get(_ENV_ANDROID_HOST_OUT),
- "bin", _CMD_STOP_CVD)
- subprocess.check_output(stop_cvd_cmd)
- else:
- print("Only 1 cuttlefish AVD at a time, "
- "please stop the current AVD via #acloud delete")
- return
+ stop_cvd_cmd = os.path.join(host_pack_dir, _CMD_STOP_CVD)
+ with open(os.devnull, "w") as dev_null:
+ subprocess.check_call(stop_cvd_cmd, stderr=dev_null,
+ stdout=dev_null)
- utils.PrintColorString("Waiting for AVD to boot... ",
- utils.TextColors.WARNING, end="")
+ else:
+ print("Exiting out")
+ sys.exit()
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
@@ -208,13 +206,10 @@
logger.debug(line.strip())
# cvd is still running and got boot complete.
if _BOOT_COMPLETE in line:
- utils.PrintColorString("OK! (%ds)" % (time.time() - start),
- utils.TextColors.OKGREEN)
boot_complete = True
break
if not boot_complete:
- utils.PrintColorString("Fail!", utils.TextColors.WARNING)
raise errors.LaunchCVDFail(
"Can't launch cuttlefish AVD. No %s found" % _BOOT_COMPLETE)
@@ -226,7 +221,9 @@
Boolean, True if launch_cvd is running. False otherwise.
"""
try:
- subprocess.check_output([_CMD_PGREP, _CMD_LAUNCH_CVD])
+ with open(os.devnull, "w") as dev_null:
+ subprocess.check_call([_CMD_PGREP, constants.CMD_LAUNCH_CVD],
+ stderr=dev_null, stdout=dev_null)
return True
except subprocess.CalledProcessError:
# launch_cvd process is not in use.
diff --git a/create/local_image_local_instance_test.py b/create/local_image_local_instance_test.py
index 4544f6c..f29fd90 100644
--- a/create/local_image_local_instance_test.py
+++ b/create/local_image_local_instance_test.py
@@ -45,8 +45,7 @@
constants.LIST_CF_USER_GROUPS = ["group1", "group2"]
launch_cmd = self.local_image_local_instance.PrepareLaunchCVDCmd(
- local_image_local_instance._CMD_LAUNCH_CVD,
- hw_property, "fake_image_dir", "flavor")
+ constants.CMD_LAUNCH_CVD, hw_property, "fake_image_dir", "flavor")
self.assertEqual(launch_cmd, self.LAUNCH_CVD_CMD)
diff --git a/create/remote_image_local_instance.py b/create/remote_image_local_instance.py
index 6d85287..3ec8e2a 100644
--- a/create/remote_image_local_instance.py
+++ b/create/remote_image_local_instance.py
@@ -25,7 +25,7 @@
import tempfile
from acloud import errors
-from acloud.create import base_avd_create
+from acloud.create import local_image_local_instance
from acloud.internal import constants
from acloud.internal.lib import android_build_client
from acloud.internal.lib import auth
@@ -50,26 +50,36 @@
logger = logging.getLogger(__name__)
-class RemoteImageLocalInstance(base_avd_create.BaseAVDCreate):
- """Create class for a remote image local instance AVD."""
+class RemoteImageLocalInstance(local_image_local_instance.LocalImageLocalInstance):
+ """Create class for a remote image local instance AVD.
- # pylint: disable=no-self-use
- def Create(self, avd_spec):
- """Create the AVD.
+ RemoteImageLocalInstance just defines logic in downloading the remote image
+ artifacts and leverages the existing logic to launch a local instance in
+ LocalImageLocalInstance.
+ """
+
+ @utils.TimeExecute(function_description="Downloading Android Build image")
+ def GetImageArtifactsPath(self, avd_spec):
+ """Download the image artifacts and return the paths to them.
Args:
avd_spec: AVDSpec object that tells us what we're going to create.
Raises:
errors.NoCuttlefishCommonInstalled: cuttlefish-common doesn't install.
+
+ Returns:
+ Tuple of (local image file, launch_cvd package) paths.
"""
- print("We will create a local instance AVD with a remote image: %s" %
- avd_spec)
if not setup_common.PackageInstalled("cuttlefish-common"):
raise errors.NoCuttlefishCommonInstalled(
"Package [cuttlefish-common] is not installed!\n"
"Please run 'acloud setup --host' to install.")
- self._DownloadAndProcessImageFiles(avd_spec)
+
+ image_dir = self._DownloadAndProcessImageFiles(avd_spec)
+ launch_cvd_path = os.path.join(image_dir, "bin", constants.CMD_LAUNCH_CVD)
+
+ return image_dir, launch_cvd_path
def _DownloadAndProcessImageFiles(self, avd_spec):
"""Download the CF image artifacts and process them.
@@ -79,20 +89,24 @@
Args:
avd_spec: AVDSpec object that tells us what we're going to create.
+
+ Returns:
+ extract_path: String, path to image folder.
"""
cfg = avd_spec.cfg
build_id = avd_spec.remote_image[constants.BUILD_ID]
build_target = avd_spec.remote_image[constants.BUILD_TARGET]
extract_path = os.path.join(_TEMP_IMAGE_FOLDER, build_id)
logger.debug("Extract path: %s", extract_path)
+ # TODO(b/117189191): If extract folder exists, check if the files are
+ # already downloaded and skip this step if they are.
if not os.path.exists(extract_path):
os.makedirs(extract_path)
+ self._DownloadRemoteImage(cfg, build_target, build_id, extract_path)
+ self._UnpackBootImage(extract_path)
+ self._AclCfImageFiles(extract_path)
- # TODO(b/117189191): Check if the files are already downloaded and
- # skip this step if they are.
- self._DownloadRemoteImage(cfg, build_target, build_id, extract_path)
- self._UnpackBootImage(extract_path)
- self._AclCfImageFiles(extract_path)
+ return extract_path
@staticmethod
def _DownloadRemoteImage(cfg, build_target, build_id, extract_path):
diff --git a/create/remote_image_local_instance_test.py b/create/remote_image_local_instance_test.py
index c35e7b2..e549ee5 100644
--- a/create/remote_image_local_instance_test.py
+++ b/create/remote_image_local_instance_test.py
@@ -46,18 +46,18 @@
self._extract_path = "/tmp/acloud_image_artifacts/cuttlefish/1234"
@mock.patch.object(RemoteImageLocalInstance, "_DownloadAndProcessImageFiles")
- def testCreate(self, mock_proc):
- """Test Create."""
+ def testGetImageArtifactsPath(self, mock_proc):
+ """Test get image artifacts path."""
avd_spec = mock.MagicMock()
# raise errors.NoCuttlefishCommonInstalled
self.Patch(setup_common, "PackageInstalled", return_value=False)
self.assertRaises(errors.NoCuttlefishCommonInstalled,
- self.RemoteImageLocalInstance.Create,
+ self.RemoteImageLocalInstance.GetImageArtifactsPath,
avd_spec)
# Valid _DownloadAndProcessImageFiles run.
self.Patch(setup_common, "PackageInstalled", return_value=True)
- self.RemoteImageLocalInstance.Create(avd_spec)
+ self.RemoteImageLocalInstance.GetImageArtifactsPath(avd_spec)
mock_proc.assert_called_once_with(avd_spec)
@mock.patch.object(RemoteImageLocalInstance, "_AclCfImageFiles")
@@ -68,7 +68,7 @@
avd_spec = mock.MagicMock()
avd_spec.cfg = mock.MagicMock()
avd_spec.remote_image = self._fake_remote_image
- self.Patch(os.path, "exists", return_value=True)
+ self.Patch(os.path, "exists", return_value=False)
self.RemoteImageLocalInstance._DownloadAndProcessImageFiles(avd_spec)
# To make sure each function execute once.
@@ -79,6 +79,8 @@
self._extract_path)
mock_unpack.assert_called_once_with(self._extract_path)
mock_acl.assert_called_once_with(self._extract_path)
+ # Clean extarcted folder after test completed.
+ os.rmdir(self._extract_path)
@mock.patch.object(utils, "TempDir")
@mock.patch.object(utils, "Decompress")
diff --git a/internal/constants.py b/internal/constants.py
index 2ca62f2..80d22d0 100755
--- a/internal/constants.py
+++ b/internal/constants.py
@@ -95,6 +95,7 @@
VNC_PORT = "vnc_port"
ADB_PORT = "adb_port"
+CMD_LAUNCH_CVD = "launch_cvd"
ENV_ANDROID_BUILD_TOP = "ANDROID_BUILD_TOP"
LOCALHOST_ADB_SERIAL = "127.0.0.1:%d"
diff --git a/public/actions/create_cuttlefish_action.py b/public/actions/create_cuttlefish_action.py
index 5c2eb2c..db48a43 100644
--- a/public/actions/create_cuttlefish_action.py
+++ b/public/actions/create_cuttlefish_action.py
@@ -92,7 +92,8 @@
# Create host instances for cuttlefish device. Currently one host instance
# has one cuttlefish device. In the future, these logics should be modified
# to support multiple cuttlefish devices per host instance.
- instance = self._compute_client.GenerateInstanceName(self._build_id)
+ instance = self._compute_client.GenerateInstanceName(
+ build_id=self._build_id, build_target=self._build_target)
# Create an instance from Stable Host Image
if self.RELEASE_BRANCH_SUFFIX in self._branch: