xref: /aosp_15_r20/tools/acloud/public/acloud_main.py (revision 800a58d989c669b8eb8a71d8df53b1ba3d411444)
1*800a58d9SAndroid Build Coastguard Worker#!/usr/bin/env python
2*800a58d9SAndroid Build Coastguard Worker#
3*800a58d9SAndroid Build Coastguard Worker# Copyright 2016 - 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"""
17*800a58d9SAndroid Build Coastguard WorkerWelcome to
18*800a58d9SAndroid Build Coastguard Worker   ___  _______   ____  __  _____
19*800a58d9SAndroid Build Coastguard Worker  / _ |/ ___/ /  / __ \/ / / / _ \
20*800a58d9SAndroid Build Coastguard Worker / __ / /__/ /__/ /_/ / /_/ / // /
21*800a58d9SAndroid Build Coastguard Worker/_/ |_\___/____/\____/\____/____/
22*800a58d9SAndroid Build Coastguard Worker
23*800a58d9SAndroid Build Coastguard Worker
24*800a58d9SAndroid Build Coastguard WorkerThis a tool to create Android Virtual Devices locally/remotely.
25*800a58d9SAndroid Build Coastguard Worker
26*800a58d9SAndroid Build Coastguard Worker- Prerequisites:
27*800a58d9SAndroid Build Coastguard Worker The manual will be available at
28*800a58d9SAndroid Build Coastguard Worker https://android.googlesource.com/platform/tools/acloud/+/master/README.md
29*800a58d9SAndroid Build Coastguard Worker
30*800a58d9SAndroid Build Coastguard Worker- To get started:
31*800a58d9SAndroid Build Coastguard Worker - Create instances:
32*800a58d9SAndroid Build Coastguard Worker    1) To create a remote cuttlefish instance with the local built image.
33*800a58d9SAndroid Build Coastguard Worker       Example:
34*800a58d9SAndroid Build Coastguard Worker       $ acloud create --local-image
35*800a58d9SAndroid Build Coastguard Worker       Or specify built image dir:
36*800a58d9SAndroid Build Coastguard Worker       $ acloud create --local-image /tmp/image_dir
37*800a58d9SAndroid Build Coastguard Worker    2) To create a local cuttlefish instance using the image which has been
38*800a58d9SAndroid Build Coastguard Worker       built out in your workspace.
39*800a58d9SAndroid Build Coastguard Worker       Example:
40*800a58d9SAndroid Build Coastguard Worker       $ acloud create --local-instance --local-image
41*800a58d9SAndroid Build Coastguard Worker
42*800a58d9SAndroid Build Coastguard Worker - Delete instances:
43*800a58d9SAndroid Build Coastguard Worker   $ acloud delete
44*800a58d9SAndroid Build Coastguard Worker
45*800a58d9SAndroid Build Coastguard Worker - Reconnect:
46*800a58d9SAndroid Build Coastguard Worker   To reconnect adb/vnc to an existing instance that's been disconnected:
47*800a58d9SAndroid Build Coastguard Worker   $ acloud reconnect
48*800a58d9SAndroid Build Coastguard Worker   Or to specify a specific instance:
49*800a58d9SAndroid Build Coastguard Worker   $ acloud reconnect --instance-names <instance_name like ins-123-cf-x86-phone>
50*800a58d9SAndroid Build Coastguard Worker
51*800a58d9SAndroid Build Coastguard Worker - List:
52*800a58d9SAndroid Build Coastguard Worker   List will retrieve all the remote instances you've created in addition to any
53*800a58d9SAndroid Build Coastguard Worker   local instances created as well.
54*800a58d9SAndroid Build Coastguard Worker   To show device IP address, adb port and instance name:
55*800a58d9SAndroid Build Coastguard Worker   $ acloud list
56*800a58d9SAndroid Build Coastguard Worker   To show more detail info on the list.
57*800a58d9SAndroid Build Coastguard Worker   $ acloud list -vv
58*800a58d9SAndroid Build Coastguard Worker
59*800a58d9SAndroid Build Coastguard Worker-  Pull:
60*800a58d9SAndroid Build Coastguard Worker   Pull will download log files or show the log file in screen from one remote
61*800a58d9SAndroid Build Coastguard Worker   cuttlefish instance:
62*800a58d9SAndroid Build Coastguard Worker   $ acloud pull
63*800a58d9SAndroid Build Coastguard Worker   Pull from a specified instance:
64*800a58d9SAndroid Build Coastguard Worker   $ acloud pull --instance-name "your_instance_name"
65*800a58d9SAndroid Build Coastguard Worker
66*800a58d9SAndroid Build Coastguard WorkerTry $acloud [cmd] --help for further details.
67*800a58d9SAndroid Build Coastguard Worker
68*800a58d9SAndroid Build Coastguard Worker"""
69*800a58d9SAndroid Build Coastguard Worker
70*800a58d9SAndroid Build Coastguard Workerfrom __future__ import print_function
71*800a58d9SAndroid Build Coastguard Workerimport argparse
72*800a58d9SAndroid Build Coastguard Workerimport logging
73*800a58d9SAndroid Build Coastguard Workerimport os
74*800a58d9SAndroid Build Coastguard Workerimport sys
75*800a58d9SAndroid Build Coastguard Workerimport traceback
76*800a58d9SAndroid Build Coastguard Worker
77*800a58d9SAndroid Build Coastguard Workerif sys.version_info.major == 2:
78*800a58d9SAndroid Build Coastguard Worker    print("Acloud only supports python3 (currently @ %d.%d.%d)."
79*800a58d9SAndroid Build Coastguard Worker          " Please run Acloud with python3." % (sys.version_info.major,
80*800a58d9SAndroid Build Coastguard Worker                                                sys.version_info.minor,
81*800a58d9SAndroid Build Coastguard Worker                                                sys.version_info.micro))
82*800a58d9SAndroid Build Coastguard Worker    sys.exit(1)
83*800a58d9SAndroid Build Coastguard Worker
84*800a58d9SAndroid Build Coastguard Worker# By Default silence root logger's stream handler since 3p lib may initial
85*800a58d9SAndroid Build Coastguard Worker# root logger no matter what level we're using. The acloud logger behavior will
86*800a58d9SAndroid Build Coastguard Worker# be defined in _SetupLogging(). This also could workaround to get rid of below
87*800a58d9SAndroid Build Coastguard Worker# oauth2client warning:
88*800a58d9SAndroid Build Coastguard Worker# 'No handlers could be found for logger "oauth2client.contrib.multistore_file'
89*800a58d9SAndroid Build Coastguard WorkerDEFAULT_STREAM_HANDLER = logging.StreamHandler()
90*800a58d9SAndroid Build Coastguard WorkerDEFAULT_STREAM_HANDLER.setLevel(logging.CRITICAL)
91*800a58d9SAndroid Build Coastguard Workerlogging.getLogger().addHandler(DEFAULT_STREAM_HANDLER)
92*800a58d9SAndroid Build Coastguard Worker
93*800a58d9SAndroid Build Coastguard Worker# pylint: disable=wrong-import-position
94*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors
95*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import create
96*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import create_args
97*800a58d9SAndroid Build Coastguard Workerfrom acloud.delete import delete
98*800a58d9SAndroid Build Coastguard Workerfrom acloud.delete import delete_args
99*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal import constants
100*800a58d9SAndroid Build Coastguard Workerfrom acloud.reconnect import reconnect
101*800a58d9SAndroid Build Coastguard Workerfrom acloud.reconnect import reconnect_args
102*800a58d9SAndroid Build Coastguard Workerfrom acloud.list import list as list_instances
103*800a58d9SAndroid Build Coastguard Workerfrom acloud.list import list_args
104*800a58d9SAndroid Build Coastguard Workerfrom acloud.metrics import metrics
105*800a58d9SAndroid Build Coastguard Workerfrom acloud.powerwash import powerwash
106*800a58d9SAndroid Build Coastguard Workerfrom acloud.powerwash import powerwash_args
107*800a58d9SAndroid Build Coastguard Workerfrom acloud.public import acloud_common
108*800a58d9SAndroid Build Coastguard Workerfrom acloud.public import config
109*800a58d9SAndroid Build Coastguard Workerfrom acloud.public import report
110*800a58d9SAndroid Build Coastguard Workerfrom acloud.public.actions import create_goldfish_action
111*800a58d9SAndroid Build Coastguard Workerfrom acloud.pull import pull
112*800a58d9SAndroid Build Coastguard Workerfrom acloud.pull import pull_args
113*800a58d9SAndroid Build Coastguard Workerfrom acloud.restart import restart
114*800a58d9SAndroid Build Coastguard Workerfrom acloud.restart import restart_args
115*800a58d9SAndroid Build Coastguard Workerfrom acloud.setup import setup
116*800a58d9SAndroid Build Coastguard Workerfrom acloud.setup import setup_args
117*800a58d9SAndroid Build Coastguard Workerfrom acloud.hostcleanup import hostcleanup
118*800a58d9SAndroid Build Coastguard Workerfrom acloud.hostcleanup import hostcleanup_args
119*800a58d9SAndroid Build Coastguard Worker
120*800a58d9SAndroid Build Coastguard Worker
121*800a58d9SAndroid Build Coastguard WorkerLOGGING_FMT = "%(asctime)s |%(levelname)s| %(module)s:%(lineno)s| %(message)s"
122*800a58d9SAndroid Build Coastguard WorkerACLOUD_LOGGER = "acloud"
123*800a58d9SAndroid Build Coastguard Worker_LOGGER = logging.getLogger(ACLOUD_LOGGER)
124*800a58d9SAndroid Build Coastguard WorkerNO_ERROR_MESSAGE = ""
125*800a58d9SAndroid Build Coastguard WorkerPROG = "acloud"
126*800a58d9SAndroid Build Coastguard WorkerDEFAULT_SUPPORT_ARGS = ["--version", "-h", "--help"]
127*800a58d9SAndroid Build Coastguard Worker
128*800a58d9SAndroid Build Coastguard Worker# Commands
129*800a58d9SAndroid Build Coastguard WorkerCMD_CREATE_GOLDFISH = "create_gf"
130*800a58d9SAndroid Build Coastguard Worker
131*800a58d9SAndroid Build Coastguard Worker# Config requires fields.
132*800a58d9SAndroid Build Coastguard Worker_CREATE_REQUIRE_FIELDS = ["project", "zone", "machine_type"]
133*800a58d9SAndroid Build Coastguard Worker# show contact info to user.
134*800a58d9SAndroid Build Coastguard Worker_CONTACT_INFO = ("If you have any question or need acloud team support, "
135*800a58d9SAndroid Build Coastguard Worker                 "please feel free to contact us by email at "
136*800a58d9SAndroid Build Coastguard Worker                 "[email protected]")
137*800a58d9SAndroid Build Coastguard Worker_LOG_INFO = " and attach those log files from %s"
138*800a58d9SAndroid Build Coastguard Worker
139*800a58d9SAndroid Build Coastguard Worker
140*800a58d9SAndroid Build Coastguard Worker# pylint: disable=too-many-statements
141*800a58d9SAndroid Build Coastguard Workerdef _ParseArgs(args):
142*800a58d9SAndroid Build Coastguard Worker    """Parse args.
143*800a58d9SAndroid Build Coastguard Worker
144*800a58d9SAndroid Build Coastguard Worker    Args:
145*800a58d9SAndroid Build Coastguard Worker        args: Argument list passed from main.
146*800a58d9SAndroid Build Coastguard Worker
147*800a58d9SAndroid Build Coastguard Worker    Returns:
148*800a58d9SAndroid Build Coastguard Worker        Parsed args and a list of unknown argument strings.
149*800a58d9SAndroid Build Coastguard Worker    """
150*800a58d9SAndroid Build Coastguard Worker    acloud_cmds = [
151*800a58d9SAndroid Build Coastguard Worker        setup_args.CMD_SETUP,
152*800a58d9SAndroid Build Coastguard Worker        create_args.CMD_CREATE,
153*800a58d9SAndroid Build Coastguard Worker        list_args.CMD_LIST,
154*800a58d9SAndroid Build Coastguard Worker        delete_args.CMD_DELETE,
155*800a58d9SAndroid Build Coastguard Worker        reconnect_args.CMD_RECONNECT,
156*800a58d9SAndroid Build Coastguard Worker        powerwash_args.CMD_POWERWASH,
157*800a58d9SAndroid Build Coastguard Worker        pull_args.CMD_PULL,
158*800a58d9SAndroid Build Coastguard Worker        restart_args.CMD_RESTART,
159*800a58d9SAndroid Build Coastguard Worker        hostcleanup_args.CMD_HOSTCLEANUP,
160*800a58d9SAndroid Build Coastguard Worker        CMD_CREATE_GOLDFISH]
161*800a58d9SAndroid Build Coastguard Worker    usage = ",".join(acloud_cmds)
162*800a58d9SAndroid Build Coastguard Worker    parser = argparse.ArgumentParser(
163*800a58d9SAndroid Build Coastguard Worker        description=__doc__,
164*800a58d9SAndroid Build Coastguard Worker        formatter_class=argparse.RawDescriptionHelpFormatter,
165*800a58d9SAndroid Build Coastguard Worker        usage="acloud {" + usage + "} ...")
166*800a58d9SAndroid Build Coastguard Worker    parser = argparse.ArgumentParser(prog=PROG)
167*800a58d9SAndroid Build Coastguard Worker    parser.add_argument('--version', action='version', version=(
168*800a58d9SAndroid Build Coastguard Worker        '%(prog)s ' + config.GetVersion()))
169*800a58d9SAndroid Build Coastguard Worker    subparsers = parser.add_subparsers(metavar="{" + usage + "}")
170*800a58d9SAndroid Build Coastguard Worker    subparser_list = []
171*800a58d9SAndroid Build Coastguard Worker
172*800a58d9SAndroid Build Coastguard Worker    # Command "create_gf", create goldfish instances
173*800a58d9SAndroid Build Coastguard Worker    # In order to create a goldfish device we need the following parameters:
174*800a58d9SAndroid Build Coastguard Worker    # 1. The emulator build we wish to use, this is the binary that emulates
175*800a58d9SAndroid Build Coastguard Worker    #    an android device. See go/emu-dev for more
176*800a58d9SAndroid Build Coastguard Worker    # 2. A system-image. This is the android release we wish to run on the
177*800a58d9SAndroid Build Coastguard Worker    #    emulated hardware.
178*800a58d9SAndroid Build Coastguard Worker    create_gf_parser = subparsers.add_parser(CMD_CREATE_GOLDFISH)
179*800a58d9SAndroid Build Coastguard Worker    create_gf_parser.required = False
180*800a58d9SAndroid Build Coastguard Worker    create_gf_parser.set_defaults(which=CMD_CREATE_GOLDFISH)
181*800a58d9SAndroid Build Coastguard Worker    create_gf_parser.add_argument(
182*800a58d9SAndroid Build Coastguard Worker        "--emulator-build-id",
183*800a58d9SAndroid Build Coastguard Worker        type=str,
184*800a58d9SAndroid Build Coastguard Worker        dest="emulator_build_id",
185*800a58d9SAndroid Build Coastguard Worker        required=False,
186*800a58d9SAndroid Build Coastguard Worker        help="Emulator build used to run the images. e.g. 4669466.")
187*800a58d9SAndroid Build Coastguard Worker    create_gf_parser.add_argument(
188*800a58d9SAndroid Build Coastguard Worker        "--emulator-branch",
189*800a58d9SAndroid Build Coastguard Worker        type=str,
190*800a58d9SAndroid Build Coastguard Worker        dest="emulator_branch",
191*800a58d9SAndroid Build Coastguard Worker        required=False,
192*800a58d9SAndroid Build Coastguard Worker        help="Emulator build branch name, e.g. aosp-emu-master-dev. If specified"
193*800a58d9SAndroid Build Coastguard Worker        " without emulator-build-id, the last green build will be used.")
194*800a58d9SAndroid Build Coastguard Worker    create_gf_parser.add_argument(
195*800a58d9SAndroid Build Coastguard Worker        "--emulator-build-target",
196*800a58d9SAndroid Build Coastguard Worker        dest="emulator_build_target",
197*800a58d9SAndroid Build Coastguard Worker        required=False,
198*800a58d9SAndroid Build Coastguard Worker        help="Emulator build target used to run the images. e.g. "
199*800a58d9SAndroid Build Coastguard Worker        "emulator-linux_x64_nolocationui.")
200*800a58d9SAndroid Build Coastguard Worker    create_gf_parser.add_argument(
201*800a58d9SAndroid Build Coastguard Worker        "--base-image",
202*800a58d9SAndroid Build Coastguard Worker        type=str,
203*800a58d9SAndroid Build Coastguard Worker        dest="base_image",
204*800a58d9SAndroid Build Coastguard Worker        required=False,
205*800a58d9SAndroid Build Coastguard Worker        help="Name of the goldfish base image to be used to create the instance. "
206*800a58d9SAndroid Build Coastguard Worker        "This will override stable_goldfish_host_image_name from config. "
207*800a58d9SAndroid Build Coastguard Worker        "e.g. emu-dev-cts-061118")
208*800a58d9SAndroid Build Coastguard Worker    create_gf_parser.add_argument(
209*800a58d9SAndroid Build Coastguard Worker        "--tags",
210*800a58d9SAndroid Build Coastguard Worker        dest="tags",
211*800a58d9SAndroid Build Coastguard Worker        nargs="*",
212*800a58d9SAndroid Build Coastguard Worker        required=False,
213*800a58d9SAndroid Build Coastguard Worker        default=None,
214*800a58d9SAndroid Build Coastguard Worker        help="Tags to be set on to the created instance. e.g. https-server.")
215*800a58d9SAndroid Build Coastguard Worker    # Arguments in old format
216*800a58d9SAndroid Build Coastguard Worker    create_gf_parser.add_argument(
217*800a58d9SAndroid Build Coastguard Worker        "--emulator_build_id",
218*800a58d9SAndroid Build Coastguard Worker        type=str,
219*800a58d9SAndroid Build Coastguard Worker        dest="emulator_build_id",
220*800a58d9SAndroid Build Coastguard Worker        required=False,
221*800a58d9SAndroid Build Coastguard Worker        help=argparse.SUPPRESS)
222*800a58d9SAndroid Build Coastguard Worker    create_gf_parser.add_argument(
223*800a58d9SAndroid Build Coastguard Worker        "--emulator_branch",
224*800a58d9SAndroid Build Coastguard Worker        type=str,
225*800a58d9SAndroid Build Coastguard Worker        dest="emulator_branch",
226*800a58d9SAndroid Build Coastguard Worker        required=False,
227*800a58d9SAndroid Build Coastguard Worker        help=argparse.SUPPRESS)
228*800a58d9SAndroid Build Coastguard Worker    create_gf_parser.add_argument(
229*800a58d9SAndroid Build Coastguard Worker        "--base_image",
230*800a58d9SAndroid Build Coastguard Worker        type=str,
231*800a58d9SAndroid Build Coastguard Worker        dest="base_image",
232*800a58d9SAndroid Build Coastguard Worker        required=False,
233*800a58d9SAndroid Build Coastguard Worker        help=argparse.SUPPRESS)
234*800a58d9SAndroid Build Coastguard Worker
235*800a58d9SAndroid Build Coastguard Worker    create_args.AddCommonCreateArgs(create_gf_parser)
236*800a58d9SAndroid Build Coastguard Worker    subparser_list.append(create_gf_parser)
237*800a58d9SAndroid Build Coastguard Worker
238*800a58d9SAndroid Build Coastguard Worker    # Command "create"
239*800a58d9SAndroid Build Coastguard Worker    subparser_list.append(create_args.GetCreateArgParser(subparsers))
240*800a58d9SAndroid Build Coastguard Worker
241*800a58d9SAndroid Build Coastguard Worker    # Command "setup"
242*800a58d9SAndroid Build Coastguard Worker    subparser_list.append(setup_args.GetSetupArgParser(subparsers))
243*800a58d9SAndroid Build Coastguard Worker
244*800a58d9SAndroid Build Coastguard Worker    # Command "delete"
245*800a58d9SAndroid Build Coastguard Worker    subparser_list.append(delete_args.GetDeleteArgParser(subparsers))
246*800a58d9SAndroid Build Coastguard Worker
247*800a58d9SAndroid Build Coastguard Worker    # Command "list"
248*800a58d9SAndroid Build Coastguard Worker    subparser_list.append(list_args.GetListArgParser(subparsers))
249*800a58d9SAndroid Build Coastguard Worker
250*800a58d9SAndroid Build Coastguard Worker    # Command "reconnect"
251*800a58d9SAndroid Build Coastguard Worker    subparser_list.append(reconnect_args.GetReconnectArgParser(subparsers))
252*800a58d9SAndroid Build Coastguard Worker
253*800a58d9SAndroid Build Coastguard Worker    # Command "restart"
254*800a58d9SAndroid Build Coastguard Worker    subparser_list.append(restart_args.GetRestartArgParser(subparsers))
255*800a58d9SAndroid Build Coastguard Worker
256*800a58d9SAndroid Build Coastguard Worker    # Command "powerwash"
257*800a58d9SAndroid Build Coastguard Worker    subparser_list.append(powerwash_args.GetPowerwashArgParser(subparsers))
258*800a58d9SAndroid Build Coastguard Worker
259*800a58d9SAndroid Build Coastguard Worker    # Command "pull"
260*800a58d9SAndroid Build Coastguard Worker    subparser_list.append(pull_args.GetPullArgParser(subparsers))
261*800a58d9SAndroid Build Coastguard Worker
262*800a58d9SAndroid Build Coastguard Worker    # Command "hostcleanup"
263*800a58d9SAndroid Build Coastguard Worker    subparser_list.append(hostcleanup_args.GetHostcleanupArgParser(subparsers))
264*800a58d9SAndroid Build Coastguard Worker
265*800a58d9SAndroid Build Coastguard Worker    # Add common arguments.
266*800a58d9SAndroid Build Coastguard Worker    for subparser in subparser_list:
267*800a58d9SAndroid Build Coastguard Worker        acloud_common.AddCommonArguments(subparser)
268*800a58d9SAndroid Build Coastguard Worker
269*800a58d9SAndroid Build Coastguard Worker    support_args = acloud_cmds + DEFAULT_SUPPORT_ARGS
270*800a58d9SAndroid Build Coastguard Worker    if not args or args[0] not in support_args:
271*800a58d9SAndroid Build Coastguard Worker        parser.print_help()
272*800a58d9SAndroid Build Coastguard Worker        sys.exit(constants.EXIT_BY_WRONG_CMD)
273*800a58d9SAndroid Build Coastguard Worker
274*800a58d9SAndroid Build Coastguard Worker    return parser.parse_known_args(args)
275*800a58d9SAndroid Build Coastguard Worker
276*800a58d9SAndroid Build Coastguard Worker
277*800a58d9SAndroid Build Coastguard Worker# pylint: disable=too-many-branches
278*800a58d9SAndroid Build Coastguard Workerdef _VerifyArgs(parsed_args):
279*800a58d9SAndroid Build Coastguard Worker    """Verify args.
280*800a58d9SAndroid Build Coastguard Worker
281*800a58d9SAndroid Build Coastguard Worker    Args:
282*800a58d9SAndroid Build Coastguard Worker        parsed_args: Parsed args.
283*800a58d9SAndroid Build Coastguard Worker
284*800a58d9SAndroid Build Coastguard Worker    Raises:
285*800a58d9SAndroid Build Coastguard Worker        errors.CommandArgError: If args are invalid.
286*800a58d9SAndroid Build Coastguard Worker        errors.UnsupportedCreateArgs: When a create arg is specified but
287*800a58d9SAndroid Build Coastguard Worker                                      unsupported for a particular avd type.
288*800a58d9SAndroid Build Coastguard Worker                                      (e.g. --system-build-id for gf)
289*800a58d9SAndroid Build Coastguard Worker    """
290*800a58d9SAndroid Build Coastguard Worker    if parsed_args.which == create_args.CMD_CREATE:
291*800a58d9SAndroid Build Coastguard Worker        create_args.VerifyArgs(parsed_args)
292*800a58d9SAndroid Build Coastguard Worker    if parsed_args.which == setup_args.CMD_SETUP:
293*800a58d9SAndroid Build Coastguard Worker        setup_args.VerifyArgs(parsed_args)
294*800a58d9SAndroid Build Coastguard Worker    if parsed_args.which == CMD_CREATE_GOLDFISH:
295*800a58d9SAndroid Build Coastguard Worker        if not parsed_args.emulator_build_id and not parsed_args.build_id and (
296*800a58d9SAndroid Build Coastguard Worker                not parsed_args.emulator_branch and not parsed_args.branch):
297*800a58d9SAndroid Build Coastguard Worker            raise errors.CommandArgError(
298*800a58d9SAndroid Build Coastguard Worker                "Must specify either --build-id or --branch or "
299*800a58d9SAndroid Build Coastguard Worker                "--emulator-branch or --emulator-build-id")
300*800a58d9SAndroid Build Coastguard Worker        if not parsed_args.build_target:
301*800a58d9SAndroid Build Coastguard Worker            raise errors.CommandArgError("Must specify --build-target")
302*800a58d9SAndroid Build Coastguard Worker        if (parsed_args.system_branch
303*800a58d9SAndroid Build Coastguard Worker                or parsed_args.system_build_id
304*800a58d9SAndroid Build Coastguard Worker                or parsed_args.system_build_target):
305*800a58d9SAndroid Build Coastguard Worker            raise errors.UnsupportedCreateArgs(
306*800a58d9SAndroid Build Coastguard Worker                "--system-* args are not supported for AVD type: %s"
307*800a58d9SAndroid Build Coastguard Worker                % constants.TYPE_GF)
308*800a58d9SAndroid Build Coastguard Worker
309*800a58d9SAndroid Build Coastguard Worker    if parsed_args.which in [create_args.CMD_CREATE, CMD_CREATE_GOLDFISH]:
310*800a58d9SAndroid Build Coastguard Worker        if (parsed_args.serial_log_file
311*800a58d9SAndroid Build Coastguard Worker                and not parsed_args.serial_log_file.endswith(".tar.gz")):
312*800a58d9SAndroid Build Coastguard Worker            raise errors.CommandArgError(
313*800a58d9SAndroid Build Coastguard Worker                "--serial-log-file must ends with .tar.gz")
314*800a58d9SAndroid Build Coastguard Worker
315*800a58d9SAndroid Build Coastguard Worker
316*800a58d9SAndroid Build Coastguard Workerdef _ValidateAuthFile(cfg):
317*800a58d9SAndroid Build Coastguard Worker    """Check if the authentication file exist.
318*800a58d9SAndroid Build Coastguard Worker
319*800a58d9SAndroid Build Coastguard Worker    Args:
320*800a58d9SAndroid Build Coastguard Worker        cfg: AcloudConfig object.
321*800a58d9SAndroid Build Coastguard Worker    """
322*800a58d9SAndroid Build Coastguard Worker    auth_file = os.path.join(os.path.expanduser("~"), cfg.creds_cache_file)
323*800a58d9SAndroid Build Coastguard Worker    if not os.path.exists(auth_file):
324*800a58d9SAndroid Build Coastguard Worker        print("Notice: Acloud will bring up browser to proceed authentication. "
325*800a58d9SAndroid Build Coastguard Worker              "For cloudtop, please run in remote desktop.")
326*800a58d9SAndroid Build Coastguard Worker
327*800a58d9SAndroid Build Coastguard Worker
328*800a58d9SAndroid Build Coastguard Workerdef _ParsingConfig(args, cfg):
329*800a58d9SAndroid Build Coastguard Worker    """Parse config to check if missing any field.
330*800a58d9SAndroid Build Coastguard Worker
331*800a58d9SAndroid Build Coastguard Worker    Args:
332*800a58d9SAndroid Build Coastguard Worker        args: Namespace object from argparse.parse_args.
333*800a58d9SAndroid Build Coastguard Worker        cfg: AcloudConfig object.
334*800a58d9SAndroid Build Coastguard Worker
335*800a58d9SAndroid Build Coastguard Worker    Returns:
336*800a58d9SAndroid Build Coastguard Worker        error message about list of missing config fields.
337*800a58d9SAndroid Build Coastguard Worker    """
338*800a58d9SAndroid Build Coastguard Worker    missing_fields = []
339*800a58d9SAndroid Build Coastguard Worker    if (args.which == create_args.CMD_CREATE and
340*800a58d9SAndroid Build Coastguard Worker            args.local_instance is None and not args.remote_host):
341*800a58d9SAndroid Build Coastguard Worker        missing_fields = cfg.GetMissingFields(_CREATE_REQUIRE_FIELDS)
342*800a58d9SAndroid Build Coastguard Worker    if missing_fields:
343*800a58d9SAndroid Build Coastguard Worker        return (f"Config file ({config.GetUserConfigPath(args.config_file)}) "
344*800a58d9SAndroid Build Coastguard Worker                f"missing required fields: {missing_fields}, please add these "
345*800a58d9SAndroid Build Coastguard Worker                "fields or reset config file. For reset config information: "
346*800a58d9SAndroid Build Coastguard Worker                "go/acloud-googler-setup#reset-configuration")
347*800a58d9SAndroid Build Coastguard Worker    return None
348*800a58d9SAndroid Build Coastguard Worker
349*800a58d9SAndroid Build Coastguard Worker
350*800a58d9SAndroid Build Coastguard Workerdef _SetupLogging(log_file, verbose):
351*800a58d9SAndroid Build Coastguard Worker    """Setup logging.
352*800a58d9SAndroid Build Coastguard Worker
353*800a58d9SAndroid Build Coastguard Worker    This function define the logging policy in below manners.
354*800a58d9SAndroid Build Coastguard Worker    - without -v , -vv ,--log-file:
355*800a58d9SAndroid Build Coastguard Worker    Only display critical log and print() message on screen.
356*800a58d9SAndroid Build Coastguard Worker
357*800a58d9SAndroid Build Coastguard Worker    - with -v:
358*800a58d9SAndroid Build Coastguard Worker    Display INFO log and set StreamHandler to acloud parent logger to turn on
359*800a58d9SAndroid Build Coastguard Worker    ONLY acloud modules logging.(silence all 3p libraries)
360*800a58d9SAndroid Build Coastguard Worker
361*800a58d9SAndroid Build Coastguard Worker    - with -vv:
362*800a58d9SAndroid Build Coastguard Worker    Display INFO/DEBUG log and set StreamHandler to root logger to turn on all
363*800a58d9SAndroid Build Coastguard Worker    acloud modules and 3p libraries logging.
364*800a58d9SAndroid Build Coastguard Worker
365*800a58d9SAndroid Build Coastguard Worker    - with --log-file.
366*800a58d9SAndroid Build Coastguard Worker    Dump logs to FileHandler with DEBUG level.
367*800a58d9SAndroid Build Coastguard Worker
368*800a58d9SAndroid Build Coastguard Worker    Args:
369*800a58d9SAndroid Build Coastguard Worker        log_file: String, if not None, dump the log to log file.
370*800a58d9SAndroid Build Coastguard Worker        verbose: Int, if verbose = 1(-v), log at INFO level and turn on
371*800a58d9SAndroid Build Coastguard Worker                 logging on libraries to a StreamHandler.
372*800a58d9SAndroid Build Coastguard Worker                 If verbose = 2(-vv), log at DEBUG level and turn on logging on
373*800a58d9SAndroid Build Coastguard Worker                 all libraries and 3rd party libraries to a StreamHandler.
374*800a58d9SAndroid Build Coastguard Worker    """
375*800a58d9SAndroid Build Coastguard Worker    # Define logging level and hierarchy by verbosity.
376*800a58d9SAndroid Build Coastguard Worker    shandler_level = None
377*800a58d9SAndroid Build Coastguard Worker    logger = None
378*800a58d9SAndroid Build Coastguard Worker    if verbose == 0:
379*800a58d9SAndroid Build Coastguard Worker        shandler_level = logging.CRITICAL
380*800a58d9SAndroid Build Coastguard Worker        logger = logging.getLogger(ACLOUD_LOGGER)
381*800a58d9SAndroid Build Coastguard Worker    elif verbose == 1:
382*800a58d9SAndroid Build Coastguard Worker        shandler_level = logging.INFO
383*800a58d9SAndroid Build Coastguard Worker        logger = logging.getLogger(ACLOUD_LOGGER)
384*800a58d9SAndroid Build Coastguard Worker    elif verbose > 1:
385*800a58d9SAndroid Build Coastguard Worker        shandler_level = logging.DEBUG
386*800a58d9SAndroid Build Coastguard Worker        logger = logging.getLogger()
387*800a58d9SAndroid Build Coastguard Worker
388*800a58d9SAndroid Build Coastguard Worker    # Add StreamHandler by default.
389*800a58d9SAndroid Build Coastguard Worker    shandler = logging.StreamHandler()
390*800a58d9SAndroid Build Coastguard Worker    shandler.setFormatter(logging.Formatter(LOGGING_FMT))
391*800a58d9SAndroid Build Coastguard Worker    shandler.setLevel(shandler_level)
392*800a58d9SAndroid Build Coastguard Worker    logger.addHandler(shandler)
393*800a58d9SAndroid Build Coastguard Worker    # Set the default level to DEBUG, the other handlers will handle
394*800a58d9SAndroid Build Coastguard Worker    # their own levels via the args supplied (-v and --log-file).
395*800a58d9SAndroid Build Coastguard Worker    logger.setLevel(logging.DEBUG)
396*800a58d9SAndroid Build Coastguard Worker
397*800a58d9SAndroid Build Coastguard Worker    # Add FileHandler if log_file is provided.
398*800a58d9SAndroid Build Coastguard Worker    if log_file:
399*800a58d9SAndroid Build Coastguard Worker        fhandler = logging.FileHandler(filename=log_file)
400*800a58d9SAndroid Build Coastguard Worker        fhandler.setFormatter(logging.Formatter(LOGGING_FMT))
401*800a58d9SAndroid Build Coastguard Worker        fhandler.setLevel(logging.DEBUG)
402*800a58d9SAndroid Build Coastguard Worker        logger.addHandler(fhandler)
403*800a58d9SAndroid Build Coastguard Worker
404*800a58d9SAndroid Build Coastguard Worker
405*800a58d9SAndroid Build Coastguard Workerdef main(argv=None):
406*800a58d9SAndroid Build Coastguard Worker    """Main entry.
407*800a58d9SAndroid Build Coastguard Worker
408*800a58d9SAndroid Build Coastguard Worker    Args:
409*800a58d9SAndroid Build Coastguard Worker        argv: A list of system arguments.
410*800a58d9SAndroid Build Coastguard Worker
411*800a58d9SAndroid Build Coastguard Worker    Returns:
412*800a58d9SAndroid Build Coastguard Worker        Job status: Integer, 0 if success. None-zero if fails.
413*800a58d9SAndroid Build Coastguard Worker        Stack trace: String of errors.
414*800a58d9SAndroid Build Coastguard Worker    """
415*800a58d9SAndroid Build Coastguard Worker    args, unknown_args = _ParseArgs(argv)
416*800a58d9SAndroid Build Coastguard Worker    _SetupLogging(args.log_file, args.verbose)
417*800a58d9SAndroid Build Coastguard Worker    _VerifyArgs(args)
418*800a58d9SAndroid Build Coastguard Worker    _LOGGER.info("Acloud version: %s", config.GetVersion())
419*800a58d9SAndroid Build Coastguard Worker
420*800a58d9SAndroid Build Coastguard Worker    cfg = config.GetAcloudConfig(args)
421*800a58d9SAndroid Build Coastguard Worker    parsing_config_error = _ParsingConfig(args, cfg)
422*800a58d9SAndroid Build Coastguard Worker    _ValidateAuthFile(cfg)
423*800a58d9SAndroid Build Coastguard Worker    # TODO: Move this check into the functions it is actually needed.
424*800a58d9SAndroid Build Coastguard Worker    # Check access.
425*800a58d9SAndroid Build Coastguard Worker    # device_driver.CheckAccess(cfg)
426*800a58d9SAndroid Build Coastguard Worker
427*800a58d9SAndroid Build Coastguard Worker    reporter = None
428*800a58d9SAndroid Build Coastguard Worker    if parsing_config_error:
429*800a58d9SAndroid Build Coastguard Worker        reporter = report.Report(command=args.which)
430*800a58d9SAndroid Build Coastguard Worker        reporter.UpdateFailure(parsing_config_error,
431*800a58d9SAndroid Build Coastguard Worker                               constants.ACLOUD_CONFIG_ERROR)
432*800a58d9SAndroid Build Coastguard Worker    elif unknown_args:
433*800a58d9SAndroid Build Coastguard Worker        reporter = report.Report(command=args.which)
434*800a58d9SAndroid Build Coastguard Worker        reporter.UpdateFailure(
435*800a58d9SAndroid Build Coastguard Worker            "unrecognized arguments: %s" % ",".join(unknown_args),
436*800a58d9SAndroid Build Coastguard Worker            constants.ACLOUD_UNKNOWN_ARGS_ERROR)
437*800a58d9SAndroid Build Coastguard Worker    elif args.which == create_args.CMD_CREATE:
438*800a58d9SAndroid Build Coastguard Worker        reporter = create.Run(args)
439*800a58d9SAndroid Build Coastguard Worker    elif args.which == CMD_CREATE_GOLDFISH:
440*800a58d9SAndroid Build Coastguard Worker        reporter = create_goldfish_action.CreateDevices(
441*800a58d9SAndroid Build Coastguard Worker            cfg=cfg,
442*800a58d9SAndroid Build Coastguard Worker            build_target=args.build_target,
443*800a58d9SAndroid Build Coastguard Worker            branch=args.branch,
444*800a58d9SAndroid Build Coastguard Worker            build_id=args.build_id,
445*800a58d9SAndroid Build Coastguard Worker            emulator_build_id=args.emulator_build_id,
446*800a58d9SAndroid Build Coastguard Worker            emulator_branch=args.emulator_branch,
447*800a58d9SAndroid Build Coastguard Worker            emulator_build_target=args.emulator_build_target,
448*800a58d9SAndroid Build Coastguard Worker            kernel_build_id=args.kernel_build_id,
449*800a58d9SAndroid Build Coastguard Worker            kernel_branch=args.kernel_branch,
450*800a58d9SAndroid Build Coastguard Worker            kernel_build_target=args.kernel_build_target,
451*800a58d9SAndroid Build Coastguard Worker            gpu=args.gpu,
452*800a58d9SAndroid Build Coastguard Worker            num=args.num,
453*800a58d9SAndroid Build Coastguard Worker            serial_log_file=args.serial_log_file,
454*800a58d9SAndroid Build Coastguard Worker            autoconnect=args.autoconnect,
455*800a58d9SAndroid Build Coastguard Worker            tags=args.tags,
456*800a58d9SAndroid Build Coastguard Worker            report_internal_ip=args.report_internal_ip,
457*800a58d9SAndroid Build Coastguard Worker            boot_timeout_secs=args.boot_timeout_secs)
458*800a58d9SAndroid Build Coastguard Worker    elif args.which == delete_args.CMD_DELETE:
459*800a58d9SAndroid Build Coastguard Worker        reporter = delete.Run(args)
460*800a58d9SAndroid Build Coastguard Worker    elif args.which == list_args.CMD_LIST:
461*800a58d9SAndroid Build Coastguard Worker        list_instances.Run(args)
462*800a58d9SAndroid Build Coastguard Worker    elif args.which == reconnect_args.CMD_RECONNECT:
463*800a58d9SAndroid Build Coastguard Worker        reconnect.Run(args)
464*800a58d9SAndroid Build Coastguard Worker    elif args.which == restart_args.CMD_RESTART:
465*800a58d9SAndroid Build Coastguard Worker        reporter = restart.Run(args)
466*800a58d9SAndroid Build Coastguard Worker    elif args.which == powerwash_args.CMD_POWERWASH:
467*800a58d9SAndroid Build Coastguard Worker        reporter = powerwash.Run(args)
468*800a58d9SAndroid Build Coastguard Worker    elif args.which == pull_args.CMD_PULL:
469*800a58d9SAndroid Build Coastguard Worker        reporter = pull.Run(args)
470*800a58d9SAndroid Build Coastguard Worker    elif args.which == setup_args.CMD_SETUP:
471*800a58d9SAndroid Build Coastguard Worker        setup.Run(args)
472*800a58d9SAndroid Build Coastguard Worker    elif args.which == hostcleanup_args.CMD_HOSTCLEANUP:
473*800a58d9SAndroid Build Coastguard Worker        hostcleanup.Run(args)
474*800a58d9SAndroid Build Coastguard Worker    else:
475*800a58d9SAndroid Build Coastguard Worker        error_msg = "Invalid command %s" % args.which
476*800a58d9SAndroid Build Coastguard Worker        sys.stderr.write(error_msg)
477*800a58d9SAndroid Build Coastguard Worker        return constants.EXIT_BY_WRONG_CMD, error_msg
478*800a58d9SAndroid Build Coastguard Worker
479*800a58d9SAndroid Build Coastguard Worker    if reporter and args.report_file:
480*800a58d9SAndroid Build Coastguard Worker        reporter.Dump(args.report_file)
481*800a58d9SAndroid Build Coastguard Worker    if reporter and reporter.errors:
482*800a58d9SAndroid Build Coastguard Worker        error_msg = "\n".join(reporter.errors)
483*800a58d9SAndroid Build Coastguard Worker        help_msg = _CONTACT_INFO
484*800a58d9SAndroid Build Coastguard Worker        if reporter.data.get(constants.ERROR_LOG_FOLDER):
485*800a58d9SAndroid Build Coastguard Worker            help_msg += _LOG_INFO % reporter.data.get(constants.ERROR_LOG_FOLDER)
486*800a58d9SAndroid Build Coastguard Worker        sys.stderr.write("Encountered the following errors:\n%s\n\n%s.\n" %
487*800a58d9SAndroid Build Coastguard Worker                         (error_msg, help_msg))
488*800a58d9SAndroid Build Coastguard Worker        return constants.EXIT_BY_FAIL_REPORT, error_msg
489*800a58d9SAndroid Build Coastguard Worker    return constants.EXIT_SUCCESS, NO_ERROR_MESSAGE
490*800a58d9SAndroid Build Coastguard Worker
491*800a58d9SAndroid Build Coastguard Worker
492*800a58d9SAndroid Build Coastguard Workerif __name__ == "__main__":
493*800a58d9SAndroid Build Coastguard Worker    EXIT_CODE = None
494*800a58d9SAndroid Build Coastguard Worker    EXCEPTION_STACKTRACE = None
495*800a58d9SAndroid Build Coastguard Worker    EXCEPTION_LOG = None
496*800a58d9SAndroid Build Coastguard Worker    LOG_METRICS = metrics.LogUsage(sys.argv[1:])
497*800a58d9SAndroid Build Coastguard Worker    try:
498*800a58d9SAndroid Build Coastguard Worker        EXIT_CODE, EXCEPTION_STACKTRACE = main(sys.argv[1:])
499*800a58d9SAndroid Build Coastguard Worker    except Exception as e:
500*800a58d9SAndroid Build Coastguard Worker        EXIT_CODE = constants.EXIT_BY_ERROR
501*800a58d9SAndroid Build Coastguard Worker        EXCEPTION_STACKTRACE = traceback.format_exc()
502*800a58d9SAndroid Build Coastguard Worker        EXCEPTION_LOG = str(e)
503*800a58d9SAndroid Build Coastguard Worker        sys.stderr.write("Exception: %s" % (EXCEPTION_STACKTRACE))
504*800a58d9SAndroid Build Coastguard Worker
505*800a58d9SAndroid Build Coastguard Worker    # Log Exit event here to calculate the consuming time.
506*800a58d9SAndroid Build Coastguard Worker    if LOG_METRICS:
507*800a58d9SAndroid Build Coastguard Worker        metrics.LogExitEvent(EXIT_CODE,
508*800a58d9SAndroid Build Coastguard Worker                             stacktrace=EXCEPTION_STACKTRACE,
509*800a58d9SAndroid Build Coastguard Worker                             logs=EXCEPTION_LOG)
510*800a58d9SAndroid Build Coastguard Worker    sys.exit(EXIT_CODE)
511