blob: 9ecbefe1048d1131cb78f2bcdb173bdaa1c5b7e3 [file] [log] [blame]
Keun Soo Yimb293fdb2016-09-21 16:03:44 -07001#!/usr/bin/env python
2#
3# Copyright 2016 - 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.
Fang Dengfed6a6f2017-03-01 18:27:28 -080016r"""Cloud Android Driver.
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070017
18This CLI manages google compute engine project for android devices.
19
20- Prerequisites:
21 See: go/acloud-manual
22
23- Configuration:
24 The script takes a required configuration file, which should look like
25 <Start of the file>
26 # If using service account
27 service_account_name: "your_account@developer.gserviceaccount.com"
28 service_account_private_key_path: "/path/to/your-project.p12"
xingdai8a00d462018-07-30 14:24:48 -070029 # Or
30 service_account_json_private_key_path: "/path/to/your-project.json"
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070031
32 # If using OAuth2 authentication flow
33 client_id: <client id created in the project>
34 client_secret: <client secret for the client id>
35
36 # Optional
Fang Deng69498c32017-03-02 14:29:30 -080037 ssh_private_key_path: "~/.ssh/acloud_rsa"
38 ssh_public_key_path: "~/.ssh/acloud_rsa.pub"
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070039 orientation: "portrait"
40 resolution: "800x1280x32x213"
41 network: "default"
42 machine_type: "n1-standard-1"
43 extra_data_disk_size_gb: 10 # 4G or 10G
44
45 # Required
46 project: "your-project"
47 zone: "us-central1-f"
48 storage_bucket_name: "your_google_storage_bucket_name"
49 <End of the file>
50
51 Save it at /path/to/acloud.config
52
53- Example calls:
54 - Create two instances:
Kevin Chengb5963882018-05-09 00:06:27 -070055 $ acloud.par create_cf
56 --build_target aosp_cf_x86_phone-userdebug \
Fang Dengfed6a6f2017-03-01 18:27:28 -080057 --build_id 3744001 --num 2 --config_file /path/to/acloud.config \
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070058 --report_file /tmp/acloud_report.json --log_file /tmp/acloud.log
59
60 - Delete two instances:
61 $ acloud.par delete --instance_names
Fang Dengfed6a6f2017-03-01 18:27:28 -080062 ins-b638cdba-3744001-gce-x86-phone-userdebug-fastbuild3c-linux
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070063 --config_file /path/to/acloud.config
64 --report_file /tmp/acloud_report.json --log_file /tmp/acloud.log
65"""
66import argparse
67import getpass
68import logging
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070069import sys
70
Kevin Chengf4137c62018-05-22 16:06:58 -070071# Needed to silence oauth2client.
72logging.basicConfig(level=logging.CRITICAL)
Kevin Chengb5963882018-05-09 00:06:27 -070073
Kevin Chengf4137c62018-05-22 16:06:58 -070074# pylint: disable=wrong-import-position
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070075from acloud.internal import constants
76from acloud.public import acloud_common
77from acloud.public import config
78from acloud.public import device_driver
79from acloud.public import errors
Kevin Chengb5963882018-05-09 00:06:27 -070080from acloud.public.actions import create_cuttlefish_action
81from acloud.public.actions import create_goldfish_action
Kevin Chengee6030f2018-06-26 10:55:30 -070082from acloud.setup import setup
83from acloud.setup import setup_args
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070084
85LOGGING_FMT = "%(asctime)s |%(levelname)s| %(module)s:%(lineno)s| %(message)s"
Tri Vo8e292532016-10-01 16:55:51 -070086LOGGER_NAME = "acloud_main"
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070087
88# Commands
89CMD_CREATE = "create"
Kevin Chengb5963882018-05-09 00:06:27 -070090CMD_CREATE_CUTTLEFISH = "create_cf"
91CMD_CREATE_GOLDFISH = "create_gf"
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070092CMD_DELETE = "delete"
93CMD_CLEANUP = "cleanup"
Fang Deng69498c32017-03-02 14:29:30 -080094CMD_SSHKEY = "project_sshkey"
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070095
96
Kevin Cheng3031f8a2018-05-16 13:21:51 -070097# pylint: disable=too-many-statements
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070098def _ParseArgs(args):
99 """Parse args.
100
101 Args:
102 args: Argument list passed from main.
103
104 Returns:
105 Parsed args.
106 """
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700107 usage = ",".join([
Kevin Chengab0b36b2018-08-02 14:38:30 -0700108 CMD_CLEANUP,
109 CMD_CREATE,
110 CMD_CREATE_CUTTLEFISH,
111 CMD_CREATE_GOLDFISH,
112 CMD_DELETE,
113 CMD_SSHKEY,
Kevin Chengee6030f2018-06-26 10:55:30 -0700114 setup_args.CMD_SETUP,
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700115 ])
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700116 parser = argparse.ArgumentParser(
117 description=__doc__,
118 formatter_class=argparse.RawDescriptionHelpFormatter,
Kevin Cheng7ff74be2018-05-23 14:18:55 -0700119 usage="acloud {" + usage + "} ...")
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700120 subparsers = parser.add_subparsers()
121 subparser_list = []
122
123 # Command "create"
124 create_parser = subparsers.add_parser(CMD_CREATE)
125 create_parser.required = False
126 create_parser.set_defaults(which=CMD_CREATE)
127 create_parser.add_argument(
128 "--build_target",
129 type=str,
130 dest="build_target",
Kevin Chengb5963882018-05-09 00:06:27 -0700131 help="Android build target, e.g. aosp_cf_x86_phone-userdebug, "
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700132 "or short names: phone, tablet, or tablet_mobile.")
133 create_parser.add_argument(
134 "--branch",
135 type=str,
136 dest="branch",
137 help="Android branch, e.g. mnc-dev or git_mnc-dev")
Kevin Chengb5963882018-05-09 00:06:27 -0700138 # TODO: Support HEAD (the latest build)
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700139 create_parser.add_argument(
140 "--build_id",
141 type=str,
142 dest="build_id",
143 help="Android build id, e.g. 2145099, P2804227")
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700144 create_parser.add_argument(
145 "--spec",
146 type=str,
147 dest="spec",
148 required=False,
149 help="The name of a pre-configured device spec that we are "
150 "going to use. Choose from: %s" % ", ".join(constants.SPEC_NAMES))
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700151 create_parser.add_argument(
152 "--num",
153 type=int,
154 dest="num",
155 required=False,
156 default=1,
157 help="Number of instances to create.")
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700158 create_parser.add_argument(
159 "--gce_image",
160 type=str,
161 dest="gce_image",
162 required=False,
163 help="Name of an existing compute engine image to reuse.")
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700164 create_parser.add_argument(
165 "--local_disk_image",
166 type=str,
167 dest="local_disk_image",
168 required=False,
169 help="Path to a local disk image to use, "
170 "e.g /tmp/avd-system.tar.gz")
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700171 create_parser.add_argument(
172 "--no_cleanup",
173 dest="no_cleanup",
174 default=False,
175 action="store_true",
176 help="Do not clean up temporary disk image and compute engine image. "
177 "For debugging purposes.")
178 create_parser.add_argument(
179 "--serial_log_file",
180 type=str,
181 dest="serial_log_file",
182 required=False,
183 help="Path to a *tar.gz file where serial logs will be saved "
184 "when a device fails on boot.")
185 create_parser.add_argument(
186 "--logcat_file",
187 type=str,
188 dest="logcat_file",
189 required=False,
190 help="Path to a *tar.gz file where logcat logs will be saved "
191 "when a device fails on boot.")
Kevin Chengb5963882018-05-09 00:06:27 -0700192 create_parser.add_argument(
193 "--autoconnect",
194 action="store_true",
195 dest="autoconnect",
196 required=False,
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700197 help=
198 "For each instance created, we will automatically creates both 2 ssh"
Kevin Chengb5963882018-05-09 00:06:27 -0700199 " tunnels forwarding both adb & vnc. Then add the device to adb.")
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700200
201 subparser_list.append(create_parser)
202
Kevin Chengb5963882018-05-09 00:06:27 -0700203 # Command "create_cf", create cuttlefish instances
204 create_cf_parser = subparsers.add_parser(CMD_CREATE_CUTTLEFISH)
205 create_cf_parser.required = False
206 create_cf_parser.set_defaults(which=CMD_CREATE_CUTTLEFISH)
207 create_cf_parser.add_argument(
208 "--build_target",
209 type=str,
210 dest="build_target",
211 help="Android build target, should be a cuttlefish target name.")
212 create_cf_parser.add_argument(
213 "--branch",
214 type=str,
215 dest="branch",
216 help="Android branch, e.g. git_master")
217 create_cf_parser.add_argument(
218 "--build_id",
219 type=str,
220 dest="build_id",
221 help="Android build id, e.g. 2145099, P2804227")
222 create_cf_parser.add_argument(
223 "--kernel_build_id",
224 type=str,
225 dest="kernel_build_id",
226 required=False,
227 help="Android kernel build id, e.g. 4586590. This is to test a new"
228 " kernel build with a particular Android build (--build_id). If not"
229 " specified, the kernel that's bundled with the Android build would"
230 " be used.")
231 create_cf_parser.add_argument(
232 "--num",
233 type=int,
234 dest="num",
235 required=False,
236 default=1,
237 help="Number of instances to create.")
238 create_cf_parser.add_argument(
239 "--serial_log_file",
240 type=str,
241 dest="serial_log_file",
242 required=False,
243 help="Path to a *tar.gz file where serial logs will be saved "
244 "when a device fails on boot.")
245 create_cf_parser.add_argument(
246 "--logcat_file",
247 type=str,
248 dest="logcat_file",
249 required=False,
250 help="Path to a *tar.gz file where logcat logs will be saved "
251 "when a device fails on boot.")
252 create_cf_parser.add_argument(
253 "--autoconnect",
254 action="store_true",
255 dest="autoconnect",
256 required=False,
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700257 help=
258 "For each instance created, we will automatically creates both 2 ssh"
Kevin Chengb5963882018-05-09 00:06:27 -0700259 " tunnels forwarding both adb & vnc. Then add the device to adb.")
260
261 subparser_list.append(create_cf_parser)
262
263 # Command "create_gf", create goldfish instances
264 # In order to create a goldfish device we need the following parameters:
265 # 1. The emulator build we wish to use, this is the binary that emulates
266 # an android device. See go/emu-dev for more
267 # 2. A system-image. This is the android release we wish to run on the
268 # emulated hardware.
269 create_gf_parser = subparsers.add_parser(CMD_CREATE_GOLDFISH)
270 create_gf_parser.required = False
271 create_gf_parser.set_defaults(which=CMD_CREATE_GOLDFISH)
272 create_gf_parser.add_argument(
273 "--build_target",
274 type=str,
275 dest="build_target",
276 help="Android build target, should be a goldfish target name.")
277 create_gf_parser.add_argument(
278 "--branch",
279 type=str,
280 dest="branch",
281 help="Android branch, e.g. git_master")
282 create_gf_parser.add_argument(
283 "--build_id",
284 type=str,
285 dest="build_id",
286 help="Android build id, e.g. 4669424, P2804227")
287 create_gf_parser.add_argument(
288 "--emulator_build_id",
289 type=str,
290 dest="emulator_build_id",
291 required=False,
292 help="Emulator build used to run the images. e.g. 4669466.")
293 create_gf_parser.add_argument(
294 "--gpu",
295 type=str,
296 dest="gpu",
297 required=False,
298 default=None,
299 help="GPU accelerator to use if any."
300 " e.g. nvidia-tesla-k80, omit to use swiftshader")
301 create_gf_parser.add_argument(
302 "--num",
303 type=int,
304 dest="num",
305 required=False,
306 default=1,
307 help="Number of instances to create.")
308 create_gf_parser.add_argument(
309 "--serial_log_file",
310 type=str,
311 dest="serial_log_file",
312 required=False,
313 help="Path to a *tar.gz file where serial logs will be saved "
314 "when a device fails on boot.")
315 create_gf_parser.add_argument(
316 "--logcat_file",
317 type=str,
318 dest="logcat_file",
319 required=False,
320 help="Path to a *tar.gz file where logcat logs will be saved "
321 "when a device fails on boot.")
322 create_gf_parser.add_argument(
323 "--autoconnect",
324 action="store_true",
325 dest="autoconnect",
326 required=False,
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700327 help=
328 "For each instance created, we will automatically creates both 2 ssh"
Kevin Chengb5963882018-05-09 00:06:27 -0700329 " tunnels forwarding both adb & vnc. Then add the device to adb.")
Kevin Chengbced4af2018-06-26 10:35:01 -0700330 create_gf_parser.add_argument(
331 "--base_image",
332 type=str,
333 dest="base_image",
334 required=False,
335 help="Name of the goldfish base image to be used to create the instance. "
336 "This will override stable_goldfish_host_image_name from config. "
337 "e.g. emu-dev-cts-061118")
Kevin Chengb5963882018-05-09 00:06:27 -0700338
339 subparser_list.append(create_gf_parser)
340
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700341 # Command "Delete"
342 delete_parser = subparsers.add_parser(CMD_DELETE)
343 delete_parser.required = False
344 delete_parser.set_defaults(which=CMD_DELETE)
345 delete_parser.add_argument(
346 "--instance_names",
347 dest="instance_names",
348 nargs="+",
349 required=True,
350 help="The names of the instances that need to delete, "
351 "separated by spaces, e.g. --instance_names instance-1 instance-2")
352 subparser_list.append(delete_parser)
353
354 # Command "cleanup"
355 cleanup_parser = subparsers.add_parser(CMD_CLEANUP)
356 cleanup_parser.required = False
357 cleanup_parser.set_defaults(which=CMD_CLEANUP)
358 cleanup_parser.add_argument(
359 "--expiration_mins",
360 type=int,
361 dest="expiration_mins",
362 required=True,
363 help="Garbage collect all gce instances, gce images, cached disk "
364 "images that are older than |expiration_mins|.")
365 subparser_list.append(cleanup_parser)
366
Fang Deng69498c32017-03-02 14:29:30 -0800367 # Command "project_sshkey"
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700368 sshkey_parser = subparsers.add_parser(CMD_SSHKEY)
369 sshkey_parser.required = False
370 sshkey_parser.set_defaults(which=CMD_SSHKEY)
371 sshkey_parser.add_argument(
372 "--user",
373 type=str,
374 dest="user",
375 default=getpass.getuser(),
376 help="The user name which the sshkey belongs to, default to: %s." %
377 getpass.getuser())
378 sshkey_parser.add_argument(
379 "--ssh_rsa_path",
380 type=str,
381 dest="ssh_rsa_path",
382 required=True,
Fang Deng69498c32017-03-02 14:29:30 -0800383 help="Absolute path to the file that contains the public rsa key "
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700384 "that will be added as project-wide ssh key.")
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700385 subparser_list.append(sshkey_parser)
386
Kevin Chengee6030f2018-06-26 10:55:30 -0700387 # Command "setup"
388 subparser_list.append(setup_args.GetSetupArgParser(subparsers))
389
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700390 # Add common arguments.
Kevin Chengb21d7712018-05-24 14:54:55 -0700391 for subparser in subparser_list:
392 acloud_common.AddCommonArguments(subparser)
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700393
394 return parser.parse_args(args)
395
396
397def _TranslateAlias(parsed_args):
398 """Translate alias to Launch Control compatible values.
399
400 This method translates alias to Launch Control compatible values.
401 - branch: "git_" prefix will be added if branch name doesn't have it.
402 - build_target: For example, "phone" will be translated to full target
403 name "git_x86_phone-userdebug",
404
405 Args:
406 parsed_args: Parsed args.
407
408 Returns:
409 Parsed args with its values being translated.
410 """
411 if parsed_args.which == CMD_CREATE:
412 if (parsed_args.branch and
413 not parsed_args.branch.startswith(constants.BRANCH_PREFIX)):
414 parsed_args.branch = constants.BRANCH_PREFIX + parsed_args.branch
415 parsed_args.build_target = constants.BUILD_TARGET_MAPPING.get(
416 parsed_args.build_target, parsed_args.build_target)
417 return parsed_args
418
419
420def _VerifyArgs(parsed_args):
421 """Verify args.
422
423 Args:
424 parsed_args: Parsed args.
425
426 Raises:
427 errors.CommandArgError: If args are invalid.
428 """
429 if parsed_args.which == CMD_CREATE:
430 if (parsed_args.spec and parsed_args.spec not in constants.SPEC_NAMES):
431 raise errors.CommandArgError(
432 "%s is not valid. Choose from: %s" %
433 (parsed_args.spec, ", ".join(constants.SPEC_NAMES)))
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700434 if not ((parsed_args.build_id and parsed_args.build_target)
435 or parsed_args.gce_image or parsed_args.local_disk_image):
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700436 raise errors.CommandArgError(
437 "At least one of the following should be specified: "
438 "--build_id and --build_target, or --gce_image, or "
439 "--local_disk_image.")
440 if bool(parsed_args.build_id) != bool(parsed_args.build_target):
441 raise errors.CommandArgError(
442 "Must specify --build_id and --build_target at the same time.")
Kevin Chengb5963882018-05-09 00:06:27 -0700443
444 if parsed_args.which in [CMD_CREATE_CUTTLEFISH, CMD_CREATE_GOLDFISH]:
445 if not parsed_args.build_id or not parsed_args.build_target:
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700446 raise errors.CommandArgError(
447 "Must specify --build_id and --build_target")
Kevin Chengb5963882018-05-09 00:06:27 -0700448
449 if parsed_args.which == CMD_CREATE_GOLDFISH:
450 if not parsed_args.emulator_build_id:
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700451 raise errors.CommandArgError("Must specify --emulator_build_id")
Kevin Chengb5963882018-05-09 00:06:27 -0700452
453 if parsed_args.which in [
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700454 CMD_CREATE, CMD_CREATE_CUTTLEFISH, CMD_CREATE_GOLDFISH
Kevin Chengb5963882018-05-09 00:06:27 -0700455 ]:
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700456 if (parsed_args.serial_log_file
457 and not parsed_args.serial_log_file.endswith(".tar.gz")):
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700458 raise errors.CommandArgError(
459 "--serial_log_file must ends with .tar.gz")
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700460 if (parsed_args.logcat_file
461 and not parsed_args.logcat_file.endswith(".tar.gz")):
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700462 raise errors.CommandArgError(
463 "--logcat_file must ends with .tar.gz")
464
465
466def _SetupLogging(log_file, verbose, very_verbose):
467 """Setup logging.
468
469 Args:
470 log_file: path to log file.
471 verbose: If True, log at DEBUG level, otherwise log at INFO level.
472 very_verbose: If True, log at DEBUG level and turn on logging on
473 all libraries. Take take precedence over |verbose|.
474 """
475 if very_verbose:
476 logger = logging.getLogger()
477 else:
478 logger = logging.getLogger(LOGGER_NAME)
479
480 logging_level = logging.DEBUG if verbose or very_verbose else logging.INFO
481 logger.setLevel(logging_level)
482
Sam Chiufde41e92018-08-07 18:37:02 +0800483 if log_file:
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700484 handler = logging.FileHandler(filename=log_file)
Sam Chiufde41e92018-08-07 18:37:02 +0800485 log_formatter = logging.Formatter(LOGGING_FMT)
486 handler.setFormatter(log_formatter)
487 logger.addHandler(handler)
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700488
489
490def main(argv):
491 """Main entry.
492
493 Args:
494 argv: A list of system arguments.
495
496 Returns:
497 0 if success. None-zero if fails.
498 """
499 args = _ParseArgs(argv)
500 _SetupLogging(args.log_file, args.verbose, args.very_verbose)
501 args = _TranslateAlias(args)
502 _VerifyArgs(args)
503
504 config_mgr = config.AcloudConfigManager(args.config_file)
505 cfg = config_mgr.Load()
506 cfg.OverrideWithArgs(args)
507
Fang Dengcef4b112017-03-02 11:20:17 -0800508 # Check access.
509 device_driver.CheckAccess(cfg)
510
Kevin Chengee6030f2018-06-26 10:55:30 -0700511 report = None
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700512 if args.which == CMD_CREATE:
513 report = device_driver.CreateAndroidVirtualDevices(
514 cfg,
515 args.build_target,
516 args.build_id,
517 args.num,
518 args.gce_image,
519 args.local_disk_image,
520 cleanup=not args.no_cleanup,
521 serial_log_file=args.serial_log_file,
Kevin Chengb5963882018-05-09 00:06:27 -0700522 logcat_file=args.logcat_file,
523 autoconnect=args.autoconnect)
524 elif args.which == CMD_CREATE_CUTTLEFISH:
525 report = create_cuttlefish_action.CreateDevices(
526 cfg=cfg,
527 build_target=args.build_target,
528 build_id=args.build_id,
529 kernel_build_id=args.kernel_build_id,
530 num=args.num,
531 serial_log_file=args.serial_log_file,
532 logcat_file=args.logcat_file,
533 autoconnect=args.autoconnect)
534 elif args.which == CMD_CREATE_GOLDFISH:
535 report = create_goldfish_action.CreateDevices(
536 cfg=cfg,
537 build_target=args.build_target,
538 build_id=args.build_id,
539 emulator_build_id=args.emulator_build_id,
540 gpu=args.gpu,
541 num=args.num,
542 serial_log_file=args.serial_log_file,
543 logcat_file=args.logcat_file,
544 autoconnect=args.autoconnect)
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700545 elif args.which == CMD_DELETE:
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700546 report = device_driver.DeleteAndroidVirtualDevices(
547 cfg, args.instance_names)
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700548 elif args.which == CMD_CLEANUP:
549 report = device_driver.Cleanup(cfg, args.expiration_mins)
550 elif args.which == CMD_SSHKEY:
551 report = device_driver.AddSshRsa(cfg, args.user, args.ssh_rsa_path)
Kevin Chengee6030f2018-06-26 10:55:30 -0700552 elif args.which == setup_args.CMD_SETUP:
553 setup.Run(args)
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700554 else:
555 sys.stderr.write("Invalid command %s" % args.which)
556 return 2
557
Kevin Chengee6030f2018-06-26 10:55:30 -0700558 if report:
559 report.Dump(args.report_file)
560 if report.errors:
561 msg = "\n".join(report.errors)
562 sys.stderr.write("Encountered the following errors:\n%s\n" % msg)
563 return 1
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700564 return 0
Tri Vo8e292532016-10-01 16:55:51 -0700565
566
567if __name__ == "__main__":
568 main(sys.argv[1:])