1#!/usr/bin/python 2 3"""Upload a local build to Google Compute Engine and run it.""" 4 5import argparse 6import glob 7import os 8import subprocess 9 10 11def gcloud_ssh(args): 12 command = 'gcloud compute ssh %s@%s ' % (args.user, args.instance) 13 if args.zone: 14 command += '--zone=%s ' % args.zone 15 return command 16 17 18def upload_artifacts(args): 19 dir = os.getcwd() 20 try: 21 os.chdir(args.image_dir) 22 artifacts = [] 23 artifact_patterns = ['*.img', 'bootloader'] 24 for artifact_pattern in artifact_patterns: 25 artifacts.extend(glob.glob(artifact_pattern)) 26 if len(artifacts) == 0: 27 raise OSError('No images found in: %s' + args.image_dir) 28 subprocess.check_call( 29 'tar -c -f - --lzop -S ' + ' '.join(artifacts) + 30 ' | ' + 31 gcloud_ssh(args) + '-- tar -x -f - --lzop -S', 32 shell=True) 33 finally: 34 os.chdir(dir) 35 36 host_package = os.path.join(args.host_dir, 'cvd-host_package.tar.gz') 37 subprocess.check_call( 38 gcloud_ssh(args) + '-- tar -x -z -f - < %s' % host_package, 39 shell=True) 40 41 42def launch_cvd(args): 43 launch_cvd_args = '' 44 if args.data_image: 45 launch_cvd_args = ( 46 '--data-image %s ' 47 '--data-policy create_if_missing ' 48 '--blank-data-image-mb %d ' % (args.data_image, args.blank_data_image_mb)) 49 50 subprocess.check_call( 51 gcloud_ssh(args) + '-- ./bin/launch_cvd ' + launch_cvd_args, 52 shell=True) 53 54 55def stop_cvd(args): 56 subprocess.call( 57 gcloud_ssh(args) + '-- ./bin/stop_cvd', 58 shell=True) 59 60 61def __get_default_hostdir(): 62 soong_host_dir = os.environ.get('ANDROID_SOONG_HOST_OUT') 63 if soong_host_dir: 64 return soong_host_dir 65 return os.environ.get('ANDROID_HOST_OUT', '.') 66 67 68def main(): 69 parser = argparse.ArgumentParser( 70 description='Upload a local build to Google Compute Engine and run it') 71 parser.add_argument( 72 '-host_dir', 73 type=str, 74 default=__get_default_hostdir(), 75 help='path to the dist directory') 76 parser.add_argument( 77 '-image_dir', 78 type=str, 79 default=os.environ.get('ANDROID_PRODUCT_OUT', '.'), 80 help='path to the img files') 81 parser.add_argument( 82 '-instance', type=str, required=True, 83 help='instance to update') 84 parser.add_argument( 85 '-zone', type=str, default=None, 86 help='zone containing the instance') 87 parser.add_argument( 88 '-user', type=str, default=os.environ.get('USER', 'vsoc-01'), 89 help='user to update on the instance') 90 parser.add_argument( 91 '-data-image', type=str, default=None, 92 help='userdata image file name, this file will be used instead of default one') 93 parser.add_argument( 94 '-blank-data-image-mb', type=int, default=4098, 95 help='custom userdata image size in megabytes') 96 parser.add_argument( 97 '-launch', default=False, 98 action='store_true', 99 help='launch the device') 100 args = parser.parse_args() 101 stop_cvd(args) 102 upload_artifacts(args) 103 if args.launch: 104 launch_cvd(args) 105 106 107if __name__ == '__main__': 108 main() 109