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 22import posixpath as remote_path 23 24from acloud import errors 25from acloud.create import create_common 26from acloud.internal import constants 27from acloud.internal.lib import utils 28 29logger = logging.getLogger(__name__) 30_DEFAULT_GPU = "default" 31CMD_CREATE = "create" 32 33 34# TODO: Add this into main create args once create_cf/gf is deprecated. 35# pylint: disable=too-many-statements 36def AddCommonCreateArgs(parser): 37 """Adds arguments common to create parsers. 38 39 Args: 40 parser: ArgumentParser object, used to parse flags. 41 """ 42 parser.add_argument( 43 "--num", 44 type=int, 45 dest="num", 46 required=False, 47 default=1, 48 help="Number of instances to create.") 49 parser.add_argument( 50 "--serial-log-file", 51 type=str, 52 dest="serial_log_file", 53 required=False, 54 help="Path to a *tar.gz file where serial logs will be saved " 55 "when a device fails on boot.") 56 parser.add_argument( 57 "--autoconnect", 58 type=str, 59 nargs="?", 60 const=constants.INS_KEY_WEBRTC, 61 dest="autoconnect", 62 required=False, 63 choices=[constants.INS_KEY_VNC, constants.INS_KEY_ADB, 64 constants.INS_KEY_WEBRTC], 65 help="Determines to establish a tunnel forwarding adb/vnc and " 66 "launch VNC/webrtc. Establish a tunnel forwarding adb and vnc " 67 "then launch vnc if --autoconnect vnc is provided. Establish a " 68 "tunnel forwarding adb if --autoconnect adb is provided. " 69 "Establish a tunnel forwarding adb and auto-launch on the browser " 70 "if --autoconnect webrtc is provided. For local goldfish " 71 "instance, create a window.") 72 parser.add_argument( 73 "--no-autoconnect", 74 action="store_false", 75 dest="autoconnect", 76 required=False, 77 help="Will not automatically create ssh tunnels forwarding adb & vnc " 78 "when instance created.") 79 parser.set_defaults(autoconnect=constants.INS_KEY_WEBRTC) 80 parser.add_argument( 81 "--unlock", 82 action="store_true", 83 dest="unlock_screen", 84 required=False, 85 default=False, 86 help="This can unlock screen after invoke vnc client.") 87 parser.add_argument( 88 "--report-internal-ip", 89 action="store_true", 90 dest="report_internal_ip", 91 required=False, 92 help="Report internal ip of the created instance instead of external " 93 "ip. Using the internal ip is used when connecting from another " 94 "GCE instance.") 95 parser.add_argument( 96 "--disable-external-ip", 97 action="store_true", 98 dest="disable_external_ip", 99 required=False, 100 help="Disable the external ip of the created instance.") 101 parser.add_argument( 102 "--extra-files", 103 nargs='+', 104 type=str, 105 dest="extra_files", 106 required=False, 107 help="Upload the extra files into GCE instance. e.g. " 108 "/path/to/file_in_local,/path/to/file_in_gce") 109 parser.add_argument( 110 "--network", 111 type=str, 112 dest="network", 113 required=False, 114 help="Set the network the GCE instance will utilize.") 115 parser.add_argument( 116 "--skip-pre-run-check", 117 action="store_true", 118 dest="skip_pre_run_check", 119 required=False, 120 help="Skip the pre-run check.") 121 parser.add_argument( 122 "--force-sync", 123 action="store_true", 124 dest="force_sync", 125 required=False, 126 help="Force to sync image files from Android Build servers even if " 127 "they are already existed for local instance mode.") 128 parser.add_argument( 129 "--boot-timeout", 130 dest="boot_timeout_secs", 131 type=int, 132 required=False, 133 help="The maximum time in seconds used to wait for the AVD to download " 134 "artifacts and boot.") 135 parser.add_argument( 136 "--wait-for-ins-stable", 137 dest="ins_timeout_secs", 138 type=int, 139 required=False, 140 help="The maximum time in seconds used to wait for the instance boot " 141 "up. The default value to wait for instance up time is 300 secs.") 142 parser.add_argument( 143 "--build-target", 144 type=str, 145 dest="build_target", 146 help="Android build target, e.g. aosp_cf_x86_64_phone-userdebug, " 147 "or short names: phone, tablet, or tablet_mobile.") 148 parser.add_argument( 149 "--branch", 150 type=str, 151 dest="branch", 152 help="Android branch, e.g. mnc-dev or git_mnc-dev") 153 parser.add_argument( 154 "--build-id", 155 type=str, 156 dest="build_id", 157 help="Android build id, e.g. 2145099, P2804227") 158 parser.add_argument( 159 "--bootloader-branch", 160 type=str, 161 dest="bootloader_branch", 162 help="'cuttlefish only' Branch to consume the bootloader from.", 163 required=False) 164 parser.add_argument( 165 "--bootloader-build-id", 166 type=str, 167 dest="bootloader_build_id", 168 help="'cuttlefish only' Bootloader build id, e.g. P2804227", 169 required=False) 170 parser.add_argument( 171 "--bootloader-build-target", 172 type=str, 173 dest="bootloader_build_target", 174 help="'cuttlefish only' Bootloader build target.", 175 required=False) 176 parser.add_argument( 177 "--android-efi-loader-build-id", 178 type=str, 179 dest="android_efi_loader_build_id", 180 help="'cuttlefish only' Android EFI loader build id, e.g. P2804227", 181 required=False) 182 parser.add_argument( 183 "--android-efi-loader-artifact", 184 type=str, 185 dest="android_efi_loader_artifact", 186 help="'cuttlefish only' Android EFI loader artifact name, e.g. gbl_aarch64.efi", 187 required=False) 188 parser.add_argument( 189 "--kernel-build-id", 190 type=str, 191 dest="kernel_build_id", 192 required=False, 193 help="Android kernel build id, e.g. 4586590. This is to test a new" 194 " kernel build with a particular Android build (--build-id). If neither" 195 " kernel-branch nor kernel-build-id are specified, the kernel that's" 196 " bundled with the Android build would be used.") 197 parser.add_argument( 198 "--kernel-branch", 199 type=str, 200 dest="kernel_branch", 201 required=False, 202 help="Android kernel build branch name, e.g." 203 " kernel-common-android-4.14. This is to test a new kernel build with a" 204 " particular Android build (--build-id). If specified without" 205 " specifying kernel-build-id, the last green build in the branch will" 206 " be used. If neither kernel-branch nor kernel-build-id are specified," 207 " the kernel that's bundled with the Android build would be used.") 208 parser.add_argument( 209 "--kernel-build-target", 210 type=str, 211 dest="kernel_build_target", 212 default="kernel", 213 help="Kernel build target, specify if different from 'kernel'") 214 parser.add_argument( 215 "--boot-build-id", 216 type=str, 217 dest="boot_build_id", 218 required=False, 219 help="Boot image build ID, e.g., 8747889, 8748012.") 220 parser.add_argument( 221 "--boot-branch", 222 type=str, 223 dest="boot_branch", 224 required=False, 225 help="Boot image branch, e.g., aosp-gki13-boot-release, aosp-master.") 226 parser.add_argument( 227 "--boot-build-target", 228 type=str, 229 dest="boot_build_target", 230 required=False, 231 help="Boot image build target, " 232 "e.g., gki_x86_64-userdebug, aosp_cf_x86_64_phone-userdebug.") 233 parser.add_argument( 234 "--boot-artifact", 235 type=str, 236 dest="boot_artifact", 237 required=False, 238 help="The name of the boot image to be retrieved from Android build, " 239 "e.g., boot-5.10.img, boot.img.") 240 parser.add_argument( 241 "--ota-branch", 242 type=str, 243 dest="ota_branch", 244 required=False, 245 help="'cuttlefish only' OTA tools branch name. e.g. aosp-master") 246 parser.add_argument( 247 "--ota-build-id", 248 type=str, 249 dest="ota_build_id", 250 required=False, 251 help="'cuttlefish only' OTA tools build id, e.g. 2145099, P2804227") 252 parser.add_argument( 253 "--ota-build-target", 254 type=str, 255 dest="ota_build_target", 256 required=False, 257 help="'cuttlefish only' OTA tools build target, e.g. " 258 "cf_x86_64_phone-userdebug.") 259 parser.add_argument( 260 "--host-package-branch", "--host_package_branch", 261 type=str, 262 dest="host_package_branch", 263 required=False, 264 help="'cuttlefish and trusty only' Host package branch name. e.g. " 265 "aosp-main") 266 parser.add_argument( 267 "--host-package-build-id", "--host_package_build_id", 268 type=str, 269 dest="host_package_build_id", 270 required=False, 271 help="'cuttlefish and trusty only' Host package build id, e.g. " 272 "2145099, P2804227") 273 parser.add_argument( 274 "--host-package-build-target", "--host_package_build_target", 275 type=str, 276 dest="host_package_build_target", 277 required=False, 278 help="'cuttlefish and trusty only' Host package build target, e.g. " 279 "cf_x86_64_phone-userdebug.") 280 parser.add_argument( 281 "--system-branch", 282 type=str, 283 dest="system_branch", 284 help="'cuttlefish only' Branch to consume the system image (system.img) " 285 "from, will default to what is defined by --branch. " 286 "That feature allows to (automatically) test various combinations " 287 "of vendor.img (CF, e.g.) and system images (GSI, e.g.). ", 288 required=False) 289 parser.add_argument( 290 "--system-build-id", 291 type=str, 292 dest="system_build_id", 293 help="'cuttlefish only' System image build id, e.g. 2145099, P2804227", 294 required=False) 295 parser.add_argument( 296 "--system-build-target", 297 type=str, 298 dest="system_build_target", 299 help="'cuttlefish only' System image build target, specify if different " 300 "from --build-target", 301 required=False) 302 parser.add_argument( 303 "--launch-args", 304 type=str, 305 dest="launch_args", 306 help="'cuttlefish only' Add extra args to launch_cvd command.", 307 required=False) 308 parser.add_argument( 309 "--pet-name", 310 "--webrtc_device_id", 311 type=str, 312 dest="webrtc_device_id", 313 help="'cuttlefish only' Give the pet name of the instance.", 314 required=False) 315 parser.add_argument( 316 "--gce-metadata", 317 type=str, 318 dest="gce_metadata", 319 default=None, 320 help="'GCE instance only' Record data into GCE instance metadata with " 321 "key-value pair format. e.g. id:12,name:unknown.") 322 parser.add_argument( 323 "--fetch_cvd-build-id", 324 type=str, 325 dest="fetch_cvd_build_id", 326 required=False, 327 help="'cuttlefish only' Build id of fetch_cvd, e.g. 2145099, P2804227") 328 # TODO(146314062): Remove --multi-stage-launch after infra don't use this 329 # args. 330 parser.add_argument( 331 "--multi-stage-launch", 332 dest="multi_stage_launch", 333 action="store_true", 334 required=False, 335 default=True, 336 help="Enable the multi-stage cuttlefish launch.") 337 parser.add_argument( 338 "--no-multi-stage-launch", 339 dest="multi_stage_launch", 340 action="store_false", 341 required=False, 342 default=None, 343 help="Disable the multi-stage cuttlefish launch.") 344 parser.add_argument( 345 "--no-pull-log", 346 dest="no_pull_log", 347 action="store_true", 348 required=False, 349 default=None, 350 help="Disable auto download logs when AVD booting up failed.") 351 parser.add_argument( 352 "--no-mkcert", 353 dest="mkcert", 354 action="store_false", 355 required=False, 356 default=True, 357 help="Disable mkcert setup process on the host.") 358 # TODO(147335651): Add gpu in user config. 359 # TODO(147335651): Support "--gpu" without giving any value. 360 parser.add_argument( 361 "--gpu", 362 type=str, 363 const=_DEFAULT_GPU, 364 nargs="?", 365 dest="gpu", 366 required=False, 367 default=None, 368 help="GPU accelerator to use if any. e.g. nvidia-tesla-k80. For local " 369 "instances, this arg without assigning any value is to enable " 370 "local gpu support.") 371 parser.add_argument( 372 "--num-avds-per-instance", 373 "--num-instances", 374 "--num_instances", 375 type=int, 376 dest="num_avds_per_instance", 377 required=False, 378 default=1, 379 help="'cuttlefish only' Create multiple cuttlefish AVDs in one local " 380 "instance.") 381 parser.add_argument( 382 "--connect-hostname", 383 action="store_true", 384 dest="connect_hostname", 385 required=False, 386 default=False, 387 help="Ssh connects to the GCE instance with hostname.") 388 parser.add_argument( 389 "--gce-only", 390 action="store_true", 391 dest="gce_only", 392 required=False, 393 default=False, 394 help="Only create the GCE instance. It won't create virtual devices.") 395 # Hide following args for users, it is only used in infra. 396 parser.add_argument( 397 "--local-instance-dir", 398 dest="local_instance_dir", 399 required=False, 400 help=argparse.SUPPRESS) 401 parser.add_argument( 402 "--remote-image-dir", 403 dest="remote_image_dir", 404 required=False, 405 # 'cuttlefish remote host only' Upload images and cvd host package to 406 # the remote directory instead of the instance's own directory. If the 407 # directory has been initialized, acloud ignores the image arguments 408 # given by command line and reuses the images in the directory. 409 help=argparse.SUPPRESS) 410 parser.add_argument( 411 "--oxygen", 412 action="store_true", 413 dest="oxygen", 414 required=False, 415 help=argparse.SUPPRESS) 416 parser.add_argument( 417 "--zone", 418 type=str, 419 dest="zone", 420 required=False, 421 help=argparse.SUPPRESS) 422 423 # TODO(b/118439885): Old arg formats to support transition, delete when 424 # transistion is done. 425 parser.add_argument( 426 "--serial_log_file", 427 type=str, 428 dest="serial_log_file", 429 required=False, 430 help=argparse.SUPPRESS) 431 parser.add_argument( 432 "--build_id", 433 type=str, 434 dest="build_id", 435 required=False, 436 help=argparse.SUPPRESS) 437 parser.add_argument( 438 "--build_target", 439 type=str, 440 dest="build_target", 441 required=False, 442 help=argparse.SUPPRESS) 443 parser.add_argument( 444 "--system_branch", 445 type=str, 446 dest="system_branch", 447 required=False, 448 help=argparse.SUPPRESS) 449 parser.add_argument( 450 "--system_build_id", 451 type=str, 452 dest="system_build_id", 453 required=False, 454 help=argparse.SUPPRESS) 455 parser.add_argument( 456 "--system_build_target", 457 type=str, 458 dest="system_build_target", 459 required=False, 460 help=argparse.SUPPRESS) 461 parser.add_argument( 462 "--kernel_build_id", 463 type=str, 464 dest="kernel_build_id", 465 required=False, 466 help=argparse.SUPPRESS) 467 parser.add_argument( 468 "--kernel_branch", 469 type=str, 470 dest="kernel_branch", 471 required=False, 472 help=argparse.SUPPRESS) 473 parser.add_argument( 474 "--kernel_build_target", 475 type=str, 476 dest="kernel_build_target", 477 default="kernel", 478 help=argparse.SUPPRESS) 479 parser.add_argument( 480 "--bootloader_branch", 481 type=str, 482 dest="bootloader_branch", 483 help=argparse.SUPPRESS, 484 required=False) 485 parser.add_argument( 486 "--bootloader_build_id", 487 type=str, 488 dest="bootloader_build_id", 489 help=argparse.SUPPRESS, 490 required=False) 491 parser.add_argument( 492 "--bootloader_build_target", 493 type=str, 494 dest="bootloader_build_target", 495 help=argparse.SUPPRESS, 496 required=False) 497 parser.add_argument( 498 "--fetch_cvd_build_id", 499 type=str, 500 dest="fetch_cvd_build_id", 501 help=argparse.SUPPRESS, 502 required=False) 503 parser.add_argument( 504 "--remote-fetch", 505 action="store_true", 506 dest="remote_fetch", 507 required=False, 508 default=None, 509 help="'cuttlefish only' Fetch artifacts in remote host.") 510 parser.add_argument( 511 "--fetch-cvd-wrapper", 512 dest="fetch_cvd_wrapper", 513 type=str, 514 required=False, 515 help="'cuttlefish only' Fetch artifacts in remote host by a" 516 " provided static executable fetch cvd wrapper file. " 517 " (Still in experiment, this flag only works on lab hosts" 518 " with special setup.)") 519 520 521def GetCreateArgParser(subparser): 522 """Return the create arg parser. 523 524 Args: 525 subparser: argparse.ArgumentParser that is attached to main acloud cmd. 526 527 Returns: 528 argparse.ArgumentParser with create options defined. 529 """ 530 create_parser = subparser.add_parser(CMD_CREATE) 531 create_parser.required = False 532 create_parser.set_defaults(which=CMD_CREATE) 533 # Use default=None to distinguish remote instance or local. The instance 534 # type will be remote if the arg is not provided. 535 create_parser.add_argument( 536 "--local-instance", 537 type=_PositiveInteger, 538 const=0, 539 metavar="ID", 540 nargs="?", 541 dest="local_instance", 542 required=False, 543 help="Create a local AVD instance using the resources associated with " 544 "the ID. Choose an unused ID automatically if the value is " 545 "not specified (primarily for infra usage).") 546 create_parser.add_argument( 547 "--adb-port", "-p", 548 type=int, 549 default=None, 550 dest="adb_port", 551 required=False, 552 help="Specify port for adb forwarding.") 553 create_parser.add_argument( 554 "--base-instance-num", 555 type=int, 556 default=None, 557 dest="base_instance_num", 558 required=False, 559 help="'cuttlefish only' The instance number of the created device.") 560 create_parser.add_argument( 561 "--avd-type", 562 type=str, 563 dest="avd_type", 564 default=constants.TYPE_CF, 565 choices=[constants.TYPE_GCE, constants.TYPE_CF, constants.TYPE_GF, constants.TYPE_CHEEPS, 566 constants.TYPE_FVP, constants.TYPE_TRUSTY], 567 help="Android Virtual Device type (default %s)." % constants.TYPE_CF) 568 create_parser.add_argument( 569 "--config", "--flavor", 570 type=str, 571 dest="flavor", 572 help="The device flavor of the AVD (default %s). e.g. phone, tv, foldable." 573 % constants.FLAVOR_PHONE) 574 create_parser.add_argument( 575 "--local-image", 576 const=constants.FIND_IN_BUILD_ENV, 577 type=str, 578 dest="local_image", 579 nargs="?", 580 required=False, 581 help="Use the locally built image for the AVD. Look for the image " 582 "artifact in $ANDROID_PRODUCT_OUT if no args value is provided." 583 "e.g --local-image or --local-image /path/to/dir or --local-image " 584 "/path/to/file") 585 create_parser.add_argument( 586 "--local-kernel-image", "--local-boot-image", 587 const=constants.FIND_IN_BUILD_ENV, 588 type=str, 589 dest="local_kernel_image", 590 nargs="?", 591 required=False, 592 help="Use the locally built kernel and ramdisk for the AVD. Look " 593 "for boot.img, vendor_boot.img, kernel, initramfs.img, etc. if the " 594 "argument is a directory. Look for the images in $ANDROID_PRODUCT_OUT " 595 "if no argument is provided. e.g., --local-kernel-image, " 596 "--local-kernel-image /path/to/dir, or --local-kernel-image " 597 "/path/to/boot.img") 598 create_parser.add_argument( 599 "--local-system-image", 600 const=constants.FIND_IN_BUILD_ENV, 601 type=str, 602 dest="local_system_image", 603 nargs="?", 604 required=False, 605 help="Use the locally built system images for the AVD. Look for the " 606 "images in $ANDROID_PRODUCT_OUT if no args value is provided. " 607 "e.g., --local-system-image, --local-system-image /path/to/dir, or " 608 "--local-system-image /path/to/img") 609 create_parser.add_argument( 610 "--local-system_dlkm-image", 611 const=constants.FIND_IN_BUILD_ENV, 612 type=str, 613 dest="local_system_dlkm_image", 614 nargs="?", 615 required=False, 616 help="`remote host only` Use the locally built system_dlkm image for " 617 "the AVD. Look for the image in $ANDROID_PRODUCT_OUT if no args value " 618 "is provided.") 619 create_parser.add_argument( 620 "--local-vendor-image", 621 const=constants.FIND_IN_BUILD_ENV, 622 type=str, 623 dest="local_vendor_image", 624 nargs="?", 625 required=False, 626 help="'cuttlefish only' Use the locally built vendor images for the " 627 "AVD. Look for vendor.img, vendor_dlkm.img, odm.img, and odm_dlkm.img " 628 "if the argument is a directory. Look for the images in " 629 "$ANDROID_PRODUCT_OUT if no argument is provided. e.g., " 630 "--local-vendor-image, or --local-vendor-image /path/to/dir") 631 create_parser.add_argument( 632 "--local-vendor_boot-image", "--local-vendor-boot-image", 633 const=constants.FIND_IN_BUILD_ENV, 634 type=str, 635 dest="local_vendor_boot_image", 636 nargs="?", 637 required=False, 638 help="'cuttlefish only' Use the locally built vendor boot image for " 639 "the AVD. Look for the vendor_boot.img in $ANDROID_PRODUCT_OUT " 640 "if no argument is provided. e.g., --local-vendor-boot-image, or " 641 "--local-vendor-boot-image /path/to/dir, or " 642 "--local-vendor-boot-image /path/to/img") 643 create_parser.add_argument( 644 "--local-tool", 645 type=str, 646 dest="local_tool", 647 action="append", 648 default=[], 649 required=False, 650 help="Use the tools in the specified directory to create local " 651 "instances. The directory structure follows $ANDROID_SOONG_HOST_OUT " 652 "or $ANDROID_EMULATOR_PREBUILTS.") 653 create_parser.add_argument( 654 "--cvd-host-package", 655 type=str, 656 dest="cvd_host_package", 657 required=False, 658 help="Use the specified path of the cvd host package to create " 659 "instances. e.g. /path/cvd-host_package_v1.tar.gz") 660 create_parser.add_argument( 661 "--image-download-dir", 662 type=str, 663 dest="image_download_dir", 664 required=False, 665 help="Define remote image download directory, e.g. /usr/local/dl.") 666 create_parser.add_argument( 667 "--yes", "-y", 668 action="store_true", 669 dest="no_prompt", 670 required=False, 671 help=("Automatic yes to prompts. Assume 'yes' as answer to all prompts " 672 "and run non-interactively.")) 673 create_parser.add_argument( 674 "--reuse-gce", 675 type=str, 676 const=constants.SELECT_ONE_GCE_INSTANCE, 677 nargs="?", 678 dest="reuse_gce", 679 required=False, 680 help="'cuttlefish only' This can help users use their own instance. " 681 "Reusing specific gce instance if --reuse-gce [instance_name] is " 682 "provided. Select one gce instance to reuse if --reuse-gce is " 683 "provided.") 684 create_parser.add_argument( 685 "--openwrt", 686 action="store_true", 687 dest="openwrt", 688 required=False, 689 help="'cuttlefish only' Create OpenWrt device when launching cuttlefish " 690 "device.") 691 create_parser.add_argument( 692 "--use-launch_cvd", 693 action="store_true", 694 dest="use_launch_cvd", 695 required=False, 696 help="'cuttlefish only' Use launch_cvd to create cuttlefish devices.") 697 create_parser.add_argument( 698 "--host", 699 type=str, 700 dest="remote_host", 701 default=None, 702 help="'cuttlefish only' Provide host name to clean up the remote host. " 703 "For example: '--host 1.1.1.1'") 704 create_parser.add_argument( 705 "--host-user", 706 type=str, 707 dest="host_user", 708 default=constants.GCE_USER, 709 help="'remote host only' Provide host user for logging in to the host. " 710 "The default value is vsoc-01. For example: '--host 1.1.1.1 --host-user " 711 "vsoc-02'") 712 create_parser.add_argument( 713 "--host-ssh-private-key-path", 714 type=str, 715 dest="host_ssh_private_key_path", 716 default=None, 717 help="'remote host only' Provide host key for login on on this host.") 718 # User should not specify --spec and --hw_property at the same time. 719 hw_spec_group = create_parser.add_mutually_exclusive_group() 720 hw_spec_group.add_argument( 721 "--hw-property", 722 type=str, 723 dest="hw_property", 724 required=False, 725 help="Supported HW properties and example values: %s" % 726 constants.HW_PROPERTIES_CMD_EXAMPLE) 727 hw_spec_group.add_argument( 728 "--spec", 729 type=str, 730 dest="spec", 731 required=False, 732 choices=constants.SPEC_NAMES, 733 help="The name of a pre-configured device spec that we are " 734 "going to use.") 735 create_parser.add_argument( 736 "--disk-type", 737 type=str, 738 dest="disk_type", 739 required=False, 740 help="This is used to customize the GCE instance disk type, the " 741 "default disk type is from the stable host image. Use pd-ssd or " 742 "pd-standard to specify instance disk type.") 743 create_parser.add_argument( 744 "--stable-host-image-name", 745 type=str, 746 dest="stable_host_image_name", 747 required=False, 748 default=None, 749 help=("'cuttlefish only' The Cuttlefish host image from which instances " 750 "are launched. If specified here, the value set in Acloud config " 751 "file will be overridden.")) 752 753 # Arguments for goldfish type. 754 create_parser.add_argument( 755 "--emulator-build-id", 756 type=str, 757 dest="emulator_build_id", 758 required=False, 759 help="'goldfish only' Emulator build ID used to run the images. " 760 "e.g. 4669466.") 761 create_parser.add_argument( 762 "--emulator-build-target", 763 dest="emulator_build_target", 764 required=False, 765 help="'goldfish remote host only' Emulator build target used to run " 766 "the images. e.g. emulator-linux_x64_nolocationui.") 767 create_parser.add_argument( 768 "--emulator-zip", 769 dest="emulator_zip", 770 required=False, 771 help="'goldfish remote host only' Emulator zip used to run the " 772 "images. e.g., /path/sdk-repo-linux-emulator-1234567.zip.") 773 774 # Arguments for cheeps type. 775 create_parser.add_argument( 776 "--stable-cheeps-host-image-name", 777 type=str, 778 dest="stable_cheeps_host_image_name", 779 required=False, 780 default=None, 781 help=("'cheeps only' The Cheeps host image from which instances are " 782 "launched. If specified here, the value set in Acloud config " 783 "file will be overridden.")) 784 create_parser.add_argument( 785 "--stable-cheeps-host-image-project", 786 type=str, 787 dest="stable_cheeps_host_image_project", 788 required=False, 789 default=None, 790 help=("'cheeps only' The project hosting the specified Cheeps host " 791 "image. If specified here, the value set in Acloud config file " 792 "will be overridden.")) 793 create_parser.add_argument( 794 "--user", 795 type=str, 796 dest="username", 797 required=False, 798 default=None, 799 help="'cheeps only' username to log in to Chrome OS as.") 800 create_parser.add_argument( 801 "--password", 802 type=str, 803 dest="password", 804 required=False, 805 default=None, 806 help="'cheeps only' password to log in to Chrome OS with.") 807 create_parser.add_argument( 808 "--betty-image", 809 type=str, 810 dest="cheeps_betty_image", 811 required=False, 812 default=None, 813 help=("'cheeps only' The L1 betty version to use. Only makes sense " 814 "when launching a controller image with " 815 "stable-cheeps-host-image")) 816 create_parser.add_argument( 817 "--cheeps-feature", 818 type=str, 819 dest="cheeps_features", 820 required=False, 821 action="append", 822 default=[], 823 help=("'cheeps only' Cheeps feature to enable. Can be repeated.")) 824 825 # Arguments for trusty type 826 create_parser.add_argument( 827 "--trusty-host-package", 828 type=str, 829 dest="trusty_host_package", 830 required=False, 831 help="Use the specified path of the trusty host package to create " 832 "instances. e.g. /path/trusty-host_package.tar.gz") 833 create_parser.add_argument( 834 "--local-trusty-image", 835 type=str, 836 dest="local_trusty_image", 837 required=False, 838 help="'trusty only' Use the specified path for the locally built " 839 "trusty emulator images package, built with " 840 "PACKAGE_TRUSTY_IMAGE_TARBALL=true in the Trusty build. E.g., " 841 "/path/trusty_image_package.tar.gz") 842 create_parser.add_argument( 843 "--trusty-build-id", 844 type=str, 845 dest="trusty_build_id", 846 required=False, 847 help="Trusty image package build ID, e.g., 8747889, 8748012.") 848 create_parser.add_argument( 849 "--trusty-branch", 850 type=str, 851 dest="trusty_branch", 852 required=False, 853 help="Trusty image package branch, e.g., aosp-trusty-master.") 854 create_parser.add_argument( 855 "--trusty-build-target", 856 type=str, 857 dest="trusty_build_target", 858 required=False, 859 help="Trusty image package build target, " 860 "e.g., qemu_generic_arm64_test_debug.") 861 862 AddCommonCreateArgs(create_parser) 863 return create_parser 864 865 866def _PositiveInteger(arg): 867 """Convert an argument from a string to a positive integer.""" 868 try: 869 value = int(arg) 870 except ValueError as e: 871 raise argparse.ArgumentTypeError(arg + " is not an integer.") from e 872 if value <= 0: 873 raise argparse.ArgumentTypeError(arg + " is not positive.") 874 return value 875 876 877def _VerifyLocalArgs(args): 878 """Verify args starting with --local. 879 880 Args: 881 args: Namespace object from argparse.parse_args. 882 883 Raises: 884 errors.CheckPathError: Image path doesn't exist. 885 errors.UnsupportedCreateArgs: The specified avd type does not support 886 a provided argument. 887 errors.UnsupportedLocalInstanceId: Local instance ID is invalid. 888 """ 889 if args.local_image and not os.path.exists(args.local_image): 890 raise errors.CheckPathError( 891 "Specified path doesn't exist: %s" % args.local_image) 892 893 if args.local_instance_dir and not os.path.exists(args.local_instance_dir): 894 raise errors.CheckPathError( 895 "Specified path doesn't exist: %s" % args.local_instance_dir) 896 897 if not (args.local_system_image is None or 898 args.avd_type in (constants.TYPE_CF, constants.TYPE_GF)): 899 raise errors.UnsupportedCreateArgs("%s instance does not support " 900 "--local-system-image" % 901 args.avd_type) 902 # TODO(b/179340595): To support local image remote instance with kernel build. 903 if args.local_instance is None and args.local_image is not None and ( 904 args.kernel_branch or args.kernel_build_id): 905 raise errors.UnsupportedCreateArgs( 906 "Acloud didn't support local image with specific kernel. " 907 "Please download the specific kernel and put it into " 908 "your local image folder: '%s'." % ( 909 args.local_image if args.local_image else 910 utils.GetBuildEnvironmentVariable(constants.ENV_ANDROID_PRODUCT_OUT))) 911 912 if (args.local_system_image and 913 not os.path.exists(args.local_system_image)): 914 raise errors.CheckPathError( 915 "Specified path doesn't exist: %s" % args.local_system_image) 916 917 for tool_dir in args.local_tool: 918 if not os.path.exists(tool_dir): 919 raise errors.CheckPathError( 920 "Specified path doesn't exist: %s" % tool_dir) 921 922 923def _VerifyHostArgs(args): 924 """Verify args starting with --host. 925 926 Args: 927 args: Namespace object from argparse.parse_args. 928 929 Raises: 930 errors.UnsupportedCreateArgs: When a create arg is specified but 931 unsupported for remote host mode. 932 """ 933 if args.remote_host and args.local_instance is not None: 934 raise errors.UnsupportedCreateArgs( 935 "--host is not supported for local instance.") 936 937 if args.remote_host and args.num > 1: 938 raise errors.UnsupportedCreateArgs( 939 "--num is not supported for remote host.") 940 941 if args.host_user != constants.GCE_USER and args.remote_host is None: 942 raise errors.UnsupportedCreateArgs( 943 "--host-user is only supported for remote host.") 944 945 if args.host_ssh_private_key_path and args.remote_host is None: 946 raise errors.UnsupportedCreateArgs( 947 "--host-ssh-private-key-path is only supported for remote host.") 948 949 if args.remote_image_dir: 950 if args.remote_host is None: 951 raise errors.UnsupportedCreateArgs( 952 "--remote-image-dir is only supported for remote host.") 953 if remote_path.basename( 954 remote_path.normpath(args.remote_image_dir)) in ("..", "."): 955 raise errors.UnsupportedCreateArgs( 956 "--remote-image-dir must not include the working directory.") 957 958 959def _VerifyGoldfishArgs(args): 960 """Verify goldfish args. 961 962 Args: 963 args: Namespace object from argparse.parse_args. 964 965 Raises: 966 errors.UnsupportedCreateArgs: When a create arg is specified but 967 unsupported for goldfish. 968 """ 969 goldfish_only_flags = [ 970 args.emulator_build_id, 971 args.emulator_build_target, 972 args.emulator_zip 973 ] 974 if args.avd_type != constants.TYPE_GF and any(goldfish_only_flags): 975 raise errors.UnsupportedCreateArgs( 976 f"--emulator-* is only valid with avd_type == {constants.TYPE_GF}") 977 978 # Exclude kernel_build_target because the default value isn't empty. 979 remote_kernel_flags = [ 980 args.kernel_build_id, 981 args.kernel_branch, 982 ] 983 if args.avd_type == constants.TYPE_GF and any(remote_kernel_flags): 984 raise errors.UnsupportedCreateArgs( 985 "--kernel-* is not supported for goldfish.") 986 987 remote_boot_flags = [ 988 args.boot_build_id, 989 args.boot_build_target, 990 args.boot_branch, 991 args.boot_artifact, 992 ] 993 if (args.avd_type == constants.TYPE_GF and any(remote_boot_flags) and 994 not all(remote_boot_flags)): 995 raise errors.UnsupportedCreateArgs( 996 "Either none or all of --boot-branch, --boot-build-target, " 997 "--boot-build-id, and --boot-artifact must be specified for " 998 "goldfish.") 999 1000 remote_system_flags = [ 1001 args.system_build_target, 1002 args.system_build_id, 1003 args.system_branch, 1004 ] 1005 if (args.avd_type == constants.TYPE_GF and any(remote_system_flags) and 1006 not all(remote_system_flags)): 1007 raise errors.UnsupportedCreateArgs( 1008 "Either none or all of --system-branch, --system-build-target, " 1009 "and --system-build-id must be specified for goldfish.") 1010 1011 remote_host_only_flags = remote_boot_flags + remote_system_flags 1012 if args.avd_type == constants.TYPE_GF and args.remote_host is None and any( 1013 remote_host_only_flags): 1014 raise errors.UnsupportedCreateArgs( 1015 "--boot-* and --system-* for goldfish are only supported for " 1016 "remote host.") 1017 1018 1019def _VerifyTrustyArgs(args): 1020 """Verify trusty args. 1021 1022 Args: 1023 args: Namespace object from argparse.parse_args. 1024 1025 Raises: 1026 errors.UnsupportedCreateArgs: When specified arguments are 1027 unsupported for trusty. 1028 errors.CheckPathError: A specified local path does not exist. 1029 """ 1030 if args.avd_type != constants.TYPE_TRUSTY: 1031 if args.local_trusty_image: 1032 raise errors.UnsupportedCreateArgs( 1033 "--local-trusty-image is only valid with " 1034 f"avd_type == {constants.TYPE_TRUSTY}") 1035 if args.trusty_host_package: 1036 raise errors.UnsupportedCreateArgs( 1037 "--trusty-host-package is only valid with " 1038 f"avd_type == {constants.TYPE_TRUSTY}") 1039 # Only check these args if AVD type is Trusty 1040 return 1041 1042 for arg_type, unsupported_args in [ 1043 ( 1044 "--boot-*", 1045 [ 1046 args.boot_build_id, 1047 args.boot_build_target, 1048 args.boot_branch, 1049 args.boot_artifact, 1050 ], 1051 ), 1052 ( 1053 "--bootloader-*", 1054 [ 1055 args.bootloader_build_id, 1056 args.bootloader_build_target, 1057 args.bootloader_branch, 1058 ], 1059 ), 1060 ( 1061 "--android-efi-loader-*", 1062 [ 1063 args.android_efi_loader_build_id, 1064 args.android_efi_loader_artifact, 1065 ], 1066 ), 1067 ( 1068 "--ota-*", 1069 [ 1070 args.ota_branch, 1071 args.ota_build_target, 1072 args.ota_build_id, 1073 ], 1074 ), 1075 ]: 1076 if any(unsupported_args): 1077 raise errors.UnsupportedCreateArgs( 1078 f"{arg_type} is not supported for Trusty." 1079 ) 1080 1081 if args.local_image is None and not args.build_target: 1082 raise errors.UnsupportedCreateArgs( 1083 "Trusty android build target not provided and cannot be " 1084 "auto-detected, use --build-target to specify a build target, " 1085 "e.g. qemu_trusty_arm64-trunk_staging-userdebug") 1086 if args.local_trusty_image: 1087 if not os.path.exists(args.local_trusty_image): 1088 raise errors.CheckPathError( 1089 f"Specified path doesn't exist: {args.local_trusty_image}") 1090 if args.trusty_host_package: 1091 if not os.path.exists(args.trusty_host_package): 1092 raise errors.CheckPathError( 1093 f"Specified path doesn't exist: {args.trusty_host_package}") 1094 1095 1096def VerifyArgs(args): 1097 """Verify args. 1098 1099 Args: 1100 args: Namespace object from argparse.parse_args. 1101 1102 Raises: 1103 errors.UnsupportedMultiAdbPort: multi adb port doesn't support. 1104 errors.UnsupportedCreateArgs: When a create arg is specified but 1105 unsupported for a particular avd type. 1106 (e.g. --system-build-id for gf) 1107 """ 1108 # Verify that user specified flavor name is in support list. 1109 # We don't use argparse's builtin validation because we need to be able to 1110 # tell when a user doesn't specify a flavor. 1111 if args.flavor and args.flavor not in constants.ALL_FLAVORS: 1112 logger.debug("Flavor[%s] isn't in default support list: %s", 1113 args.flavor, constants.ALL_FLAVORS) 1114 1115 if args.avd_type not in (constants.TYPE_CF, constants.TYPE_GF): 1116 if args.system_branch or args.system_build_id or args.system_build_target: 1117 raise errors.UnsupportedCreateArgs( 1118 "--system-* args are not supported for AVD type: %s" 1119 % args.avd_type) 1120 1121 if args.num > 1 and args.adb_port: 1122 raise errors.UnsupportedMultiAdbPort( 1123 "--adb-port is not supported for multi-devices.") 1124 1125 if args.num > 1 and args.local_instance is not None: 1126 raise errors.UnsupportedCreateArgs( 1127 "--num is not supported for local instance.") 1128 1129 if args.local_instance is None and args.gpu == _DEFAULT_GPU: 1130 raise errors.UnsupportedCreateArgs( 1131 "Please assign one gpu model for GCE instance. Reference: " 1132 "https://cloud.google.com/compute/docs/gpus") 1133 1134 if args.adb_port: 1135 utils.CheckPortFree(args.adb_port) 1136 1137 hw_properties = create_common.ParseKeyValuePairArgs(args.hw_property) 1138 for key in hw_properties: 1139 if key not in constants.HW_PROPERTIES: 1140 raise errors.InvalidHWPropertyError( 1141 "[%s] is an invalid hw property, supported values are:%s. " 1142 % (key, constants.HW_PROPERTIES)) 1143 1144 cheeps_only_flags = [args.stable_cheeps_host_image_name, 1145 args.stable_cheeps_host_image_project, 1146 args.username, 1147 args.password, 1148 args.cheeps_betty_image, 1149 args.cheeps_features] 1150 if args.avd_type != constants.TYPE_CHEEPS and any(cheeps_only_flags): 1151 raise errors.UnsupportedCreateArgs( 1152 "--stable-cheeps-*, --betty-image, --cheeps-feature, --username " 1153 "and --password are only valid with avd_type == %s" 1154 % constants.TYPE_CHEEPS) 1155 if (args.username or args.password) and not (args.username and args.password): 1156 raise ValueError("--username and --password must both be set") 1157 if not args.autoconnect and args.unlock_screen: 1158 raise ValueError("--no-autoconnect and --unlock couldn't be " 1159 "passed in together.") 1160 1161 _VerifyGoldfishArgs(args) 1162 _VerifyTrustyArgs(args) 1163 _VerifyLocalArgs(args) 1164 _VerifyHostArgs(args) 1165