blob: 780a61d4e7502b922646b6a4b149c37824e2fd7d [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.
Sam Chiu42ac7c52018-10-22 12:27:34 +080016r"""
17Welcome to
18 ___ _______ ____ __ _____
19 / _ |/ ___/ / / __ \/ / / / _ \
20 / __ / /__/ /__/ /_/ / /_/ / // /
21/_/ |_\___/____/\____/\____/____/
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070022
Sam Chiu42ac7c52018-10-22 12:27:34 +080023
24This a tool to create Android Virtual Devices locally/remotely.
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070025
26- Prerequisites:
Sam Chiu42ac7c52018-10-22 12:27:34 +080027 The manual will be available at
28 https://android.googlesource.com/platform/tools/acloud/+/master/README.md
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070029
Sam Chiu42ac7c52018-10-22 12:27:34 +080030- To get started:
31 - Create instances:
32 1) To create a remote cuttlefish instance with the local built image.
33 Example:
chojoyce1c4ecc92018-12-06 14:16:44 +080034 $ acloud create --local-image
35 Or specify built image dir:
36 $ acloud create --local-image /tmp/image_dir
Sam Chiu42ac7c52018-10-22 12:27:34 +080037 2) To create a local cuttlefish instance using the image which has been
38 built out in your workspace.
39 Example:
40 $ acloud create --local-instance --local-image
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070041
Sam Chiu42ac7c52018-10-22 12:27:34 +080042 - Delete instances:
43 $ acloud delete
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070044
Sam Chiu42ac7c52018-10-22 12:27:34 +080045Try $acloud [cmd] --help for further details.
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070046
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070047"""
48import argparse
49import getpass
50import logging
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070051import sys
52
Kevin Chengf4137c62018-05-22 16:06:58 -070053# Needed to silence oauth2client.
Sam Chiu29d858f2018-08-14 20:06:25 +080054# This is a workaround to get rid of below warning message:
55# 'No handlers could be found for logger "oauth2client.contrib.multistore_file'
56# TODO(b/112803893): Remove this code once bug is fixed.
57OAUTH2_LOGGER = logging.getLogger('oauth2client.contrib.multistore_file')
58OAUTH2_LOGGER.setLevel(logging.CRITICAL)
59OAUTH2_LOGGER.addHandler(logging.FileHandler("/dev/null"))
Kevin Chengb5963882018-05-09 00:06:27 -070060
Kevin Chengf4137c62018-05-22 16:06:58 -070061# pylint: disable=wrong-import-position
Sam Chiu7de3b232018-12-06 19:45:52 +080062from acloud import errors
Kevin Cheng6001db32018-10-23 12:34:20 -070063from acloud.create import create
64from acloud.create import create_args
65from acloud.delete import delete
66from acloud.delete import delete_args
cylan4569dca2018-11-02 12:12:53 +080067from acloud.reconnect import reconnect
68from acloud.reconnect import reconnect_args
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070069from acloud.internal import constants
Sam Chiu56c58892018-10-25 09:53:19 +080070from acloud.list import list as list_instances
71from acloud.list import list_args
Kevin Cheng6001db32018-10-23 12:34:20 -070072from acloud.metrics import metrics
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070073from acloud.public import acloud_common
74from acloud.public import config
75from acloud.public import device_driver
Kevin Chengb5963882018-05-09 00:06:27 -070076from acloud.public.actions import create_cuttlefish_action
77from acloud.public.actions import create_goldfish_action
Kevin Chengee6030f2018-06-26 10:55:30 -070078from acloud.setup import setup
79from acloud.setup import setup_args
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070080
Sam Chiu445941f2018-10-04 11:54:40 +080081LOGGING_FMT = "%(asctime)s |%(levelname)s| %(module)s:%(lineno)s| %(message)s"
Sam Chiu29d858f2018-08-14 20:06:25 +080082ACLOUD_LOGGER = "acloud"
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070083
84# Commands
Kevin Chengb5963882018-05-09 00:06:27 -070085CMD_CREATE_CUTTLEFISH = "create_cf"
86CMD_CREATE_GOLDFISH = "create_gf"
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070087CMD_CLEANUP = "cleanup"
Fang Deng69498c32017-03-02 14:29:30 -080088CMD_SSHKEY = "project_sshkey"
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070089
90
Kevin Cheng3031f8a2018-05-16 13:21:51 -070091# pylint: disable=too-many-statements
Keun Soo Yimb293fdb2016-09-21 16:03:44 -070092def _ParseArgs(args):
93 """Parse args.
94
95 Args:
96 args: Argument list passed from main.
97
98 Returns:
99 Parsed args.
100 """
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700101 usage = ",".join([
Sam Chiue669ef72018-10-16 16:23:37 +0800102 setup_args.CMD_SETUP,
103 create_args.CMD_CREATE,
Kevin Chengab0b36b2018-08-02 14:38:30 -0700104 CMD_CREATE_CUTTLEFISH,
105 CMD_CREATE_GOLDFISH,
Sam Chiu56c58892018-10-25 09:53:19 +0800106 list_args.CMD_LIST,
Kevin Chengeb85e862018-10-09 15:35:13 -0700107 delete_args.CMD_DELETE,
cylan4569dca2018-11-02 12:12:53 +0800108 reconnect_args.CMD_RECONNECT,
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700109 ])
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700110 parser = argparse.ArgumentParser(
111 description=__doc__,
112 formatter_class=argparse.RawDescriptionHelpFormatter,
Sam Chiu42ac7c52018-10-22 12:27:34 +0800113 usage="acloud {" + usage + "} ...")
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700114 subparsers = parser.add_subparsers()
115 subparser_list = []
116
Kevin Chengb5963882018-05-09 00:06:27 -0700117 # Command "create_cf", create cuttlefish instances
118 create_cf_parser = subparsers.add_parser(CMD_CREATE_CUTTLEFISH)
119 create_cf_parser.required = False
120 create_cf_parser.set_defaults(which=CMD_CREATE_CUTTLEFISH)
121 create_cf_parser.add_argument(
122 "--build_target",
123 type=str,
124 dest="build_target",
125 help="Android build target, should be a cuttlefish target name.")
126 create_cf_parser.add_argument(
127 "--branch",
128 type=str,
129 dest="branch",
130 help="Android branch, e.g. git_master")
131 create_cf_parser.add_argument(
132 "--build_id",
133 type=str,
134 dest="build_id",
135 help="Android build id, e.g. 2145099, P2804227")
136 create_cf_parser.add_argument(
137 "--kernel_build_id",
138 type=str,
139 dest="kernel_build_id",
140 required=False,
141 help="Android kernel build id, e.g. 4586590. This is to test a new"
142 " kernel build with a particular Android build (--build_id). If not"
143 " specified, the kernel that's bundled with the Android build would"
144 " be used.")
Kevin Chengb5963882018-05-09 00:06:27 -0700145
Kevin Cheng3087af52018-08-13 13:26:50 -0700146 create_args.AddCommonCreateArgs(create_cf_parser)
Kevin Chengb5963882018-05-09 00:06:27 -0700147 subparser_list.append(create_cf_parser)
148
149 # Command "create_gf", create goldfish instances
150 # In order to create a goldfish device we need the following parameters:
151 # 1. The emulator build we wish to use, this is the binary that emulates
152 # an android device. See go/emu-dev for more
153 # 2. A system-image. This is the android release we wish to run on the
154 # emulated hardware.
155 create_gf_parser = subparsers.add_parser(CMD_CREATE_GOLDFISH)
156 create_gf_parser.required = False
157 create_gf_parser.set_defaults(which=CMD_CREATE_GOLDFISH)
158 create_gf_parser.add_argument(
159 "--build_target",
160 type=str,
161 dest="build_target",
162 help="Android build target, should be a goldfish target name.")
163 create_gf_parser.add_argument(
164 "--branch",
165 type=str,
166 dest="branch",
167 help="Android branch, e.g. git_master")
168 create_gf_parser.add_argument(
169 "--build_id",
170 type=str,
171 dest="build_id",
172 help="Android build id, e.g. 4669424, P2804227")
173 create_gf_parser.add_argument(
174 "--emulator_build_id",
175 type=str,
176 dest="emulator_build_id",
177 required=False,
178 help="Emulator build used to run the images. e.g. 4669466.")
179 create_gf_parser.add_argument(
180 "--gpu",
181 type=str,
182 dest="gpu",
183 required=False,
184 default=None,
185 help="GPU accelerator to use if any."
186 " e.g. nvidia-tesla-k80, omit to use swiftshader")
187 create_gf_parser.add_argument(
Kevin Chengbced4af2018-06-26 10:35:01 -0700188 "--base_image",
189 type=str,
190 dest="base_image",
191 required=False,
192 help="Name of the goldfish base image to be used to create the instance. "
193 "This will override stable_goldfish_host_image_name from config. "
194 "e.g. emu-dev-cts-061118")
Kevin Chengb5963882018-05-09 00:06:27 -0700195
Kevin Cheng3087af52018-08-13 13:26:50 -0700196 create_args.AddCommonCreateArgs(create_gf_parser)
Kevin Chengb5963882018-05-09 00:06:27 -0700197 subparser_list.append(create_gf_parser)
198
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700199 # Command "cleanup"
200 cleanup_parser = subparsers.add_parser(CMD_CLEANUP)
201 cleanup_parser.required = False
202 cleanup_parser.set_defaults(which=CMD_CLEANUP)
203 cleanup_parser.add_argument(
204 "--expiration_mins",
205 type=int,
206 dest="expiration_mins",
207 required=True,
208 help="Garbage collect all gce instances, gce images, cached disk "
209 "images that are older than |expiration_mins|.")
210 subparser_list.append(cleanup_parser)
211
Fang Deng69498c32017-03-02 14:29:30 -0800212 # Command "project_sshkey"
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700213 sshkey_parser = subparsers.add_parser(CMD_SSHKEY)
214 sshkey_parser.required = False
215 sshkey_parser.set_defaults(which=CMD_SSHKEY)
216 sshkey_parser.add_argument(
217 "--user",
218 type=str,
219 dest="user",
220 default=getpass.getuser(),
221 help="The user name which the sshkey belongs to, default to: %s." %
222 getpass.getuser())
223 sshkey_parser.add_argument(
224 "--ssh_rsa_path",
225 type=str,
226 dest="ssh_rsa_path",
227 required=True,
Fang Deng69498c32017-03-02 14:29:30 -0800228 help="Absolute path to the file that contains the public rsa key "
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700229 "that will be added as project-wide ssh key.")
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700230 subparser_list.append(sshkey_parser)
231
Kevin Chengeb85e862018-10-09 15:35:13 -0700232 # Command "create"
233 subparser_list.append(create_args.GetCreateArgParser(subparsers))
234
Kevin Chengee6030f2018-06-26 10:55:30 -0700235 # Command "setup"
236 subparser_list.append(setup_args.GetSetupArgParser(subparsers))
237
Sam Chiu56c58892018-10-25 09:53:19 +0800238 # Command "delete"
Kevin Chengeb85e862018-10-09 15:35:13 -0700239 subparser_list.append(delete_args.GetDeleteArgParser(subparsers))
240
Sam Chiu56c58892018-10-25 09:53:19 +0800241 # Command "list"
242 subparser_list.append(list_args.GetListArgParser(subparsers))
243
cylan4569dca2018-11-02 12:12:53 +0800244 # Command "Reconnect"
245 subparser_list.append(reconnect_args.GetReconnectArgParser(subparsers))
246
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700247 # Add common arguments.
Kevin Chengb21d7712018-05-24 14:54:55 -0700248 for subparser in subparser_list:
249 acloud_common.AddCommonArguments(subparser)
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700250
251 return parser.parse_args(args)
252
253
herbertxue2625b042018-08-16 23:28:20 +0800254# pylint: disable=too-many-branches
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700255def _VerifyArgs(parsed_args):
256 """Verify args.
257
258 Args:
259 parsed_args: Parsed args.
260
261 Raises:
262 errors.CommandArgError: If args are invalid.
263 """
herbertxue2625b042018-08-16 23:28:20 +0800264 if parsed_args.which == create_args.CMD_CREATE:
265 create_args.VerifyArgs(parsed_args)
266
Kevin Cheng3087af52018-08-13 13:26:50 -0700267 if (parsed_args.which == create_args.CMD_CREATE
268 and parsed_args.avd_type == constants.TYPE_GCE):
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700269 if (parsed_args.spec and parsed_args.spec not in constants.SPEC_NAMES):
270 raise errors.CommandArgError(
271 "%s is not valid. Choose from: %s" %
272 (parsed_args.spec, ", ".join(constants.SPEC_NAMES)))
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700273 if not ((parsed_args.build_id and parsed_args.build_target)
274 or parsed_args.gce_image or parsed_args.local_disk_image):
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700275 raise errors.CommandArgError(
276 "At least one of the following should be specified: "
277 "--build_id and --build_target, or --gce_image, or "
278 "--local_disk_image.")
279 if bool(parsed_args.build_id) != bool(parsed_args.build_target):
280 raise errors.CommandArgError(
281 "Must specify --build_id and --build_target at the same time.")
Kevin Chengb5963882018-05-09 00:06:27 -0700282
Kevin Cheng84d3eed2018-08-16 15:16:00 -0700283 if parsed_args.which == CMD_CREATE_CUTTLEFISH:
Kevin Chengb5963882018-05-09 00:06:27 -0700284 if not parsed_args.build_id or not parsed_args.build_target:
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700285 raise errors.CommandArgError(
286 "Must specify --build_id and --build_target")
Kevin Chengb5963882018-05-09 00:06:27 -0700287
288 if parsed_args.which == CMD_CREATE_GOLDFISH:
Kevin Cheng84d3eed2018-08-16 15:16:00 -0700289 if not parsed_args.emulator_build_id and not parsed_args.build_id:
290 raise errors.CommandArgError("Must specify either "
291 "--emulator_build_id or --build_id")
292 if not parsed_args.build_target:
293 raise errors.CommandArgError("Must specify --build_target")
Kevin Chengb5963882018-05-09 00:06:27 -0700294
295 if parsed_args.which in [
Kevin Cheng3087af52018-08-13 13:26:50 -0700296 create_args.CMD_CREATE, CMD_CREATE_CUTTLEFISH, CMD_CREATE_GOLDFISH
Kevin Chengb5963882018-05-09 00:06:27 -0700297 ]:
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700298 if (parsed_args.serial_log_file
299 and not parsed_args.serial_log_file.endswith(".tar.gz")):
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700300 raise errors.CommandArgError(
301 "--serial_log_file must ends with .tar.gz")
Kevin Cheng3031f8a2018-05-16 13:21:51 -0700302 if (parsed_args.logcat_file
303 and not parsed_args.logcat_file.endswith(".tar.gz")):
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700304 raise errors.CommandArgError(
305 "--logcat_file must ends with .tar.gz")
306
307
Sam Chiu29d858f2018-08-14 20:06:25 +0800308def _SetupLogging(log_file, verbose):
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700309 """Setup logging.
310
Sam Chiu29d858f2018-08-14 20:06:25 +0800311 This function define the logging policy in below manners.
312 - without -v , -vv ,--log_file:
313 Only display critical log and print() message on screen.
314
315 - with -v:
316 Display INFO log and set StreamHandler to acloud parent logger to turn on
317 ONLY acloud modules logging.(silence all 3p libraries)
318
319 - with -vv:
320 Display INFO/DEBUG log and set StreamHandler to root logger to turn on all
321 acloud modules and 3p libraries logging.
322
323 - with --log_file.
324 Dump logs to FileHandler with DEBUG level.
325
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700326 Args:
Sam Chiu29d858f2018-08-14 20:06:25 +0800327 log_file: String, if not None, dump the log to log file.
328 verbose: Int, if verbose = 1(-v), log at INFO level and turn on
329 logging on libraries to a StreamHandler.
330 If verbose = 2(-vv), log at DEBUG level and turn on logging on
331 all libraries and 3rd party libraries to a StreamHandler.
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700332 """
Sam Chiu29d858f2018-08-14 20:06:25 +0800333 # Define logging level and hierarchy by verbosity.
334 shandler_level = None
335 logger = None
336 if verbose == 0:
337 shandler_level = logging.CRITICAL
338 logger = logging.getLogger(ACLOUD_LOGGER)
339 elif verbose == 1:
340 shandler_level = logging.INFO
341 logger = logging.getLogger(ACLOUD_LOGGER)
342 elif verbose > 1:
343 shandler_level = logging.DEBUG
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700344 logger = logging.getLogger()
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700345
Sam Chiu29d858f2018-08-14 20:06:25 +0800346 # Add StreamHandler by default.
347 shandler = logging.StreamHandler()
348 shandler.setFormatter(logging.Formatter(LOGGING_FMT))
349 shandler.setLevel(shandler_level)
350 logger.addHandler(shandler)
351 # Set the default level to DEBUG, the other handlers will handle
352 # their own levels via the args supplied (-v and --log_file).
353 logger.setLevel(logging.DEBUG)
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700354
Sam Chiu29d858f2018-08-14 20:06:25 +0800355 # Add FileHandler if log_file is provided.
Sam Chiufde41e92018-08-07 18:37:02 +0800356 if log_file:
Sam Chiu29d858f2018-08-14 20:06:25 +0800357 fhandler = logging.FileHandler(filename=log_file)
358 fhandler.setFormatter(logging.Formatter(LOGGING_FMT))
359 fhandler.setLevel(logging.DEBUG)
360 logger.addHandler(fhandler)
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700361
362
Erwin Jansen95559242018-11-08 15:38:18 -0800363def main(argv=None):
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700364 """Main entry.
365
366 Args:
367 argv: A list of system arguments.
368
369 Returns:
370 0 if success. None-zero if fails.
371 """
Erwin Jansen95559242018-11-08 15:38:18 -0800372 if argv is None:
373 argv = sys.argv[1:]
374
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700375 args = _ParseArgs(argv)
Sam Chiu29d858f2018-08-14 20:06:25 +0800376 _SetupLogging(args.log_file, args.verbose)
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700377 _VerifyArgs(args)
378
Sam Chiuc64f3432018-08-17 11:19:06 +0800379 cfg = config.GetAcloudConfig(args)
Kevin Cheng3087af52018-08-13 13:26:50 -0700380 # TODO: Move this check into the functions it is actually needed.
Fang Dengcef4b112017-03-02 11:20:17 -0800381 # Check access.
Kevin Cheng3087af52018-08-13 13:26:50 -0700382 # device_driver.CheckAccess(cfg)
Fang Dengcef4b112017-03-02 11:20:17 -0800383
Kevin Cheng6001db32018-10-23 12:34:20 -0700384 metrics.LogUsage()
Kevin Chengee6030f2018-06-26 10:55:30 -0700385 report = None
Kevin Cheng3087af52018-08-13 13:26:50 -0700386 if (args.which == create_args.CMD_CREATE
387 and args.avd_type == constants.TYPE_GCE):
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700388 report = device_driver.CreateAndroidVirtualDevices(
389 cfg,
390 args.build_target,
391 args.build_id,
392 args.num,
393 args.gce_image,
394 args.local_disk_image,
395 cleanup=not args.no_cleanup,
396 serial_log_file=args.serial_log_file,
Kevin Chengb5963882018-05-09 00:06:27 -0700397 logcat_file=args.logcat_file,
Kevin Cheng86d43c72018-08-30 10:59:14 -0700398 autoconnect=args.autoconnect,
399 report_internal_ip=args.report_internal_ip)
Kevin Cheng3087af52018-08-13 13:26:50 -0700400 elif args.which == create_args.CMD_CREATE:
Kevin Chengc3d0d5e2018-08-14 14:22:44 -0700401 create.Run(args)
Kevin Chengb5963882018-05-09 00:06:27 -0700402 elif args.which == CMD_CREATE_CUTTLEFISH:
403 report = create_cuttlefish_action.CreateDevices(
404 cfg=cfg,
405 build_target=args.build_target,
406 build_id=args.build_id,
407 kernel_build_id=args.kernel_build_id,
408 num=args.num,
409 serial_log_file=args.serial_log_file,
410 logcat_file=args.logcat_file,
Kevin Cheng86d43c72018-08-30 10:59:14 -0700411 autoconnect=args.autoconnect,
412 report_internal_ip=args.report_internal_ip)
Kevin Chengb5963882018-05-09 00:06:27 -0700413 elif args.which == CMD_CREATE_GOLDFISH:
414 report = create_goldfish_action.CreateDevices(
415 cfg=cfg,
416 build_target=args.build_target,
417 build_id=args.build_id,
418 emulator_build_id=args.emulator_build_id,
419 gpu=args.gpu,
420 num=args.num,
421 serial_log_file=args.serial_log_file,
422 logcat_file=args.logcat_file,
Kevin Cheng84d3eed2018-08-16 15:16:00 -0700423 autoconnect=args.autoconnect,
Kevin Cheng86d43c72018-08-30 10:59:14 -0700424 branch=args.branch,
425 report_internal_ip=args.report_internal_ip)
Sam Chiu56c58892018-10-25 09:53:19 +0800426 elif args.which == delete_args.CMD_DELETE:
Kevin Chengeb85e862018-10-09 15:35:13 -0700427 report = delete.Run(args)
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700428 elif args.which == CMD_CLEANUP:
429 report = device_driver.Cleanup(cfg, args.expiration_mins)
Sam Chiu56c58892018-10-25 09:53:19 +0800430 elif args.which == list_args.CMD_LIST:
431 list_instances.Run(args)
cylan4569dca2018-11-02 12:12:53 +0800432 elif args.which == reconnect_args.CMD_RECONNECT:
433 reconnect.Run(args)
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700434 elif args.which == CMD_SSHKEY:
435 report = device_driver.AddSshRsa(cfg, args.user, args.ssh_rsa_path)
Kevin Chengee6030f2018-06-26 10:55:30 -0700436 elif args.which == setup_args.CMD_SETUP:
herbertxue34776bb2018-07-03 21:57:48 +0800437 setup.Run(args)
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700438 else:
439 sys.stderr.write("Invalid command %s" % args.which)
440 return 2
441
herbertxue07293a32018-11-05 20:40:11 +0800442 if report and args.report_file:
Kevin Chengee6030f2018-06-26 10:55:30 -0700443 report.Dump(args.report_file)
444 if report.errors:
445 msg = "\n".join(report.errors)
446 sys.stderr.write("Encountered the following errors:\n%s\n" % msg)
447 return 1
Keun Soo Yimb293fdb2016-09-21 16:03:44 -0700448 return 0
Tri Vo8e292532016-10-01 16:55:51 -0700449
450
451if __name__ == "__main__":
452 main(sys.argv[1:])