1# Copyright 2018 - The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14r"""Create args. 15 16Defines the create arg parser that holds create specific args. 17""" 18 19import argparse 20import logging 21import os 22 23from acloud import errors 24from acloud.create import create_common 25from acloud.internal import constants 26from acloud.internal.lib import utils 27 28logger = logging.getLogger(__name__) 29_DEFAULT_GPU = "default" 30CMD_CREATE = "create" 31 32 33# TODO: Add this into main create args once create_cf/gf is deprecated. 34# pylint: disable=too-many-statements 35def AddCommonCreateArgs(parser): 36 """Adds arguments common to create parsers. 37 38 Args: 39 parser: ArgumentParser object, used to parse flags. 40 """ 41 parser.add_argument( 42 "--num", 43 type=int, 44 dest="num", 45 required=False, 46 default=1, 47 help="Number of instances to create.") 48 parser.add_argument( 49 "--serial-log-file", 50 type=str, 51 dest="serial_log_file", 52 required=False, 53 help="Path to a *tar.gz file where serial logs will be saved " 54 "when a device fails on boot.") 55 parser.add_argument( 56 "--autoconnect", 57 type=str, 58 nargs="?", 59 const=constants.INS_KEY_WEBRTC, 60 dest="autoconnect", 61 required=False, 62 choices=[constants.INS_KEY_VNC, constants.INS_KEY_ADB, 63 constants.INS_KEY_WEBRTC], 64 help="Determines to establish a tunnel forwarding adb/vnc and " 65 "launch VNC/webrtc. Establish a tunnel forwarding adb and vnc " 66 "then launch vnc if --autoconnect vnc is provided. Establish a " 67 "tunnel forwarding adb if --autoconnect adb is provided. " 68 "Establish a tunnel forwarding adb and auto-launch on the browser " 69 "if --autoconnect webrtc is provided. For local goldfish " 70 "instance, create a window.") 71 parser.add_argument( 72 "--no-autoconnect", 73 action="store_false", 74 dest="autoconnect", 75 required=False, 76 help="Will not automatically create ssh tunnels forwarding adb & vnc " 77 "when instance created.") 78 parser.set_defaults(autoconnect=constants.INS_KEY_WEBRTC) 79 parser.add_argument( 80 "--unlock", 81 action="store_true", 82 dest="unlock_screen", 83 required=False, 84 default=False, 85 help="This can unlock screen after invoke vnc client.") 86 parser.add_argument( 87 "--report-internal-ip", 88 action="store_true", 89 dest="report_internal_ip", 90 required=False, 91 help="Report internal ip of the created instance instead of external " 92 "ip. Using the internal ip is used when connecting from another " 93 "GCE instance.") 94 parser.add_argument( 95 "--disable-external-ip", 96 action="store_true", 97 dest="disable_external_ip", 98 required=False, 99 help="Disable the external ip of the created instance.") 100 parser.add_argument( 101 "--extra-files", 102 nargs='+', 103 type=str, 104 dest="extra_files", 105 required=False, 106 help="Upload the extra files into GCE instance. e.g. " 107 "/path/to/file_in_local,/path/to/file_in_gce") 108 parser.add_argument( 109 "--network", 110 type=str, 111 dest="network", 112 required=False, 113 help="Set the network the GCE instance will utilize.") 114 parser.add_argument( 115 "--skip-pre-run-check", 116 action="store_true", 117 dest="skip_pre_run_check", 118 required=False, 119 help="Skip the pre-run check.") 120 parser.add_argument( 121 "--force-sync", 122 action="store_true", 123 dest="force_sync", 124 required=False, 125 help="Force to sync image files from Android Build servers even if " 126 "they are already existed for local instance mode.") 127 parser.add_argument( 128 "--boot-timeout", 129 dest="boot_timeout_secs", 130 type=int, 131 required=False, 132 help="The maximum time in seconds used to wait for the AVD to download " 133 "artifacts and boot.") 134 parser.add_argument( 135 "--wait-for-ins-stable", 136 dest="ins_timeout_secs", 137 type=int, 138 required=False, 139 help="The maximum time in seconds used to wait for the instance boot " 140 "up. The default value to wait for instance up time is 300 secs.") 141 parser.add_argument( 142 "--build-target", 143 type=str, 144 dest="build_target", 145 help="Android build target, e.g. aosp_cf_x86_64_phone-userdebug, " 146 "or short names: phone, tablet, or tablet_mobile.") 147 parser.add_argument( 148 "--branch", 149 type=str, 150 dest="branch", 151 help="Android branch, e.g. mnc-dev or git_mnc-dev") 152 parser.add_argument( 153 "--build-id", 154 type=str, 155 dest="build_id", 156 help="Android build id, e.g. 2145099, P2804227") 157 parser.add_argument( 158 "--bootloader-branch", 159 type=str, 160 dest="bootloader_branch", 161 help="'cuttlefish only' Branch to consume the bootloader from.", 162 required=False) 163 parser.add_argument( 164 "--bootloader-build-id", 165 type=str, 166 dest="bootloader_build_id", 167 help="'cuttlefish only' Bootloader build id, e.g. P2804227", 168 required=False) 169 parser.add_argument( 170 "--bootloader-build-target", 171 type=str, 172 dest="bootloader_build_target", 173 help="'cuttlefish only' Bootloader build target.", 174 required=False) 175 parser.add_argument( 176 "--kernel-build-id", 177 type=str, 178 dest="kernel_build_id", 179 required=False, 180 help="Android kernel build id, e.g. 4586590. This is to test a new" 181 " kernel build with a particular Android build (--build-id). If neither" 182 " kernel-branch nor kernel-build-id are specified, the kernel that's" 183 " bundled with the Android build would be used.") 184 parser.add_argument( 185 "--kernel-branch", 186 type=str, 187 dest="kernel_branch", 188 required=False, 189 help="Android kernel build branch name, e.g." 190 " kernel-common-android-4.14. This is to test a new kernel build with a" 191 " particular Android build (--build-id). If specified without" 192 " specifying kernel-build-id, the last green build in the branch will" 193 " be used. If neither kernel-branch nor kernel-build-id are specified," 194 " the kernel that's bundled with the Android build would be used.") 195 parser.add_argument( 196 "--kernel-build-target", 197 type=str, 198 dest="kernel_build_target", 199 default="kernel", 200 help="Kernel build target, specify if different from 'kernel'") 201 parser.add_argument( 202 "--kernel-artifact", 203 type=str, 204 dest="kernel_artifact", 205 required=False, 206 help="Goldfish remote host only. The name of the boot image to be " 207 "retrieved from Android build, e.g., boot-5.10.img.") 208 parser.add_argument( 209 "--ota-branch", 210 type=str, 211 dest="ota_branch", 212 required=False, 213 help="'cuttlefish only' OTA tools branch name. e.g. aosp-master") 214 parser.add_argument( 215 "--ota-build-id", 216 type=str, 217 dest="ota_build_id", 218 required=False, 219 help="'cuttlefish only' OTA tools build id, e.g. 2145099, P2804227") 220 parser.add_argument( 221 "--ota-build-target", 222 type=str, 223 dest="ota_build_target", 224 required=False, 225 help="'cuttlefish only' OTA tools build target, e.g. " 226 "cf_x86_64_phone-userdebug.") 227 parser.add_argument( 228 "--system-branch", 229 type=str, 230 dest="system_branch", 231 help="'cuttlefish only' Branch to consume the system image (system.img) " 232 "from, will default to what is defined by --branch. " 233 "That feature allows to (automatically) test various combinations " 234 "of vendor.img (CF, e.g.) and system images (GSI, e.g.). ", 235 required=False) 236 parser.add_argument( 237 "--system-build-id", 238 type=str, 239 dest="system_build_id", 240 help="'cuttlefish only' System image build id, e.g. 2145099, P2804227", 241 required=False) 242 parser.add_argument( 243 "--system-build-target", 244 type=str, 245 dest="system_build_target", 246 help="'cuttlefish only' System image build target, specify if different " 247 "from --build-target", 248 required=False) 249 parser.add_argument( 250 "--launch-args", 251 type=str, 252 dest="launch_args", 253 help="'cuttlefish only' Add extra args to launch_cvd command.", 254 required=False) 255 parser.add_argument( 256 "--gce-metadata", 257 type=str, 258 dest="gce_metadata", 259 default=None, 260 help="'GCE instance only' Record data into GCE instance metadata with " 261 "key-value pair format. e.g. id:12,name:unknown.") 262 # TODO(146314062): Remove --multi-stage-launch after infra don't use this 263 # args. 264 parser.add_argument( 265 "--multi-stage-launch", 266 dest="multi_stage_launch", 267 action="store_true", 268 required=False, 269 default=True, 270 help="Enable the multi-stage cuttlefish launch.") 271 parser.add_argument( 272 "--no-multi-stage-launch", 273 dest="multi_stage_launch", 274 action="store_false", 275 required=False, 276 default=None, 277 help="Disable the multi-stage cuttlefish launch.") 278 parser.add_argument( 279 "--no-pull-log", 280 dest="no_pull_log", 281 action="store_true", 282 required=False, 283 default=None, 284 help="Disable auto download logs when AVD booting up failed.") 285 parser.add_argument( 286 "--no-mkcert", 287 dest="mkcert", 288 action="store_false", 289 required=False, 290 default=True, 291 help="Disable mkcert setup process on the host.") 292 # TODO(147335651): Add gpu in user config. 293 # TODO(147335651): Support "--gpu" without giving any value. 294 parser.add_argument( 295 "--gpu", 296 type=str, 297 const=_DEFAULT_GPU, 298 nargs="?", 299 dest="gpu", 300 required=False, 301 default=None, 302 help="GPU accelerator to use if any. e.g. nvidia-tesla-k80. For local " 303 "instances, this arg without assigning any value is to enable " 304 "local gpu support.") 305 # Hide following args for users, it is only used in infra. 306 parser.add_argument( 307 "--local-instance-dir", 308 dest="local_instance_dir", 309 required=False, 310 help=argparse.SUPPRESS) 311 parser.add_argument( 312 "--num-avds-per-instance", 313 type=int, 314 dest="num_avds_per_instance", 315 required=False, 316 default=1, 317 help=argparse.SUPPRESS) 318 parser.add_argument( 319 "--oxygen", 320 action="store_true", 321 dest="oxygen", 322 required=False, 323 help=argparse.SUPPRESS) 324 parser.add_argument( 325 "--zone", 326 type=str, 327 dest="zone", 328 required=False, 329 help=argparse.SUPPRESS) 330 331 # TODO(b/118439885): Old arg formats to support transition, delete when 332 # transistion is done. 333 parser.add_argument( 334 "--serial_log_file", 335 type=str, 336 dest="serial_log_file", 337 required=False, 338 help=argparse.SUPPRESS) 339 parser.add_argument( 340 "--build_id", 341 type=str, 342 dest="build_id", 343 required=False, 344 help=argparse.SUPPRESS) 345 parser.add_argument( 346 "--build_target", 347 type=str, 348 dest="build_target", 349 required=False, 350 help=argparse.SUPPRESS) 351 parser.add_argument( 352 "--system_branch", 353 type=str, 354 dest="system_branch", 355 required=False, 356 help=argparse.SUPPRESS) 357 parser.add_argument( 358 "--system_build_id", 359 type=str, 360 dest="system_build_id", 361 required=False, 362 help=argparse.SUPPRESS) 363 parser.add_argument( 364 "--system_build_target", 365 type=str, 366 dest="system_build_target", 367 required=False, 368 help=argparse.SUPPRESS) 369 parser.add_argument( 370 "--kernel_build_id", 371 type=str, 372 dest="kernel_build_id", 373 required=False, 374 help=argparse.SUPPRESS) 375 parser.add_argument( 376 "--kernel_branch", 377 type=str, 378 dest="kernel_branch", 379 required=False, 380 help=argparse.SUPPRESS) 381 parser.add_argument( 382 "--kernel_build_target", 383 type=str, 384 dest="kernel_build_target", 385 default="kernel", 386 help=argparse.SUPPRESS) 387 parser.add_argument( 388 "--bootloader_branch", 389 type=str, 390 dest="bootloader_branch", 391 help=argparse.SUPPRESS, 392 required=False) 393 parser.add_argument( 394 "--bootloader_build_id", 395 type=str, 396 dest="bootloader_build_id", 397 help=argparse.SUPPRESS, 398 required=False) 399 parser.add_argument( 400 "--bootloader_build_target", 401 type=str, 402 dest="bootloader_build_target", 403 help=argparse.SUPPRESS, 404 required=False) 405 406 407def GetCreateArgParser(subparser): 408 """Return the create arg parser. 409 410 Args: 411 subparser: argparse.ArgumentParser that is attached to main acloud cmd. 412 413 Returns: 414 argparse.ArgumentParser with create options defined. 415 """ 416 create_parser = subparser.add_parser(CMD_CREATE) 417 create_parser.required = False 418 create_parser.set_defaults(which=CMD_CREATE) 419 # Use default=None to distinguish remote instance or local. The instance 420 # type will be remote if the arg is not provided. 421 create_parser.add_argument( 422 "--local-instance", 423 type=_PositiveInteger, 424 const=0, 425 metavar="ID", 426 nargs="?", 427 dest="local_instance", 428 required=False, 429 help="Create a local AVD instance using the resources associated with " 430 "the ID. Choose an unused ID automatically if the value is " 431 "not specified (primarily for infra usage).") 432 create_parser.add_argument( 433 "--adb-port", "-p", 434 type=int, 435 default=None, 436 dest="adb_port", 437 required=False, 438 help="Specify port for adb forwarding.") 439 create_parser.add_argument( 440 "--base-instance-num", 441 type=int, 442 default=None, 443 dest="base_instance_num", 444 required=False, 445 help="'cuttlefish only' The instance number of the created device.") 446 create_parser.add_argument( 447 "--avd-type", 448 type=str, 449 dest="avd_type", 450 default=constants.TYPE_CF, 451 choices=[constants.TYPE_GCE, constants.TYPE_CF, constants.TYPE_GF, constants.TYPE_CHEEPS, 452 constants.TYPE_FVP], 453 help="Android Virtual Device type (default %s)." % constants.TYPE_CF) 454 create_parser.add_argument( 455 "--config", "--flavor", 456 type=str, 457 dest="flavor", 458 help="The device flavor of the AVD (default %s). e.g. phone, tv, foldable." 459 % constants.FLAVOR_PHONE) 460 create_parser.add_argument( 461 "--local-image", 462 const=constants.FIND_IN_BUILD_ENV, 463 type=str, 464 dest="local_image", 465 nargs="?", 466 required=False, 467 help="Use the locally built image for the AVD. Look for the image " 468 "artifact in $ANDROID_PRODUCT_OUT if no args value is provided." 469 "e.g --local-image or --local-image /path/to/dir or --local-image " 470 "/path/to/file") 471 create_parser.add_argument( 472 "--local-kernel-image", "--local-boot-image", 473 const=constants.FIND_IN_BUILD_ENV, 474 type=str, 475 dest="local_kernel_image", 476 nargs="?", 477 required=False, 478 help="Use the locally built kernel image for the AVD. Look for " 479 "boot.img or boot-*.img if the argument is a directory. Look for the " 480 "image in $ANDROID_PRODUCT_OUT if no argument is provided. e.g., " 481 "--local-kernel-image, --local-kernel-image /path/to/dir, or " 482 "--local-kernel-image /path/to/img") 483 create_parser.add_argument( 484 "--local-system-image", 485 const=constants.FIND_IN_BUILD_ENV, 486 type=str, 487 dest="local_system_image", 488 nargs="?", 489 required=False, 490 help="Use the locally built system images for the AVD. Look for the " 491 "images in $ANDROID_PRODUCT_OUT if no args value is provided. " 492 "e.g., --local-system-image, --local-system-image /path/to/dir, or " 493 "--local-system-image /path/to/img") 494 create_parser.add_argument( 495 "--local-tool", 496 type=str, 497 dest="local_tool", 498 action="append", 499 default=[], 500 required=False, 501 help="Use the tools in the specified directory to create local " 502 "instances. The directory structure follows $ANDROID_SOONG_HOST_OUT " 503 "or $ANDROID_EMULATOR_PREBUILTS.") 504 create_parser.add_argument( 505 "--cvd-host-package", 506 type=str, 507 dest="cvd_host_package", 508 required=False, 509 help="Use the specified path of the cvd host package to create " 510 "instances. e.g. /path/cvd-host_package_v1.tar.gz") 511 create_parser.add_argument( 512 "--image-download-dir", 513 type=str, 514 dest="image_download_dir", 515 required=False, 516 help="Define remote image download directory, e.g. /usr/local/dl.") 517 create_parser.add_argument( 518 "--yes", "-y", 519 action="store_true", 520 dest="no_prompt", 521 required=False, 522 help=("Automatic yes to prompts. Assume 'yes' as answer to all prompts " 523 "and run non-interactively.")) 524 create_parser.add_argument( 525 "--reuse-gce", 526 type=str, 527 const=constants.SELECT_ONE_GCE_INSTANCE, 528 nargs="?", 529 dest="reuse_gce", 530 required=False, 531 help="'cuttlefish only' This can help users use their own instance. " 532 "Reusing specific gce instance if --reuse-gce [instance_name] is " 533 "provided. Select one gce instance to reuse if --reuse-gce is " 534 "provided.") 535 create_parser.add_argument( 536 "--openwrt", 537 action="store_true", 538 dest="openwrt", 539 required=False, 540 help="'cuttlefish only' Create OpenWrt device when launching cuttlefish " 541 "device.") 542 create_parser.add_argument( 543 "--use-launch_cvd", 544 action="store_true", 545 dest="use_launch_cvd", 546 required=False, 547 help="'cuttlefish only' Use launch_cvd to create cuttlefish devices.") 548 create_parser.add_argument( 549 "--host", 550 type=str, 551 dest="remote_host", 552 default=None, 553 help="'cuttlefish only' Provide host name to clean up the remote host. " 554 "For example: '--host 1.1.1.1'") 555 create_parser.add_argument( 556 "--host-user", 557 type=str, 558 dest="host_user", 559 default=constants.GCE_USER, 560 help="'remote host only' Provide host user for logging in to the host. " 561 "The default value is vsoc-01. For example: '--host 1.1.1.1 --host-user " 562 "vsoc-02'") 563 create_parser.add_argument( 564 "--host-ssh-private-key-path", 565 type=str, 566 dest="host_ssh_private_key_path", 567 default=None, 568 help="'remote host only' Provide host key for login on on this host.") 569 # User should not specify --spec and --hw_property at the same time. 570 hw_spec_group = create_parser.add_mutually_exclusive_group() 571 hw_spec_group.add_argument( 572 "--hw-property", 573 type=str, 574 dest="hw_property", 575 required=False, 576 help="Supported HW properties and example values: %s" % 577 constants.HW_PROPERTIES_CMD_EXAMPLE) 578 hw_spec_group.add_argument( 579 "--spec", 580 type=str, 581 dest="spec", 582 required=False, 583 choices=constants.SPEC_NAMES, 584 help="The name of a pre-configured device spec that we are " 585 "going to use.") 586 create_parser.add_argument( 587 "--disk-type", 588 type=str, 589 dest="disk_type", 590 required=False, 591 help="This is used to customize the GCE instance disk type, the " 592 "default disk type is from the stable host image. Use pd-ssd or " 593 "pd-standard to specify instance disk type.") 594 create_parser.add_argument( 595 "--stable-host-image-name", 596 type=str, 597 dest="stable_host_image_name", 598 required=False, 599 default=None, 600 help=("'cuttlefish only' The Cuttlefish host image from which instances " 601 "are launched. If specified here, the value set in Acloud config " 602 "file will be overridden.")) 603 604 # Arguments for goldfish type. 605 create_parser.add_argument( 606 "--emulator-build-id", 607 type=int, 608 dest="emulator_build_id", 609 required=False, 610 help="'goldfish only' Emulator build ID used to run the images. " 611 "e.g. 4669466.") 612 create_parser.add_argument( 613 "--emulator-build-target", 614 dest="emulator_build_target", 615 required=False, 616 help="'goldfish remote host only' Emulator build target used to run " 617 "the images. e.g. sdk_tools_linux.") 618 619 # Arguments for cheeps type. 620 create_parser.add_argument( 621 "--stable-cheeps-host-image-name", 622 type=str, 623 dest="stable_cheeps_host_image_name", 624 required=False, 625 default=None, 626 help=("'cheeps only' The Cheeps host image from which instances are " 627 "launched. If specified here, the value set in Acloud config " 628 "file will be overridden.")) 629 create_parser.add_argument( 630 "--stable-cheeps-host-image-project", 631 type=str, 632 dest="stable_cheeps_host_image_project", 633 required=False, 634 default=None, 635 help=("'cheeps only' The project hosting the specified Cheeps host " 636 "image. If specified here, the value set in Acloud config file " 637 "will be overridden.")) 638 create_parser.add_argument( 639 "--user", 640 type=str, 641 dest="username", 642 required=False, 643 default=None, 644 help="'cheeps only' username to log in to Chrome OS as.") 645 create_parser.add_argument( 646 "--password", 647 type=str, 648 dest="password", 649 required=False, 650 default=None, 651 help="'cheeps only' password to log in to Chrome OS with.") 652 create_parser.add_argument( 653 "--betty-image", 654 type=str, 655 dest="cheeps_betty_image", 656 required=False, 657 default=None, 658 help=("'cheeps only' The L1 betty version to use. Only makes sense " 659 "when launching a controller image with " 660 "stable-cheeps-host-image")) 661 create_parser.add_argument( 662 "--cheeps-feature", 663 type=str, 664 dest="cheeps_features", 665 required=False, 666 action="append", 667 default=[], 668 help=("'cheeps only' Cheeps feature to enable. Can be repeated.")) 669 670 AddCommonCreateArgs(create_parser) 671 return create_parser 672 673 674def _PositiveInteger(arg): 675 """Convert an argument from a string to a positive integer.""" 676 try: 677 value = int(arg) 678 except ValueError as e: 679 raise argparse.ArgumentTypeError(arg + " is not an integer.") from e 680 if value <= 0: 681 raise argparse.ArgumentTypeError(arg + " is not positive.") 682 return value 683 684 685def _VerifyLocalArgs(args): 686 """Verify args starting with --local. 687 688 Args: 689 args: Namespace object from argparse.parse_args. 690 691 Raises: 692 errors.CheckPathError: Image path doesn't exist. 693 errors.UnsupportedCreateArgs: The specified avd type does not support 694 --local-system-image. 695 errors.UnsupportedLocalInstanceId: Local instance ID is invalid. 696 """ 697 if args.local_image and not os.path.exists(args.local_image): 698 raise errors.CheckPathError( 699 "Specified path doesn't exist: %s" % args.local_image) 700 701 if args.local_instance_dir and not os.path.exists(args.local_instance_dir): 702 raise errors.CheckPathError( 703 "Specified path doesn't exist: %s" % args.local_instance_dir) 704 705 if not (args.local_system_image is None or 706 args.avd_type in (constants.TYPE_CF, constants.TYPE_GF)): 707 raise errors.UnsupportedCreateArgs("%s instance does not support " 708 "--local-system-image" % 709 args.avd_type) 710 # TODO(b/179340595): To support local image remote instance with kernel build. 711 if args.local_instance is None and args.local_image is not None and ( 712 args.kernel_branch or args.kernel_build_id): 713 raise errors.UnsupportedCreateArgs( 714 "Acloud didn't support local image with specific kernel. " 715 "Please download the specific kernel and put it into " 716 "your local image folder: '%s'." % ( 717 args.local_image if args.local_image else 718 utils.GetBuildEnvironmentVariable(constants.ENV_ANDROID_PRODUCT_OUT))) 719 720 if (args.local_system_image and 721 not os.path.exists(args.local_system_image)): 722 raise errors.CheckPathError( 723 "Specified path doesn't exist: %s" % args.local_system_image) 724 725 for tool_dir in args.local_tool: 726 if not os.path.exists(tool_dir): 727 raise errors.CheckPathError( 728 "Specified path doesn't exist: %s" % tool_dir) 729 730 731def _VerifyHostArgs(args): 732 """Verify args starting with --host. 733 734 Args: 735 args: Namespace object from argparse.parse_args. 736 737 Raises: 738 errors.UnsupportedCreateArgs: When a create arg is specified but 739 unsupported for remote host mode. 740 """ 741 if args.remote_host and args.local_instance is not None: 742 raise errors.UnsupportedCreateArgs( 743 "--host is not supported for local instance.") 744 745 if args.remote_host and args.num > 1: 746 raise errors.UnsupportedCreateArgs( 747 "--num is not supported for remote host.") 748 749 if args.host_user != constants.GCE_USER and args.remote_host is None: 750 raise errors.UnsupportedCreateArgs( 751 "--host-user only support for remote host.") 752 753 if args.host_ssh_private_key_path and args.remote_host is None: 754 raise errors.UnsupportedCreateArgs( 755 "--host-ssh-private-key-path only support for remote host.") 756 757 758def _VerifyGoldfishArgs(args): 759 """Verify goldfish args. 760 761 Args: 762 args: Namespace object from argparse.parse_args. 763 764 Raises: 765 errors.UnsupportedCreateArgs: When a create arg is specified but 766 unsupported for goldfish. 767 """ 768 goldfish_only_flags = [ 769 args.emulator_build_id, 770 args.emulator_build_target, 771 args.kernel_artifact 772 ] 773 if args.avd_type != constants.TYPE_GF and any(goldfish_only_flags): 774 raise errors.UnsupportedCreateArgs( 775 "--emulator-* and --kernel-artifact are only valid with " 776 "avd_type == %s" % constants.TYPE_GF) 777 778 # Exclude kernel_build_target because the default value isn't empty. 779 remote_kernel_flags = [ 780 args.kernel_build_id, 781 args.kernel_branch, 782 args.kernel_artifact, 783 ] 784 if (args.avd_type == constants.TYPE_GF and any(remote_kernel_flags) and 785 not all(remote_kernel_flags)): 786 raise errors.UnsupportedCreateArgs( 787 "Either none or all of --kernel-branch, --kernel-build-target, " 788 "--kernel-build-id, and --kernel-artifact must be specified for " 789 "goldfish.") 790 791 remote_system_flags = [ 792 args.system_build_target, 793 args.system_build_id, 794 args.system_branch, 795 ] 796 if (args.avd_type == constants.TYPE_GF and any(remote_system_flags) and 797 not all(remote_system_flags)): 798 raise errors.UnsupportedCreateArgs( 799 "Either none or all of --system-branch, --system-build-target, " 800 "and --system-build-id must be specified for goldfish.") 801 802 remote_host_only_flags = ([args.emulator_build_target] + 803 remote_kernel_flags + remote_system_flags) 804 if args.avd_type == constants.TYPE_GF and args.remote_host is None and any( 805 remote_host_only_flags): 806 raise errors.UnsupportedCreateArgs( 807 "--kernel-*, --system-*, and --emulator-build-target for goldfish " 808 "are only supported for remote host.") 809 810 811def VerifyArgs(args): 812 """Verify args. 813 814 Args: 815 args: Namespace object from argparse.parse_args. 816 817 Raises: 818 errors.UnsupportedMultiAdbPort: multi adb port doesn't support. 819 errors.UnsupportedCreateArgs: When a create arg is specified but 820 unsupported for a particular avd type. 821 (e.g. --system-build-id for gf) 822 """ 823 # Verify that user specified flavor name is in support list. 824 # We don't use argparse's builtin validation because we need to be able to 825 # tell when a user doesn't specify a flavor. 826 if args.flavor and args.flavor not in constants.ALL_FLAVORS: 827 logger.debug("Flavor[%s] isn't in default support list: %s", 828 args.flavor, constants.ALL_FLAVORS) 829 830 if args.avd_type not in (constants.TYPE_CF, constants.TYPE_GF): 831 if args.system_branch or args.system_build_id or args.system_build_target: 832 raise errors.UnsupportedCreateArgs( 833 "--system-* args are not supported for AVD type: %s" 834 % args.avd_type) 835 836 if args.num > 1 and args.adb_port: 837 raise errors.UnsupportedMultiAdbPort( 838 "--adb-port is not supported for multi-devices.") 839 840 if args.num > 1 and args.local_instance is not None: 841 raise errors.UnsupportedCreateArgs( 842 "--num is not supported for local instance.") 843 844 if args.local_instance is None and args.gpu == _DEFAULT_GPU: 845 raise errors.UnsupportedCreateArgs( 846 "Please assign one gpu model for GCE instance. Reference: " 847 "https://cloud.google.com/compute/docs/gpus") 848 849 if args.adb_port: 850 utils.CheckPortFree(args.adb_port) 851 852 hw_properties = create_common.ParseKeyValuePairArgs(args.hw_property) 853 for key in hw_properties: 854 if key not in constants.HW_PROPERTIES: 855 raise errors.InvalidHWPropertyError( 856 "[%s] is an invalid hw property, supported values are:%s. " 857 % (key, constants.HW_PROPERTIES)) 858 859 cheeps_only_flags = [args.stable_cheeps_host_image_name, 860 args.stable_cheeps_host_image_project, 861 args.username, 862 args.password, 863 args.cheeps_betty_image, 864 args.cheeps_features] 865 if args.avd_type != constants.TYPE_CHEEPS and any(cheeps_only_flags): 866 raise errors.UnsupportedCreateArgs( 867 "--stable-cheeps-*, --betty-image, --cheeps-feature, --username " 868 "and --password are only valid with avd_type == %s" 869 % constants.TYPE_CHEEPS) 870 if (args.username or args.password) and not (args.username and args.password): 871 raise ValueError("--username and --password must both be set") 872 if not args.autoconnect and args.unlock_screen: 873 raise ValueError("--no-autoconnect and --unlock couldn't be " 874 "passed in together.") 875 876 _VerifyGoldfishArgs(args) 877 _VerifyLocalArgs(args) 878 _VerifyHostArgs(args) 879