blob: f1c9bb52011521869c19754e70c64c0d174dd44d [file] [log] [blame]
Kevin Cheng3ce4b452018-08-23 14:47:22 -07001#!/usr/bin/env python
2#
3# Copyright 2018 - The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16r"""LocalImageLocalInstance class.
17
18Create class that is responsible for creating a local instance AVD with a
19local image.
20"""
21
Sam Chiuafbc6582018-09-04 20:47:13 +080022from __future__ import print_function
23import logging
24import os
25import subprocess
herbertxue61007092018-10-10 11:56:57 +080026import sys
Sam Chiuafbc6582018-09-04 20:47:13 +080027
28from acloud import errors
Kevin Cheng3ce4b452018-08-23 14:47:22 -070029from acloud.create import base_avd_create
Sam Chiuafbc6582018-09-04 20:47:13 +080030from acloud.create import create_common
31from acloud.internal import constants
32from acloud.internal.lib import utils
Kevin Chengae7a49d2018-10-18 14:11:22 -070033from acloud.public import report
Sam Chiuafbc6582018-09-04 20:47:13 +080034
35logger = logging.getLogger(__name__)
36
37_BOOT_COMPLETE = "VIRTUAL_DEVICE_BOOT_COMPLETED"
Sam Chiuafbc6582018-09-04 20:47:13 +080038_CMD_LAUNCH_CVD_ARGS = (" --daemon --cpus %s --x_res %s --y_res %s --dpi %s "
39 "--memory_mb %s --blank_data_image_mb %s "
40 "--data_policy always_create "
41 "--system_image_dir %s "
Kevin Chengc992c342018-11-06 00:45:53 -080042 "--vnc_server_port %s")
Kevin Cheng2aa41da2018-10-11 15:00:48 -070043_CONFIRM_RELAUNCH = ("\nCuttlefish AVD is already running. \n"
Kevin Chengae7a49d2018-10-18 14:11:22 -070044 "Enter 'y' to terminate current instance and launch a new "
45 "instance, enter anything else to exit out [y]: ")
Sam Chiuafbc6582018-09-04 20:47:13 +080046_ENV_ANDROID_HOST_OUT = "ANDROID_HOST_OUT"
Kevin Cheng3ce4b452018-08-23 14:47:22 -070047
48
49class LocalImageLocalInstance(base_avd_create.BaseAVDCreate):
50 """Create class for a local image local instance AVD."""
51
Kevin Chengae7a49d2018-10-18 14:11:22 -070052 @utils.TimeExecute(function_description="Total time: ",
53 print_before_call=False, print_status=False)
54 def _CreateAVD(self, avd_spec):
Kevin Cheng3ce4b452018-08-23 14:47:22 -070055 """Create the AVD.
56
57 Args:
58 avd_spec: AVDSpec object that tells us what we're going to create.
59 """
Sam Chiu395b2322018-12-03 20:57:02 +080060 self.PrintDisclaimer()
Sam Chiuafbc6582018-09-04 20:47:13 +080061 local_image_path, launch_cvd_path = self.GetImageArtifactsPath(avd_spec)
62
63 cmd = self.PrepareLaunchCVDCmd(launch_cvd_path,
64 avd_spec.hw_property,
Kevin Chengc992c342018-11-06 00:45:53 -080065 local_image_path)
Sam Chiuafbc6582018-09-04 20:47:13 +080066 try:
herbertxue61007092018-10-10 11:56:57 +080067 self.CheckLaunchCVD(cmd, os.path.dirname(launch_cvd_path))
Sam Chiuafbc6582018-09-04 20:47:13 +080068 except errors.LaunchCVDFail as launch_error:
69 raise launch_error
70
Sam Chiu56c58892018-10-25 09:53:19 +080071 result_report = report.Report(constants.LOCAL_INS_NAME)
Kevin Chengae7a49d2018-10-18 14:11:22 -070072 result_report.SetStatus(report.Status.SUCCESS)
73 result_report.AddData(key="devices",
Sam Chiu7a477f52018-10-22 11:20:36 +080074 value={"adb_port": constants.DEFAULT_ADB_PORT,
75 constants.VNC_PORT: constants.DEFAULT_VNC_PORT})
76 # Launch vnc client if we're auto-connecting.
77 if avd_spec.autoconnect:
78 utils.LaunchVNCFromReport(result_report, avd_spec)
Kevin Chengae7a49d2018-10-18 14:11:22 -070079 return result_report
Sam Chiuafbc6582018-09-04 20:47:13 +080080
81 @staticmethod
82 def GetImageArtifactsPath(avd_spec):
83 """Get image artifacts path.
84
85 This method will check if local image and launch_cvd are exist and
86 return the tuple path where they are located respectively.
87 For remote image, RemoteImageLocalInstance will override this method and
88 return the artifacts path which is extracted and downloaded from remote.
89
90 Args:
91 avd_spec: AVDSpec object that tells us what we're going to create.
92
93 Returns:
94 Tuple of (local image file, launch_cvd package) paths.
95 """
96 try:
97 # Check if local image is exist.
98 create_common.VerifyLocalImageArtifactsExist(
99 avd_spec.local_image_dir)
100
101 # TODO(b/117306227): help user to build out images and host package if
102 # anything needed is not found.
103 except errors.GetLocalImageError as imgerror:
104 logger.error(imgerror.message)
105 raise imgerror
106
107 # Check if launch_cvd is exist.
108 launch_cvd_path = os.path.join(
herbertxue61007092018-10-10 11:56:57 +0800109 os.environ.get(_ENV_ANDROID_HOST_OUT), "bin", constants.CMD_LAUNCH_CVD)
Sam Chiuafbc6582018-09-04 20:47:13 +0800110 if not os.path.exists(launch_cvd_path):
111 raise errors.GetCvdLocalHostPackageError(
112 "No launch_cvd found. Please run \"m launch_cvd\" first")
113
114 return avd_spec.local_image_dir, launch_cvd_path
115
116 @staticmethod
herbertxue07293a32018-11-05 20:40:11 +0800117 def PrepareLaunchCVDCmd(launch_cvd_path, hw_property, system_image_dir):
Kevin Cheng2aa41da2018-10-11 15:00:48 -0700118 """Prepare launch_cvd command.
119
120 Create the launch_cvd commands with all the required args and add
121 in the user groups to it if necessary.
122
123 Args:
Sam Chiuafbc6582018-09-04 20:47:13 +0800124 launch_cvd_path: String of launch_cvd path.
125 hw_property: dict object of hw property.
126 system_image_dir: String of local images path.
Sam Chiuafbc6582018-09-04 20:47:13 +0800127
128 Returns:
129 String, launch_cvd cmd.
130 """
131 launch_cvd_w_args = launch_cvd_path + _CMD_LAUNCH_CVD_ARGS % (
132 hw_property["cpu"], hw_property["x_res"], hw_property["y_res"],
133 hw_property["dpi"], hw_property["memory"], hw_property["disk"],
Kevin Chengc992c342018-11-06 00:45:53 -0800134 system_image_dir, constants.DEFAULT_VNC_PORT)
Sam Chiuafbc6582018-09-04 20:47:13 +0800135
herbertxue07293a32018-11-05 20:40:11 +0800136 launch_cmd = utils.AddUserGroupsToCmd(launch_cvd_w_args,
137 constants.LIST_CF_USER_GROUPS)
Kevin Cheng2aa41da2018-10-11 15:00:48 -0700138 logger.debug("launch_cvd cmd:\n %s", launch_cmd)
139 return launch_cmd
Sam Chiuafbc6582018-09-04 20:47:13 +0800140
herbertxue07293a32018-11-05 20:40:11 +0800141 @staticmethod
herbertxue61007092018-10-10 11:56:57 +0800142 @utils.TimeExecute(function_description="Waiting for AVD(s) to boot up")
herbertxue07293a32018-11-05 20:40:11 +0800143 def CheckLaunchCVD(cmd, host_pack_dir):
Sam Chiuafbc6582018-09-04 20:47:13 +0800144 """Execute launch_cvd command and wait for boot up completed.
145
146 Args:
147 cmd: String, launch_cvd command.
herbertxue61007092018-10-10 11:56:57 +0800148 host_pack_dir: String of host package directory.
Sam Chiuafbc6582018-09-04 20:47:13 +0800149 """
Sam Chiuafbc6582018-09-04 20:47:13 +0800150 # Cuttlefish support launch single AVD at one time currently.
herbertxue07293a32018-11-05 20:40:11 +0800151 if utils.IsCommandRunning(constants.CMD_LAUNCH_CVD):
Sam Chiuafbc6582018-09-04 20:47:13 +0800152 logger.info("Cuttlefish AVD is already running.")
153 if utils.GetUserAnswerYes(_CONFIRM_RELAUNCH):
herbertxue07293a32018-11-05 20:40:11 +0800154 stop_cvd_cmd = os.path.join(host_pack_dir,
155 constants.CMD_STOP_CVD)
herbertxue61007092018-10-10 11:56:57 +0800156 with open(os.devnull, "w") as dev_null:
Kevin Cheng2aa41da2018-10-11 15:00:48 -0700157 subprocess.check_call(
herbertxue07293a32018-11-05 20:40:11 +0800158 utils.AddUserGroupsToCmd(
159 stop_cvd_cmd, constants.LIST_CF_USER_GROUPS),
Kevin Cheng2aa41da2018-10-11 15:00:48 -0700160 stderr=dev_null, stdout=dev_null, shell=True)
herbertxue61007092018-10-10 11:56:57 +0800161 else:
162 print("Exiting out")
163 sys.exit()
Sam Chiuafbc6582018-09-04 20:47:13 +0800164
Sam Chiuf6fc9fd2018-11-06 15:55:34 +0800165 try:
166 # Check the result of launch_cvd command.
167 # An exit code of 0 is equivalent to VIRTUAL_DEVICE_BOOT_COMPLETED
168 logger.debug(subprocess.check_output(cmd, shell=True,
169 stderr=subprocess.STDOUT))
170 except subprocess.CalledProcessError as error:
Sam Chiuafbc6582018-09-04 20:47:13 +0800171 raise errors.LaunchCVDFail(
Sam Chiuf6fc9fd2018-11-06 15:55:34 +0800172 "Can't launch cuttlefish AVD.%s. \nFor more detail: "
173 "~/cuttlefish_runtime/launcher.log" % error.message)
Sam Chiu395b2322018-12-03 20:57:02 +0800174
175 @staticmethod
176 def PrintDisclaimer():
177 """Print Disclaimer."""
178 utils.PrintColorString(
179 "(Disclaimer: Local cuttlefish instance is not a fully supported\n"
180 "runtime configuration, fixing breakages is on a best effort SLO.)\n",
181 utils.TextColors.WARNING)