xref: /aosp_15_r20/tools/acloud/create/create.py (revision 800a58d989c669b8eb8a71d8df53b1ba3d411444)
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