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 only' Host package branch name. e.g. aosp-main") 265 parser.add_argument( 266 "--host-package-build-id", "--host_package_build_id", 267 type=str, 268 dest="host_package_build_id", 269 required=False, 270 help="'cuttlefish only' Host package build id, e.g. 2145099, P2804227") 271 parser.add_argument( 272 "--host-package-build-target", "--host_package_build_target", 273 type=str, 274 dest="host_package_build_target", 275 required=False, 276 help="'cuttlefish only' Host package build target, e.g. " 277 "cf_x86_64_phone-userdebug.") 278 parser.add_argument( 279 "--system-branch", 280 type=str, 281 dest="system_branch", 282 help="'cuttlefish only' Branch to consume the system image (system.img) " 283 "from, will default to what is defined by --branch. " 284 "That feature allows to (automatically) test various combinations " 285 "of vendor.img (CF, e.g.) and system images (GSI, e.g.). ", 286 required=False) 287 parser.add_argument( 288 "--system-build-id", 289 type=str, 290 dest="system_build_id", 291 help="'cuttlefish only' System image build id, e.g. 2145099, P2804227", 292 required=False) 293 parser.add_argument( 294 "--system-build-target", 295 type=str, 296 dest="system_build_target", 297 help="'cuttlefish only' System image build target, specify if different " 298 "from --build-target", 299 required=False) 300 parser.add_argument( 301 "--launch-args", 302 type=str, 303 dest="launch_args", 304 help="'cuttlefish only' Add extra args to launch_cvd command.", 305 required=False) 306 parser.add_argument( 307 "--pet-name", 308 "--webrtc_device_id", 309 type=str, 310 dest="webrtc_device_id", 311 help="'cuttlefish only' Give the pet name of the instance.", 312 required=False) 313 parser.add_argument( 314 "--gce-metadata", 315 type=str, 316 dest="gce_metadata", 317 default=None, 318 help="'GCE instance only' Record data into GCE instance metadata with " 319 "key-value pair format. e.g. id:12,name:unknown.") 320 parser.add_argument( 321 "--fetch_cvd-build-id", 322 type=str, 323 dest="fetch_cvd_build_id", 324 required=False, 325 help="'cuttlefish only' Build id of fetch_cvd, e.g. 2145099, P2804227") 326 # TODO(146314062): Remove --multi-stage-launch after infra don't use this 327 # args. 328 parser.add_argument( 329 "--multi-stage-launch", 330 dest="multi_stage_launch", 331 action="store_true", 332 required=False, 333 default=True, 334 help="Enable the multi-stage cuttlefish launch.") 335 parser.add_argument( 336 "--no-multi-stage-launch", 337 dest="multi_stage_launch", 338 action="store_false", 339 required=False, 340 default=None, 341 help="Disable the multi-stage cuttlefish launch.") 342 parser.add_argument( 343 "--no-pull-log", 344 dest="no_pull_log", 345 action="store_true", 346 required=False, 347 default=None, 348 help="Disable auto download logs when AVD booting up failed.") 349 parser.add_argument( 350 "--no-mkcert", 351 dest="mkcert", 352 action="store_false", 353 required=False, 354 default=True, 355 help="Disable mkcert setup process on the host.") 356 # TODO(147335651): Add gpu in user config. 357 # TODO(147335651): Support "--gpu" without giving any value. 358 parser.add_argument( 359 "--gpu", 360 type=str, 361 const=_DEFAULT_GPU, 362 nargs="?", 363 dest="gpu", 364 required=False, 365 default=None, 366 help="GPU accelerator to use if any. e.g. nvidia-tesla-k80. For local " 367 "instances, this arg without assigning any value is to enable " 368 "local gpu support.") 369 parser.add_argument( 370 "--num-avds-per-instance", 371 "--num-instances", 372 "--num_instances", 373 type=int, 374 dest="num_avds_per_instance", 375 required=False, 376 default=1, 377 help="'cuttlefish only' Create multiple cuttlefish AVDs in one local " 378 "instance.") 379 parser.add_argument( 380 "--connect-hostname", 381 action="store_true", 382 dest="connect_hostname", 383 required=False, 384 default=False, 385 help="Ssh connects to the GCE instance with hostname.") 386 parser.add_argument( 387 "--gce-only", 388 action="store_true", 389 dest="gce_only", 390 required=False, 391 default=False, 392 help="Only create the GCE instance. It won't create virtual devices.") 393 # Hide following args for users, it is only used in infra. 394 parser.add_argument( 395 "--local-instance-dir", 396 dest="local_instance_dir", 397 required=False, 398 help=argparse.SUPPRESS) 399 parser.add_argument( 400 "--remote-image-dir", 401 dest="remote_image_dir", 402 required=False, 403 # 'cuttlefish remote host only' Upload images and cvd host package to 404 # the remote directory instead of the instance's own directory. If the 405 # directory has been initialized, acloud ignores the image arguments 406 # given by command line and reuses the images in the directory. 407 help=argparse.SUPPRESS) 408 parser.add_argument( 409 "--oxygen", 410 action="store_true", 411 dest="oxygen", 412 required=False, 413 help=argparse.SUPPRESS) 414 parser.add_argument( 415 "--zone", 416 type=str, 417 dest="zone", 418 required=False, 419 help=argparse.SUPPRESS) 420 421 # TODO(b/118439885): Old arg formats to support transition, delete when 422 # transistion is done. 423 parser.add_argument( 424 "--serial_log_file", 425 type=str, 426 dest="serial_log_file", 427 required=False, 428 help=argparse.SUPPRESS) 429 parser.add_argument( 430 "--build_id", 431 type=str, 432 dest="build_id", 433 required=False, 434 help=argparse.SUPPRESS) 435 parser.add_argument( 436 "--build_target", 437 type=str, 438 dest="build_target", 439 required=False, 440 help=argparse.SUPPRESS) 441 parser.add_argument( 442 "--system_branch", 443 type=str, 444 dest="system_branch", 445 required=False, 446 help=argparse.SUPPRESS) 447 parser.add_argument( 448 "--system_build_id", 449 type=str, 450 dest="system_build_id", 451 required=False, 452 help=argparse.SUPPRESS) 453 parser.add_argument( 454 "--system_build_target", 455 type=str, 456 dest="system_build_target", 457 required=False, 458 help=argparse.SUPPRESS) 459 parser.add_argument( 460 "--kernel_build_id", 461 type=str, 462 dest="kernel_build_id", 463 required=False, 464 help=argparse.SUPPRESS) 465 parser.add_argument( 466 "--kernel_branch", 467 type=str, 468 dest="kernel_branch", 469 required=False, 470 help=argparse.SUPPRESS) 471 parser.add_argument( 472 "--kernel_build_target", 473 type=str, 474 dest="kernel_build_target", 475 default="kernel", 476 help=argparse.SUPPRESS) 477 parser.add_argument( 478 "--bootloader_branch", 479 type=str, 480 dest="bootloader_branch", 481 help=argparse.SUPPRESS, 482 required=False) 483 parser.add_argument( 484 "--bootloader_build_id", 485 type=str, 486 dest="bootloader_build_id", 487 help=argparse.SUPPRESS, 488 required=False) 489 parser.add_argument( 490 "--bootloader_build_target", 491 type=str, 492 dest="bootloader_build_target", 493 help=argparse.SUPPRESS, 494 required=False) 495 parser.add_argument( 496 "--fetch_cvd_build_id", 497 type=str, 498 dest="fetch_cvd_build_id", 499 help=argparse.SUPPRESS, 500 required=False) 501 parser.add_argument( 502 "--remote-fetch", 503 action="store_true", 504 dest="remote_fetch", 505 required=False, 506 default=None, 507 help="'cuttlefish only' Fetch artifacts in remote host.") 508 parser.add_argument( 509 "--fetch-cvd-wrapper", 510 dest="fetch_cvd_wrapper", 511 type=str, 512 required=False, 513 help="'cuttlefish only' Fetch artifacts in remote host by a" 514 " provided static executable fetch cvd wrapper file. " 515 " (Still in experiment, this flag only works on lab hosts" 516 " with special setup.)") 517 518 519def GetCreateArgParser(subparser): 520 """Return the create arg parser. 521 522 Args: 523 subparser: argparse.ArgumentParser that is attached to main acloud cmd. 524 525 Returns: 526 argparse.ArgumentParser with create options defined. 527 """ 528 create_parser = subparser.add_parser(CMD_CREATE) 529 create_parser.required = False 530 create_parser.set_defaults(which=CMD_CREATE) 531 # Use default=None to distinguish remote instance or local. The instance 532 # type will be remote if the arg is not provided. 533 create_parser.add_argument( 534 "--local-instance", 535 type=_PositiveInteger, 536 const=0, 537 metavar="ID", 538 nargs="?", 539 dest="local_instance", 540 required=False, 541 help="Create a local AVD instance using the resources associated with " 542 "the ID. Choose an unused ID automatically if the value is " 543 "not specified (primarily for infra usage).") 544 create_parser.add_argument( 545 "--adb-port", "-p", 546 type=int, 547 default=None, 548 dest="adb_port", 549 required=False, 550 help="Specify port for adb forwarding.") 551 create_parser.add_argument( 552 "--base-instance-num", 553 type=int, 554 default=None, 555 dest="base_instance_num", 556 required=False, 557 help="'cuttlefish only' The instance number of the created device.") 558 create_parser.add_argument( 559 "--avd-type", 560 type=str, 561 dest="avd_type", 562 default=constants.TYPE_CF, 563 choices=[constants.TYPE_GCE, constants.TYPE_CF, constants.TYPE_GF, constants.TYPE_CHEEPS, 564 constants.TYPE_FVP], 565 help="Android Virtual Device type (default %s)." % constants.TYPE_CF) 566 create_parser.add_argument( 567 "--config", "--flavor", 568 type=str, 569 dest="flavor", 570 help="The device flavor of the AVD (default %s). e.g. phone, tv, foldable." 571 % constants.FLAVOR_PHONE) 572 create_parser.add_argument( 573 "--local-image", 574 const=constants.FIND_IN_BUILD_ENV, 575 type=str, 576 dest="local_image", 577 nargs="?", 578 required=False, 579 help="Use the locally built image for the AVD. Look for the image " 580 "artifact in $ANDROID_PRODUCT_OUT if no args value is provided." 581 "e.g --local-image or --local-image /path/to/dir or --local-image " 582 "/path/to/file") 583 create_parser.add_argument( 584 "--local-kernel-image", "--local-boot-image", 585 const=constants.FIND_IN_BUILD_ENV, 586 type=str, 587 dest="local_kernel_image", 588 nargs="?", 589 required=False, 590 help="Use the locally built kernel and ramdisk for the AVD. Look " 591 "for boot.img, vendor_boot.img, kernel, initramfs.img, etc. if the " 592 "argument is a directory. Look for the images in $ANDROID_PRODUCT_OUT " 593 "if no argument is provided. e.g., --local-kernel-image, " 594 "--local-kernel-image /path/to/dir, or --local-kernel-image " 595 "/path/to/boot.img") 596 create_parser.add_argument( 597 "--local-system-image", 598 const=constants.FIND_IN_BUILD_ENV, 599 type=str, 600 dest="local_system_image", 601 nargs="?", 602 required=False, 603 help="Use the locally built system images for the AVD. Look for the " 604 "images in $ANDROID_PRODUCT_OUT if no args value is provided. " 605 "e.g., --local-system-image, --local-system-image /path/to/dir, or " 606 "--local-system-image /path/to/img") 607 create_parser.add_argument( 608 "--local-system_dlkm-image", 609 const=constants.FIND_IN_BUILD_ENV, 610 type=str, 611 dest="local_system_dlkm_image", 612 nargs="?", 613 required=False, 614 help="`remote host only` Use the locally built system_dlkm image for " 615 "the AVD. Look for the image in $ANDROID_PRODUCT_OUT if no args value " 616 "is provided.") 617 create_parser.add_argument( 618 "--local-vendor-image", 619 const=constants.FIND_IN_BUILD_ENV, 620 type=str, 621 dest="local_vendor_image", 622 nargs="?", 623 required=False, 624 help="'cuttlefish only' Use the locally built vendor images for the " 625 "AVD. Look for vendor.img, vendor_dlkm.img, odm.img, and odm_dlkm.img " 626 "if the argument is a directory. Look for the images in " 627 "$ANDROID_PRODUCT_OUT if no argument is provided. e.g., " 628 "--local-vendor-image, or --local-vendor-image /path/to/dir") 629 create_parser.add_argument( 630 "--local-vendor_boot-image", "--local-vendor-boot-image", 631 const=constants.FIND_IN_BUILD_ENV, 632 type=str, 633 dest="local_vendor_boot_image", 634 nargs="?", 635 required=False, 636 help="'cuttlefish only' Use the locally built vendor boot image for " 637 "the AVD. Look for the vendor_boot.img in $ANDROID_PRODUCT_OUT " 638 "if no argument is provided. e.g., --local-vendor-boot-image, or " 639 "--local-vendor-boot-image /path/to/dir, or " 640 "--local-vendor-boot-image /path/to/img") 641 create_parser.add_argument( 642 "--local-tool", 643 type=str, 644 dest="local_tool", 645 action="append", 646 default=[], 647 required=False, 648 help="Use the tools in the specified directory to create local " 649 "instances. The directory structure follows $ANDROID_SOONG_HOST_OUT " 650 "or $ANDROID_EMULATOR_PREBUILTS.") 651 create_parser.add_argument( 652 "--cvd-host-package", 653 type=str, 654 dest="cvd_host_package", 655 required=False, 656 help="Use the specified path of the cvd host package to create " 657 "instances. e.g. /path/cvd-host_package_v1.tar.gz") 658 create_parser.add_argument( 659 "--image-download-dir", 660 type=str, 661 dest="image_download_dir", 662 required=False, 663 help="Define remote image download directory, e.g. /usr/local/dl.") 664 create_parser.add_argument( 665 "--yes", "-y", 666 action="store_true", 667 dest="no_prompt", 668 required=False, 669 help=("Automatic yes to prompts. Assume 'yes' as answer to all prompts " 670 "and run non-interactively.")) 671 create_parser.add_argument( 672 "--reuse-gce", 673 type=str, 674 const=constants.SELECT_ONE_GCE_INSTANCE, 675 nargs="?", 676 dest="reuse_gce", 677 required=False, 678 help="'cuttlefish only' This can help users use their own instance. " 679 "Reusing specific gce instance if --reuse-gce [instance_name] is " 680 "provided. Select one gce instance to reuse if --reuse-gce is " 681 "provided.") 682 create_parser.add_argument( 683 "--openwrt", 684 action="store_true", 685 dest="openwrt", 686 required=False, 687 help="'cuttlefish only' Create OpenWrt device when launching cuttlefish " 688 "device.") 689 create_parser.add_argument( 690 "--use-launch_cvd", 691 action="store_true", 692 dest="use_launch_cvd", 693 required=False, 694 help="'cuttlefish only' Use launch_cvd to create cuttlefish devices.") 695 create_parser.add_argument( 696 "--host", 697 type=str, 698 dest="remote_host", 699 default=None, 700 help="'cuttlefish only' Provide host name to clean up the remote host. " 701 "For example: '--host 1.1.1.1'") 702 create_parser.add_argument( 703 "--host-user", 704 type=str, 705 dest="host_user", 706 default=constants.GCE_USER, 707 help="'remote host only' Provide host user for logging in to the host. " 708 "The default value is vsoc-01. For example: '--host 1.1.1.1 --host-user " 709 "vsoc-02'") 710 create_parser.add_argument( 711 "--host-ssh-private-key-path", 712 type=str, 713 dest="host_ssh_private_key_path", 714 default=None, 715 help="'remote host only' Provide host key for login on on this host.") 716 # User should not specify --spec and --hw_property at the same time. 717 hw_spec_group = create_parser.add_mutually_exclusive_group() 718 hw_spec_group.add_argument( 719 "--hw-property", 720 type=str, 721 dest="hw_property", 722 required=False, 723 help="Supported HW properties and example values: %s" % 724 constants.HW_PROPERTIES_CMD_EXAMPLE) 725 hw_spec_group.add_argument( 726 "--spec", 727 type=str, 728 dest="spec", 729 required=False, 730 choices=constants.SPEC_NAMES, 731 help="The name of a pre-configured device spec that we are " 732 "going to use.") 733 create_parser.add_argument( 734 "--disk-type", 735 type=str, 736 dest="disk_type", 737 required=False, 738 help="This is used to customize the GCE instance disk type, the " 739 "default disk type is from the stable host image. Use pd-ssd or " 740 "pd-standard to specify instance disk type.") 741 create_parser.add_argument( 742 "--stable-host-image-name", 743 type=str, 744 dest="stable_host_image_name", 745 required=False, 746 default=None, 747 help=("'cuttlefish only' The Cuttlefish host image from which instances " 748 "are launched. If specified here, the value set in Acloud config " 749 "file will be overridden.")) 750 751 # Arguments for goldfish type. 752 create_parser.add_argument( 753 "--emulator-build-id", 754 type=str, 755 dest="emulator_build_id", 756 required=False, 757 help="'goldfish only' Emulator build ID used to run the images. " 758 "e.g. 4669466.") 759 create_parser.add_argument( 760 "--emulator-build-target", 761 dest="emulator_build_target", 762 required=False, 763 help="'goldfish remote host only' Emulator build target used to run " 764 "the images. e.g. emulator-linux_x64_nolocationui.") 765 create_parser.add_argument( 766 "--emulator-zip", 767 dest="emulator_zip", 768 required=False, 769 help="'goldfish remote host only' Emulator zip used to run the " 770 "images. e.g., /path/sdk-repo-linux-emulator-1234567.zip.") 771 772 # Arguments for cheeps type. 773 create_parser.add_argument( 774 "--stable-cheeps-host-image-name", 775 type=str, 776 dest="stable_cheeps_host_image_name", 777 required=False, 778 default=None, 779 help=("'cheeps only' The Cheeps host image from which instances are " 780 "launched. If specified here, the value set in Acloud config " 781 "file will be overridden.")) 782 create_parser.add_argument( 783 "--stable-cheeps-host-image-project", 784 type=str, 785 dest="stable_cheeps_host_image_project", 786 required=False, 787 default=None, 788 help=("'cheeps only' The project hosting the specified Cheeps host " 789 "image. If specified here, the value set in Acloud config file " 790 "will be overridden.")) 791 create_parser.add_argument( 792 "--user", 793 type=str, 794 dest="username", 795 required=False, 796 default=None, 797 help="'cheeps only' username to log in to Chrome OS as.") 798 create_parser.add_argument( 799 "--password", 800 type=str, 801 dest="password", 802 required=False, 803 default=None, 804 help="'cheeps only' password to log in to Chrome OS with.") 805 create_parser.add_argument( 806 "--betty-image", 807 type=str, 808 dest="cheeps_betty_image", 809 required=False, 810 default=None, 811 help=("'cheeps only' The L1 betty version to use. Only makes sense " 812 "when launching a controller image with " 813 "stable-cheeps-host-image")) 814 create_parser.add_argument( 815 "--cheeps-feature", 816 type=str, 817 dest="cheeps_features", 818 required=False, 819 action="append", 820 default=[], 821 help=("'cheeps only' Cheeps feature to enable. Can be repeated.")) 822 823 AddCommonCreateArgs(create_parser) 824 return create_parser 825 826 827def _PositiveInteger(arg): 828 """Convert an argument from a string to a positive integer.""" 829 try: 830 value = int(arg) 831 except ValueError as e: 832 raise argparse.ArgumentTypeError(arg + " is not an integer.") from e 833 if value <= 0: 834 raise argparse.ArgumentTypeError(arg + " is not positive.") 835 return value 836 837 838def _VerifyLocalArgs(args): 839 """Verify args starting with --local. 840 841 Args: 842 args: Namespace object from argparse.parse_args. 843 844 Raises: 845 errors.CheckPathError: Image path doesn't exist. 846 errors.UnsupportedCreateArgs: The specified avd type does not support 847 --local-system-image. 848 errors.UnsupportedLocalInstanceId: Local instance ID is invalid. 849 """ 850 if args.local_image and not os.path.exists(args.local_image): 851 raise errors.CheckPathError( 852 "Specified path doesn't exist: %s" % args.local_image) 853 854 if args.local_instance_dir and not os.path.exists(args.local_instance_dir): 855 raise errors.CheckPathError( 856 "Specified path doesn't exist: %s" % args.local_instance_dir) 857 858 if not (args.local_system_image is None or 859 args.avd_type in (constants.TYPE_CF, constants.TYPE_GF)): 860 raise errors.UnsupportedCreateArgs("%s instance does not support " 861 "--local-system-image" % 862 args.avd_type) 863 # TODO(b/179340595): To support local image remote instance with kernel build. 864 if args.local_instance is None and args.local_image is not None and ( 865 args.kernel_branch or args.kernel_build_id): 866 raise errors.UnsupportedCreateArgs( 867 "Acloud didn't support local image with specific kernel. " 868 "Please download the specific kernel and put it into " 869 "your local image folder: '%s'." % ( 870 args.local_image if args.local_image else 871 utils.GetBuildEnvironmentVariable(constants.ENV_ANDROID_PRODUCT_OUT))) 872 873 if (args.local_system_image and 874 not os.path.exists(args.local_system_image)): 875 raise errors.CheckPathError( 876 "Specified path doesn't exist: %s" % args.local_system_image) 877 878 for tool_dir in args.local_tool: 879 if not os.path.exists(tool_dir): 880 raise errors.CheckPathError( 881 "Specified path doesn't exist: %s" % tool_dir) 882 883 884def _VerifyHostArgs(args): 885 """Verify args starting with --host. 886 887 Args: 888 args: Namespace object from argparse.parse_args. 889 890 Raises: 891 errors.UnsupportedCreateArgs: When a create arg is specified but 892 unsupported for remote host mode. 893 """ 894 if args.remote_host and args.local_instance is not None: 895 raise errors.UnsupportedCreateArgs( 896 "--host is not supported for local instance.") 897 898 if args.remote_host and args.num > 1: 899 raise errors.UnsupportedCreateArgs( 900 "--num is not supported for remote host.") 901 902 if args.host_user != constants.GCE_USER and args.remote_host is None: 903 raise errors.UnsupportedCreateArgs( 904 "--host-user is only supported for remote host.") 905 906 if args.host_ssh_private_key_path and args.remote_host is None: 907 raise errors.UnsupportedCreateArgs( 908 "--host-ssh-private-key-path is only supported for remote host.") 909 910 if args.remote_image_dir: 911 if args.remote_host is None: 912 raise errors.UnsupportedCreateArgs( 913 "--remote-image-dir is only supported for remote host.") 914 if remote_path.basename( 915 remote_path.normpath(args.remote_image_dir)) in ("..", "."): 916 raise errors.UnsupportedCreateArgs( 917 "--remote-image-dir must not include the working directory.") 918 919 920def _VerifyGoldfishArgs(args): 921 """Verify goldfish args. 922 923 Args: 924 args: Namespace object from argparse.parse_args. 925 926 Raises: 927 errors.UnsupportedCreateArgs: When a create arg is specified but 928 unsupported for goldfish. 929 """ 930 goldfish_only_flags = [ 931 args.emulator_build_id, 932 args.emulator_build_target, 933 args.emulator_zip 934 ] 935 if args.avd_type != constants.TYPE_GF and any(goldfish_only_flags): 936 raise errors.UnsupportedCreateArgs( 937 f"--emulator-* is only valid with avd_type == {constants.TYPE_GF}") 938 939 # Exclude kernel_build_target because the default value isn't empty. 940 remote_kernel_flags = [ 941 args.kernel_build_id, 942 args.kernel_branch, 943 ] 944 if args.avd_type == constants.TYPE_GF and any(remote_kernel_flags): 945 raise errors.UnsupportedCreateArgs( 946 "--kernel-* is not supported for goldfish.") 947 948 remote_boot_flags = [ 949 args.boot_build_id, 950 args.boot_build_target, 951 args.boot_branch, 952 args.boot_artifact, 953 ] 954 if (args.avd_type == constants.TYPE_GF and any(remote_boot_flags) and 955 not all(remote_boot_flags)): 956 raise errors.UnsupportedCreateArgs( 957 "Either none or all of --boot-branch, --boot-build-target, " 958 "--boot-build-id, and --boot-artifact must be specified for " 959 "goldfish.") 960 961 remote_system_flags = [ 962 args.system_build_target, 963 args.system_build_id, 964 args.system_branch, 965 ] 966 if (args.avd_type == constants.TYPE_GF and any(remote_system_flags) and 967 not all(remote_system_flags)): 968 raise errors.UnsupportedCreateArgs( 969 "Either none or all of --system-branch, --system-build-target, " 970 "and --system-build-id must be specified for goldfish.") 971 972 remote_host_only_flags = remote_boot_flags + remote_system_flags 973 if args.avd_type == constants.TYPE_GF and args.remote_host is None and any( 974 remote_host_only_flags): 975 raise errors.UnsupportedCreateArgs( 976 "--boot-* and --system-* for goldfish are only supported for " 977 "remote host.") 978 979 980def VerifyArgs(args): 981 """Verify args. 982 983 Args: 984 args: Namespace object from argparse.parse_args. 985 986 Raises: 987 errors.UnsupportedMultiAdbPort: multi adb port doesn't support. 988 errors.UnsupportedCreateArgs: When a create arg is specified but 989 unsupported for a particular avd type. 990 (e.g. --system-build-id for gf) 991 """ 992 # Verify that user specified flavor name is in support list. 993 # We don't use argparse's builtin validation because we need to be able to 994 # tell when a user doesn't specify a flavor. 995 if args.flavor and args.flavor not in constants.ALL_FLAVORS: 996 logger.debug("Flavor[%s] isn't in default support list: %s", 997 args.flavor, constants.ALL_FLAVORS) 998 999 if args.avd_type not in (constants.TYPE_CF, constants.TYPE_GF): 1000 if args.system_branch or args.system_build_id or args.system_build_target: 1001 raise errors.UnsupportedCreateArgs( 1002 "--system-* args are not supported for AVD type: %s" 1003 % args.avd_type) 1004 1005 if args.num > 1 and args.adb_port: 1006 raise errors.UnsupportedMultiAdbPort( 1007 "--adb-port is not supported for multi-devices.") 1008 1009 if args.num > 1 and args.local_instance is not None: 1010 raise errors.UnsupportedCreateArgs( 1011 "--num is not supported for local instance.") 1012 1013 if args.local_instance is None and args.gpu == _DEFAULT_GPU: 1014 raise errors.UnsupportedCreateArgs( 1015 "Please assign one gpu model for GCE instance. Reference: " 1016 "https://cloud.google.com/compute/docs/gpus") 1017 1018 if args.adb_port: 1019 utils.CheckPortFree(args.adb_port) 1020 1021 hw_properties = create_common.ParseKeyValuePairArgs(args.hw_property) 1022 for key in hw_properties: 1023 if key not in constants.HW_PROPERTIES: 1024 raise errors.InvalidHWPropertyError( 1025 "[%s] is an invalid hw property, supported values are:%s. " 1026 % (key, constants.HW_PROPERTIES)) 1027 1028 cheeps_only_flags = [args.stable_cheeps_host_image_name, 1029 args.stable_cheeps_host_image_project, 1030 args.username, 1031 args.password, 1032 args.cheeps_betty_image, 1033 args.cheeps_features] 1034 if args.avd_type != constants.TYPE_CHEEPS and any(cheeps_only_flags): 1035 raise errors.UnsupportedCreateArgs( 1036 "--stable-cheeps-*, --betty-image, --cheeps-feature, --username " 1037 "and --password are only valid with avd_type == %s" 1038 % constants.TYPE_CHEEPS) 1039 if (args.username or args.password) and not (args.username and args.password): 1040 raise ValueError("--username and --password must both be set") 1041 if not args.autoconnect and args.unlock_screen: 1042 raise ValueError("--no-autoconnect and --unlock couldn't be " 1043 "passed in together.") 1044 1045 _VerifyGoldfishArgs(args) 1046 _VerifyLocalArgs(args) 1047 _VerifyHostArgs(args) 1048