1*800a58d9SAndroid Build Coastguard Worker#!/usr/bin/env python 2*800a58d9SAndroid Build Coastguard Worker# 3*800a58d9SAndroid Build Coastguard Worker# Copyright 2018 - The Android Open Source Project 4*800a58d9SAndroid Build Coastguard Worker# 5*800a58d9SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*800a58d9SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*800a58d9SAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*800a58d9SAndroid Build Coastguard Worker# 9*800a58d9SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*800a58d9SAndroid Build Coastguard Worker# 11*800a58d9SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*800a58d9SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*800a58d9SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*800a58d9SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*800a58d9SAndroid Build Coastguard Worker# limitations under the License. 16*800a58d9SAndroid Build Coastguard Workerr"""Create entry point. 17*800a58d9SAndroid Build Coastguard Worker 18*800a58d9SAndroid Build Coastguard WorkerCreate will handle all the logic related to creating a local/remote instance 19*800a58d9SAndroid Build Coastguard Workeran Android Virtual Device and the logic related to prepping the local/remote 20*800a58d9SAndroid Build Coastguard Workerimage artifacts. 21*800a58d9SAndroid Build Coastguard Worker""" 22*800a58d9SAndroid Build Coastguard Worker 23*800a58d9SAndroid Build Coastguard Workerfrom __future__ import print_function 24*800a58d9SAndroid Build Coastguard Worker 25*800a58d9SAndroid Build Coastguard Workerimport logging 26*800a58d9SAndroid Build Coastguard Workerimport os 27*800a58d9SAndroid Build Coastguard Workerimport subprocess 28*800a58d9SAndroid Build Coastguard Workerimport sys 29*800a58d9SAndroid Build Coastguard Worker 30*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors 31*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import avd_spec 32*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import cheeps_remote_image_remote_instance 33*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import gce_local_image_remote_instance 34*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import gce_remote_image_remote_instance 35*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import goldfish_local_image_local_instance 36*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import goldfish_remote_host 37*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import goldfish_remote_image_remote_instance 38*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import local_image_local_instance 39*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import local_image_remote_instance 40*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import local_image_remote_host 41*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import remote_image_remote_instance 42*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import remote_image_local_instance 43*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import remote_image_remote_host 44*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal import constants 45*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import utils 46*800a58d9SAndroid Build Coastguard Workerfrom acloud.setup import setup 47*800a58d9SAndroid Build Coastguard Workerfrom acloud.setup import gcp_setup_runner 48*800a58d9SAndroid Build Coastguard Workerfrom acloud.setup import host_setup_runner 49*800a58d9SAndroid Build Coastguard Worker 50*800a58d9SAndroid Build Coastguard Worker 51*800a58d9SAndroid Build Coastguard Workerlogger = logging.getLogger(__name__) 52*800a58d9SAndroid Build Coastguard Worker 53*800a58d9SAndroid Build Coastguard Worker_MAKE_CMD = "build/soong/soong_ui.bash" 54*800a58d9SAndroid Build Coastguard Worker_MAKE_ARG = "--make-mode" 55*800a58d9SAndroid Build Coastguard Worker_YES = "y" 56*800a58d9SAndroid Build Coastguard Worker 57*800a58d9SAndroid Build Coastguard Worker_CREATOR_CLASS_DICT = { 58*800a58d9SAndroid Build Coastguard Worker # GCE types 59*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_GCE, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_REMOTE): 60*800a58d9SAndroid Build Coastguard Worker gce_local_image_remote_instance.GceLocalImageRemoteInstance, 61*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_GCE, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_REMOTE): 62*800a58d9SAndroid Build Coastguard Worker gce_remote_image_remote_instance.GceRemoteImageRemoteInstance, 63*800a58d9SAndroid Build Coastguard Worker # CF types 64*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_CF, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_LOCAL): 65*800a58d9SAndroid Build Coastguard Worker local_image_local_instance.LocalImageLocalInstance, 66*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_CF, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_REMOTE): 67*800a58d9SAndroid Build Coastguard Worker local_image_remote_instance.LocalImageRemoteInstance, 68*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_CF, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_HOST): 69*800a58d9SAndroid Build Coastguard Worker local_image_remote_host.LocalImageRemoteHost, 70*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_CF, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_REMOTE): 71*800a58d9SAndroid Build Coastguard Worker remote_image_remote_instance.RemoteImageRemoteInstance, 72*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_CF, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_LOCAL): 73*800a58d9SAndroid Build Coastguard Worker remote_image_local_instance.RemoteImageLocalInstance, 74*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_CF, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_HOST): 75*800a58d9SAndroid Build Coastguard Worker remote_image_remote_host.RemoteImageRemoteHost, 76*800a58d9SAndroid Build Coastguard Worker # Cheeps types 77*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_CHEEPS, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_REMOTE): 78*800a58d9SAndroid Build Coastguard Worker cheeps_remote_image_remote_instance.CheepsRemoteImageRemoteInstance, 79*800a58d9SAndroid Build Coastguard Worker # GF types 80*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_GF, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_REMOTE): 81*800a58d9SAndroid Build Coastguard Worker goldfish_remote_image_remote_instance.GoldfishRemoteImageRemoteInstance, 82*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_GF, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_LOCAL): 83*800a58d9SAndroid Build Coastguard Worker goldfish_local_image_local_instance.GoldfishLocalImageLocalInstance, 84*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_GF, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_HOST): 85*800a58d9SAndroid Build Coastguard Worker goldfish_remote_host.GoldfishRemoteHost, 86*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_GF, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_HOST): 87*800a58d9SAndroid Build Coastguard Worker goldfish_remote_host.GoldfishRemoteHost, 88*800a58d9SAndroid Build Coastguard Worker # FVP types 89*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_FVP, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_REMOTE): 90*800a58d9SAndroid Build Coastguard Worker local_image_remote_instance.LocalImageRemoteInstance, 91*800a58d9SAndroid Build Coastguard Worker # Trusty types 92*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_TRUSTY, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_REMOTE): 93*800a58d9SAndroid Build Coastguard Worker local_image_remote_instance.LocalImageRemoteInstance, 94*800a58d9SAndroid Build Coastguard Worker (constants.TYPE_TRUSTY, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_REMOTE): 95*800a58d9SAndroid Build Coastguard Worker remote_image_remote_instance.RemoteImageRemoteInstance, 96*800a58d9SAndroid Build Coastguard Worker} 97*800a58d9SAndroid Build Coastguard Worker 98*800a58d9SAndroid Build Coastguard Worker 99*800a58d9SAndroid Build Coastguard Workerdef GetAvdCreatorClass(avd_type, instance_type, image_source): 100*800a58d9SAndroid Build Coastguard Worker """Return the creator class for the specified spec. 101*800a58d9SAndroid Build Coastguard Worker 102*800a58d9SAndroid Build Coastguard Worker Based on the image source and the instance type, return the proper 103*800a58d9SAndroid Build Coastguard Worker creator class. 104*800a58d9SAndroid Build Coastguard Worker 105*800a58d9SAndroid Build Coastguard Worker Args: 106*800a58d9SAndroid Build Coastguard Worker avd_type: String, the AVD type(cuttlefish, gce). 107*800a58d9SAndroid Build Coastguard Worker instance_type: String, the AVD instance type (local or remote). 108*800a58d9SAndroid Build Coastguard Worker image_source: String, the source of the image (local or remote). 109*800a58d9SAndroid Build Coastguard Worker 110*800a58d9SAndroid Build Coastguard Worker Returns: 111*800a58d9SAndroid Build Coastguard Worker An AVD creator class (e.g. LocalImageRemoteInstance). 112*800a58d9SAndroid Build Coastguard Worker 113*800a58d9SAndroid Build Coastguard Worker Raises: 114*800a58d9SAndroid Build Coastguard Worker UnsupportedInstanceImageType if argments didn't match _CREATOR_CLASS_DICT. 115*800a58d9SAndroid Build Coastguard Worker """ 116*800a58d9SAndroid Build Coastguard Worker creator_class = _CREATOR_CLASS_DICT.get( 117*800a58d9SAndroid Build Coastguard Worker (avd_type, image_source, instance_type)) 118*800a58d9SAndroid Build Coastguard Worker 119*800a58d9SAndroid Build Coastguard Worker if not creator_class: 120*800a58d9SAndroid Build Coastguard Worker raise errors.UnsupportedInstanceImageType( 121*800a58d9SAndroid Build Coastguard Worker "unsupported creation of avd type: %s, instance type: %s, " 122*800a58d9SAndroid Build Coastguard Worker "image source: %s" % (avd_type, instance_type, image_source)) 123*800a58d9SAndroid Build Coastguard Worker return creator_class 124*800a58d9SAndroid Build Coastguard Worker 125*800a58d9SAndroid Build Coastguard Workerdef _CheckForAutoconnect(args): 126*800a58d9SAndroid Build Coastguard Worker """Check that we have all prerequisites for autoconnect. 127*800a58d9SAndroid Build Coastguard Worker 128*800a58d9SAndroid Build Coastguard Worker Autoconnect requires adb and ssh, we'll just check for adb for now and 129*800a58d9SAndroid Build Coastguard Worker assume ssh is everywhere. If adb isn't around, ask the user if they want us 130*800a58d9SAndroid Build Coastguard Worker to build it, if not we'll disable autoconnect. 131*800a58d9SAndroid Build Coastguard Worker 132*800a58d9SAndroid Build Coastguard Worker Args: 133*800a58d9SAndroid Build Coastguard Worker args: Namespace object from argparse.parse_args. 134*800a58d9SAndroid Build Coastguard Worker """ 135*800a58d9SAndroid Build Coastguard Worker if not args.autoconnect or utils.FindExecutable(constants.ADB_BIN): 136*800a58d9SAndroid Build Coastguard Worker return 137*800a58d9SAndroid Build Coastguard Worker 138*800a58d9SAndroid Build Coastguard Worker disable_autoconnect = False 139*800a58d9SAndroid Build Coastguard Worker answer = _YES if args.no_prompt else utils.InteractWithQuestion( 140*800a58d9SAndroid Build Coastguard Worker "adb is required for autoconnect, without it autoconnect will be " 141*800a58d9SAndroid Build Coastguard Worker "disabled, would you like acloud to build it[y/N]? ") 142*800a58d9SAndroid Build Coastguard Worker if answer in constants.USER_ANSWER_YES: 143*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString("Building adb ... ", end="") 144*800a58d9SAndroid Build Coastguard Worker android_build_top = os.environ.get( 145*800a58d9SAndroid Build Coastguard Worker constants.ENV_ANDROID_BUILD_TOP) 146*800a58d9SAndroid Build Coastguard Worker if not android_build_top: 147*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString("Fail! (Not in a lunch'd env)", 148*800a58d9SAndroid Build Coastguard Worker utils.TextColors.FAIL) 149*800a58d9SAndroid Build Coastguard Worker disable_autoconnect = True 150*800a58d9SAndroid Build Coastguard Worker else: 151*800a58d9SAndroid Build Coastguard Worker make_cmd = os.path.join(android_build_top, _MAKE_CMD) 152*800a58d9SAndroid Build Coastguard Worker build_adb_cmd = [make_cmd, _MAKE_ARG, "adb"] 153*800a58d9SAndroid Build Coastguard Worker try: 154*800a58d9SAndroid Build Coastguard Worker with open(os.devnull, "w") as dev_null: 155*800a58d9SAndroid Build Coastguard Worker subprocess.check_call(build_adb_cmd, stderr=dev_null, 156*800a58d9SAndroid Build Coastguard Worker stdout=dev_null) 157*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString("OK!", utils.TextColors.OKGREEN) 158*800a58d9SAndroid Build Coastguard Worker except subprocess.CalledProcessError: 159*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString("Fail! (build failed)", 160*800a58d9SAndroid Build Coastguard Worker utils.TextColors.FAIL) 161*800a58d9SAndroid Build Coastguard Worker disable_autoconnect = True 162*800a58d9SAndroid Build Coastguard Worker else: 163*800a58d9SAndroid Build Coastguard Worker disable_autoconnect = True 164*800a58d9SAndroid Build Coastguard Worker 165*800a58d9SAndroid Build Coastguard Worker if disable_autoconnect: 166*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString("Disabling autoconnect", 167*800a58d9SAndroid Build Coastguard Worker utils.TextColors.WARNING) 168*800a58d9SAndroid Build Coastguard Worker args.autoconnect = False 169*800a58d9SAndroid Build Coastguard Worker 170*800a58d9SAndroid Build Coastguard Worker 171*800a58d9SAndroid Build Coastguard Workerdef _CheckForSetup(args): 172*800a58d9SAndroid Build Coastguard Worker """Check that host is setup to run the create commands. 173*800a58d9SAndroid Build Coastguard Worker 174*800a58d9SAndroid Build Coastguard Worker We'll check we have the necessary bits setup to do what the user wants, and 175*800a58d9SAndroid Build Coastguard Worker if not, tell them what they need to do before running create again. 176*800a58d9SAndroid Build Coastguard Worker 177*800a58d9SAndroid Build Coastguard Worker Args: 178*800a58d9SAndroid Build Coastguard Worker args: Namespace object from argparse.parse_args. 179*800a58d9SAndroid Build Coastguard Worker """ 180*800a58d9SAndroid Build Coastguard Worker # Need to set all these so if we need to run setup, it won't barf on us 181*800a58d9SAndroid Build Coastguard Worker # because of some missing fields. 182*800a58d9SAndroid Build Coastguard Worker args.gcp_init = False 183*800a58d9SAndroid Build Coastguard Worker args.host = False 184*800a58d9SAndroid Build Coastguard Worker args.host_base = False 185*800a58d9SAndroid Build Coastguard Worker args.force = False 186*800a58d9SAndroid Build Coastguard Worker args.update_config = None 187*800a58d9SAndroid Build Coastguard Worker args.host_local_ca = False 188*800a58d9SAndroid Build Coastguard Worker # Remote image/instance requires the GCP config setup. 189*800a58d9SAndroid Build Coastguard Worker if args.local_instance is None or args.local_image is None: 190*800a58d9SAndroid Build Coastguard Worker gcp_setup = gcp_setup_runner.GcpTaskRunner(args.config_file) 191*800a58d9SAndroid Build Coastguard Worker if gcp_setup.ShouldRun(): 192*800a58d9SAndroid Build Coastguard Worker args.gcp_init = True 193*800a58d9SAndroid Build Coastguard Worker logger.debug("Auto-detect to setup GCP config.") 194*800a58d9SAndroid Build Coastguard Worker 195*800a58d9SAndroid Build Coastguard Worker # Local instance requires host to be setup. We'll assume that if the 196*800a58d9SAndroid Build Coastguard Worker # packages were installed, then the user was added into the groups. This 197*800a58d9SAndroid Build Coastguard Worker # avoids the scenario where a user runs setup and creates a local instance. 198*800a58d9SAndroid Build Coastguard Worker # The following local instance create will trigger this if statment and go 199*800a58d9SAndroid Build Coastguard Worker # through the whole setup again even though it's already done because the 200*800a58d9SAndroid Build Coastguard Worker # user groups aren't set until the user logs out and back in. 201*800a58d9SAndroid Build Coastguard Worker if args.local_instance is not None: 202*800a58d9SAndroid Build Coastguard Worker host_pkg_setup = host_setup_runner.AvdPkgInstaller() 203*800a58d9SAndroid Build Coastguard Worker if host_pkg_setup.ShouldRun(): 204*800a58d9SAndroid Build Coastguard Worker args.host = True 205*800a58d9SAndroid Build Coastguard Worker logger.debug("Auto-detect to install host packages.") 206*800a58d9SAndroid Build Coastguard Worker 207*800a58d9SAndroid Build Coastguard Worker user_groups_setup = host_setup_runner.CuttlefishHostSetup() 208*800a58d9SAndroid Build Coastguard Worker if user_groups_setup.ShouldRun(): 209*800a58d9SAndroid Build Coastguard Worker args.host = True 210*800a58d9SAndroid Build Coastguard Worker logger.debug("Auto-detect to setup user groups.") 211*800a58d9SAndroid Build Coastguard Worker 212*800a58d9SAndroid Build Coastguard Worker if args.mkcert and args.autoconnect == constants.INS_KEY_WEBRTC: 213*800a58d9SAndroid Build Coastguard Worker local_ca_setup = host_setup_runner.LocalCAHostSetup() 214*800a58d9SAndroid Build Coastguard Worker if local_ca_setup.ShouldRun(): 215*800a58d9SAndroid Build Coastguard Worker args.host_local_ca = True 216*800a58d9SAndroid Build Coastguard Worker logger.debug("Auto-detect to setup local CA.") 217*800a58d9SAndroid Build Coastguard Worker 218*800a58d9SAndroid Build Coastguard Worker # Install base packages if we haven't already. 219*800a58d9SAndroid Build Coastguard Worker host_base_setup = host_setup_runner.HostBasePkgInstaller() 220*800a58d9SAndroid Build Coastguard Worker if host_base_setup.ShouldRun(): 221*800a58d9SAndroid Build Coastguard Worker args.host_base = True 222*800a58d9SAndroid Build Coastguard Worker logger.debug("Auto-detect to install host_base packages.") 223*800a58d9SAndroid Build Coastguard Worker 224*800a58d9SAndroid Build Coastguard Worker run_setup = any([ 225*800a58d9SAndroid Build Coastguard Worker args.force, args.gcp_init, args.host, args.host_base, args.host_local_ca]) 226*800a58d9SAndroid Build Coastguard Worker 227*800a58d9SAndroid Build Coastguard Worker if run_setup: 228*800a58d9SAndroid Build Coastguard Worker answer = utils.InteractWithQuestion("Missing necessary acloud setup, " 229*800a58d9SAndroid Build Coastguard Worker "would you like to run setup[y/N]?") 230*800a58d9SAndroid Build Coastguard Worker if answer in constants.USER_ANSWER_YES: 231*800a58d9SAndroid Build Coastguard Worker setup.Run(args) 232*800a58d9SAndroid Build Coastguard Worker else: 233*800a58d9SAndroid Build Coastguard Worker print("Please run '#acloud setup' so we can get your host setup") 234*800a58d9SAndroid Build Coastguard Worker sys.exit(constants.EXIT_BY_USER) 235*800a58d9SAndroid Build Coastguard Worker 236*800a58d9SAndroid Build Coastguard Worker 237*800a58d9SAndroid Build Coastguard Workerdef PreRunCheck(args): 238*800a58d9SAndroid Build Coastguard Worker """Do some pre-run checks to ensure a smooth create experience. 239*800a58d9SAndroid Build Coastguard Worker 240*800a58d9SAndroid Build Coastguard Worker Args: 241*800a58d9SAndroid Build Coastguard Worker args: Namespace object from argparse.parse_args. 242*800a58d9SAndroid Build Coastguard Worker """ 243*800a58d9SAndroid Build Coastguard Worker _CheckForSetup(args) 244*800a58d9SAndroid Build Coastguard Worker _CheckForAutoconnect(args) 245*800a58d9SAndroid Build Coastguard Worker 246*800a58d9SAndroid Build Coastguard Worker 247*800a58d9SAndroid Build Coastguard Workerdef Run(args): 248*800a58d9SAndroid Build Coastguard Worker """Run create. 249*800a58d9SAndroid Build Coastguard Worker 250*800a58d9SAndroid Build Coastguard Worker Args: 251*800a58d9SAndroid Build Coastguard Worker args: Namespace object from argparse.parse_args. 252*800a58d9SAndroid Build Coastguard Worker 253*800a58d9SAndroid Build Coastguard Worker Returns: 254*800a58d9SAndroid Build Coastguard Worker A Report instance. 255*800a58d9SAndroid Build Coastguard Worker """ 256*800a58d9SAndroid Build Coastguard Worker if not args.skip_pre_run_check: 257*800a58d9SAndroid Build Coastguard Worker PreRunCheck(args) 258*800a58d9SAndroid Build Coastguard Worker spec = avd_spec.AVDSpec(args) 259*800a58d9SAndroid Build Coastguard Worker avd_creator_class = GetAvdCreatorClass(spec.avd_type, 260*800a58d9SAndroid Build Coastguard Worker spec.instance_type, 261*800a58d9SAndroid Build Coastguard Worker spec.image_source) 262*800a58d9SAndroid Build Coastguard Worker avd_creator = avd_creator_class() 263*800a58d9SAndroid Build Coastguard Worker report = avd_creator.Create(spec, args.no_prompt) 264*800a58d9SAndroid Build Coastguard Worker return report 265