def _CreateAVD(self, avd_spec, no_prompts): """Create the AVD. Args: avd_spec: AVDSpec object that tells us what we're going to create. no_prompts: Boolean, True to skip all prompts. Returns: A Report instance. """ # Running instances on local is not supported on all OS. if not utils.IsSupportedPlatform(print_warning=True): result_report = report.Report(command="create") result_report.SetStatus(report.Status.FAIL) return result_report local_image_path, host_bins_path = self.GetImageArtifactsPath(avd_spec) # Determine the instance id. if avd_spec.local_instance_id: ins_id = avd_spec.local_instance_id ins_lock = instance.GetLocalInstanceLock(ins_id) if not ins_lock.Lock(): result_report = report.Report(command="create") result_report.AddError("Instance %d is locked by another " "process." % ins_id) result_report.SetStatus(report.Status.FAIL) return result_report else: ins_id = None for candidate_id in range(1, _MAX_INSTANCE_ID + 1): ins_lock = instance.GetLocalInstanceLock(candidate_id) if ins_lock.LockIfNotInUse(timeout_secs=0): ins_id = candidate_id break if not ins_id: result_report = report.Report(command="create") result_report.AddError(_INSTANCES_IN_USE_MSG) result_report.SetStatus(report.Status.FAIL) return result_report logger.info("Selected instance id: %d", ins_id) try: if not self._CheckRunningCvd(ins_id, no_prompts): # Mark as in-use so that it won't be auto-selected again. ins_lock.SetInUse(True) sys.exit(constants.EXIT_BY_USER) result_report = self._CreateInstance(ins_id, local_image_path, host_bins_path, avd_spec, no_prompts) # The infrastructure is able to delete the instance only if the # instance name is reported. This method changes the state to # in-use after creating the report. ins_lock.SetInUse(True) return result_report finally: ins_lock.Unlock()
def testDeleteLocalGoldfishInstanceSuccess(self): """Test DeleteLocalGoldfishInstance.""" mock_adb_tools = mock.Mock() mock_adb_tools.EmuCommand.return_value = 0 mock_instance = mock.Mock(adb=mock_adb_tools, adb_port=5555, device_serial="serial", instance_dir="/unit/test") # name is a positional argument of Mock(). mock_instance.name = "unittest" mock_lock = mock.Mock() mock_lock.Lock.return_value = True mock_instance.GetLock.return_value = mock_lock delete_report = report.Report(command="delete") delete.DeleteLocalGoldfishInstance(mock_instance, delete_report) mock_adb_tools.EmuCommand.assert_called_with("kill") self.assertEqual(delete_report.data, { "deleted": [ { "type": "instance", "name": "unittest", }, ], }) self.assertEqual(delete_report.status, "SUCCESS") mock_lock.SetInUse.assert_called_once_with(False) mock_lock.Unlock.assert_called_once()
def DeleteAndroidVirtualDevices(cfg, instance_names): """Deletes android devices. Args: cfg: An AcloudConfig instance. instance_names: A list of names of the instances to delete. Returns: A Report instance. """ r = report.Report(command="delete") credentials = auth.CreateCredentials(cfg, ALL_SCOPES) compute_client = android_compute_client.AndroidComputeClient(cfg, credentials) try: deleted, failed, error_msgs = compute_client.DeleteInstances( instance_names, cfg.zone) _AddDeletionResultToReport( r, deleted, failed, error_msgs, resource_name="instance") if r.status == report.Status.UNKNOWN: r.SetStatus(report.Status.SUCCESS) except errors.DriverError as e: r.AddError(str(e)) r.SetStatus(report.Status.FAIL) return r
def Run(args): """Run reconnect. Args: args: Namespace object from argparse.parse_args. """ cfg = config.GetAcloudConfig(args) instances_to_reconnect = [] if args.instance_names is not None: # user input instance name to get instance object. instances_to_reconnect = list_instance.GetInstancesFromInstanceNames( cfg, args.instance_names) if not instances_to_reconnect: instances_to_reconnect = list_instance.ChooseInstances(cfg, args.all) reconnect_report = report.Report(command="reconnect") for instance in instances_to_reconnect: if instance.avd_type not in utils.AVD_PORT_DICT: utils.PrintColorString( "Skipping reconnect of instance %s due to " "unknown avd type (%s)." % (instance.name, instance.avd_type), utils.TextColors.WARNING) continue if not instance.islocal: AddPublicSshRsaToInstance(cfg, constants.GCE_USER, instance.name) ReconnectInstance(cfg.ssh_private_key_path, instance, reconnect_report, cfg.extra_args_ssh_tunnel, connect_vnc=(args.autoconnect is True)) utils.PrintDeviceSummary(reconnect_report)
def SwapKernel(self, local_kernel_image): """Swaps the kernel image on target AVD with given kernel. Mounts boot image containing the kernel image to the filesystem, then overwrites that kernel image with a new kernel image, then reboots the Cloud Android instance. Args: local_kernel_image: string, local path to a kernel image. Returns: A Report instance. """ r = report.Report(command='swap_kernel') try: self._ShellCmdOnTarget(MOUNT_CMD) self.PushFile(local_kernel_image, '/boot') self.RebootTarget() except subprocess.CalledProcessError as e: r.AddError(str(e)) r.SetStatus(report.Status.FAIL) return r except errors.DeviceBootTimeoutError as e: r.AddError(str(e)) r.SetStatus(report.Status.BOOT_FAIL) return r r.SetStatus(report.Status.SUCCESS) return r
def PullFileFromInstance(cfg, instance, file_name=None, no_prompts=False): """Pull file from remote CF instance. 1. Download log files to temp folder. 2. If only one file selected, display it on screen. 3. Show the download folder for users. Args: cfg: AcloudConfig object. instance: list.Instance() object. file_name: String of file name. no_prompts: Boolean, True to skip the prompt about file streaming. Returns: A Report instance. """ ssh = Ssh(ip=IP(ip=instance.ip), user=constants.GCE_USER, ssh_private_key_path=cfg.ssh_private_key_path, extra_args_ssh_tunnel=cfg.extra_args_ssh_tunnel) log_files = SelectLogFileToPull(ssh, file_name) download_folder = GetDownloadLogFolder(instance.name) PullLogs(ssh, log_files, download_folder) if len(log_files) == 1: DisplayLog(ssh, log_files[0], no_prompts) return report.Report(command="pull")
def testAddDevice(self): """test AddDevice.""" test_report = report.Report("create") test_report.AddDevice("instance_1", "127.0.0.1", 6520, 6444) expected = { "devices": [{ "instance_name": "instance_1", "ip": "127.0.0.1:6520", "adb_port": 6520, "vnc_port": 6444 }] } self.assertEqual(test_report.data, expected)
def testAddData(self): """test AddData.""" test_report = report.Report("create") test_report.AddData("devices", {"instance_name": "instance_1"}) test_report.AddData("devices", {"instance_name": "instance_2"}) expected = { "devices": [{ "instance_name": "instance_1" }, { "instance_name": "instance_2" }] } self.assertEqual(test_report.data, expected)
def testSetStatus(self): """test SetStatus.""" test_report = report.Report("create") test_report.SetStatus(report.Status.SUCCESS) self.assertEqual(test_report.status, "SUCCESS") test_report.SetStatus(report.Status.FAIL) self.assertEqual(test_report.status, "FAIL") test_report.SetStatus(report.Status.BOOT_FAIL) self.assertEqual(test_report.status, "BOOT_FAIL") # Test that more severe status won't get overriden. test_report.SetStatus(report.Status.FAIL) self.assertEqual(test_report.status, "BOOT_FAIL")
def testAddDeviceBootFailure(self): """test AddDeviceBootFailure.""" test_report = report.Report("create") test_report.AddDeviceBootFailure("instance_1", "127.0.0.1", 6520, 6444, "some errors") expected = { "devices_failing_boot": [{ "instance_name": "instance_1", "ip": "127.0.0.1:6520", "adb_port": 6520, "vnc_port": 6444 }] } self.assertEqual(test_report.data, expected) self.assertEqual(test_report.errors, ["some errors"])
def testDeleteLocalCuttlefishInstanceFailure(self): """Test DeleteLocalCuttlefishInstance with command failure.""" instance_object = mock.MagicMock() instance_object.name = "local-instance" instance_object.Delete.side_effect = subprocess.CalledProcessError( 1, "cmd") mock_lock = mock.Mock() mock_lock.Lock.return_value = True instance_object.GetLock.return_value = mock_lock delete_report = report.Report(command="delete") delete.DeleteLocalCuttlefishInstance(instance_object, delete_report) self.assertEqual(delete_report.status, "FAIL") mock_lock.SetInUse.assert_called_once_with(False) mock_lock.Unlock.assert_called_once()
def PowerwashFromInstance(cfg, instance, instance_id): """Powerwash AVD from remote CF instance. Args: cfg: AcloudConfig object. instance: list.Instance() object. instance_id: Integer of the instance id. Returns: A Report instance. """ ssh = Ssh(ip=IP(ip=instance.ip), user=constants.GCE_USER, ssh_private_key_path=cfg.ssh_private_key_path, extra_args_ssh_tunnel=cfg.extra_args_ssh_tunnel) logger.info("Start to powerwash AVD id (%s) from the instance: %s.", instance_id, instance.name) PowerwashDevice(ssh, instance_id) return report.Report(command="powerwash")
def testDeleteLocalCuttlefishInstanceSuccess(self): """Test DeleteLocalCuttlefishInstance.""" instance_object = mock.MagicMock() instance_object.name = "local-instance" mock_lock = mock.Mock() mock_lock.Lock.return_value = True instance_object.GetLock.return_value = mock_lock delete_report = report.Report(command="delete") delete.DeleteLocalCuttlefishInstance(instance_object, delete_report) self.assertEqual(delete_report.data, { "deleted": [ { "type": "instance", "name": "local-instance", }, ], }) self.assertEqual(delete_report.status, "SUCCESS") mock_lock.SetInUse.assert_called_once_with(False) mock_lock.Unlock.assert_called_once()
def DeleteAndroidVirtualDevices(cfg, instance_names, default_report=None): """Deletes android devices. Args: cfg: An AcloudConfig instance. instance_names: A list of names of the instances to delete. default_report: A initialized Report instance. Returns: A Report instance. """ # delete, failed, error_msgs are used to record result. deleted = [] failed = [] error_msgs = [] r = default_report if default_report else report.Report(command="delete") credentials = auth.CreateCredentials(cfg) compute_client = android_compute_client.AndroidComputeClient( cfg, credentials) zone_instances = compute_client.GetZonesByInstances(instance_names) try: for zone, instances in zone_instances.items(): deleted_ins, failed_ins, error_ins = compute_client.DeleteInstances( instances, zone) deleted.extend(deleted_ins) failed.extend(failed_ins) error_msgs.extend(error_ins) AddDeletionResultToReport(r, deleted, failed, error_msgs, resource_name="instance") if r.status == report.Status.UNKNOWN: r.SetStatus(report.Status.SUCCESS) except errors.DriverError as e: r.AddError(str(e)) r.SetStatus(report.Status.FAIL) return r
def DeleteInstances(cfg, instances_to_delete): """Delete instances according to instances_to_delete. Args: cfg: AcloudConfig object. instances_to_delete: List of list.Instance() object. Returns: Report instance if there are instances to delete, None otherwise. """ if not instances_to_delete: print("No instances to delete") return None delete_report = report.Report(command="delete") remote_instance_list = [] for instance in instances_to_delete: if instance.islocal: if instance.avd_type == constants.TYPE_GF: DeleteLocalGoldfishInstance(instance, delete_report) elif instance.avd_type == constants.TYPE_CF: DeleteLocalCuttlefishInstance(instance, delete_report) else: delete_report.AddError("Deleting %s is not supported." % instance.avd_type) delete_report.SetStatus(report.Status.FAIL) else: remote_instance_list.append(instance.name) # Delete ssvnc viewer if instance.vnc_port: utils.CleanupSSVncviewer(instance.vnc_port) if remote_instance_list: # TODO(119283708): We should move DeleteAndroidVirtualDevices into # delete.py after gce is deprecated. # Stop remote instances. return DeleteRemoteInstances(cfg, remote_instance_list, delete_report) return delete_report
def AddSshRsa(cfg, user, ssh_rsa_path): """Add public ssh rsa key to the project. Args: cfg: An AcloudConfig instance. user: the name of the user which the key belongs to. ssh_rsa_path: The absolute path to public rsa key. Returns: A Report instance. """ r = report.Report(command="sshkey") try: credentials = auth.CreateCredentials(cfg, ALL_SCOPES) compute_client = android_compute_client.AndroidComputeClient( cfg, credentials) compute_client.AddSshRsa(user, ssh_rsa_path) r.SetStatus(report.Status.SUCCESS) except errors.DriverError as e: r.AddError(str(e)) r.SetStatus(report.Status.FAIL) return r
def testDeleteLocalGoldfishInstanceFailure(self): """Test DeleteLocalGoldfishInstance with adb command failure.""" mock_adb_tools = mock.Mock() mock_adb_tools.EmuCommand.return_value = 1 mock_instance = mock.Mock(adb=mock_adb_tools, adb_port=5555, device_serial="serial", instance_dir="/unit/test") # name is a positional argument of Mock(). mock_instance.name = "unittest" mock_lock = mock.Mock() mock_lock.Lock.return_value = True mock_instance.GetLock.return_value = mock_lock delete_report = report.Report(command="delete") delete.DeleteLocalGoldfishInstance(mock_instance, delete_report) mock_adb_tools.EmuCommand.assert_called_with("kill") self.assertTrue(len(delete_report.errors) > 0) self.assertEqual(delete_report.status, "FAIL") mock_lock.SetInUse.assert_called_once_with(False) mock_lock.Unlock.assert_called_once()
def CleanUpRemoteHost(cfg, remote_host, host_user, host_ssh_private_key_path=None): """Clean up the remote host. Args: cfg: An AcloudConfig instance. remote_host : String, ip address or host name of the remote host. host_user: String of user login into the instance. host_ssh_private_key_path: String of host key for logging in to the host. Returns: A Report instance. """ delete_report = report.Report(command="delete") credentials = auth.CreateCredentials(cfg) compute_client = cvd_compute_client_multi_stage.CvdComputeClient( acloud_config=cfg, oauth2_credentials=credentials) ssh = ssh_object.Ssh( ip=ssh_object.IP(ip=remote_host), user=host_user, ssh_private_key_path=( host_ssh_private_key_path or cfg.ssh_private_key_path)) try: compute_client.InitRemoteHost(ssh, remote_host, host_user) delete_report.SetStatus(report.Status.SUCCESS) device_driver.AddDeletionResultToReport( delete_report, [remote_host], failed=[], error_msgs=[], resource_name="remote host") except subprocess.CalledProcessError as e: delete_report.AddError(str(e)) delete_report.SetStatus(report.Status.FAIL) return delete_report
def DeleteInstanceByNames(cfg, instances): """Delete instances by the names of these instances. Args: cfg: AcloudConfig object. instances: List of instance name. Returns: A Report instance. """ delete_report = report.Report(command="delete") local_instances = [ ins for ins in instances if ins.startswith(_LOCAL_INSTANCE_PREFIX) ] remote_instances = list(set(instances) - set(local_instances)) if local_instances: utils.PrintColorString("Deleting local instances") delete_report = DeleteInstances( cfg, list_instances.GetLocalInstancesByNames(local_instances)) if remote_instances: delete_report = DeleteRemoteInstances(cfg, remote_instances, delete_report) return delete_report
def CreateDevices(command, cfg, device_factory, num, avd_type, report_internal_ip=False, autoconnect=False, serial_log_file=None, client_adb_port=None, boot_timeout_secs=None, unlock_screen=False, wait_for_boot=True, connect_webrtc=False): """Create a set of devices using the given factory. Main jobs in create devices. 1. Create GCE instance: Launch instance in GCP(Google Cloud Platform). 2. Starting up AVD: Wait device boot up. Args: command: The name of the command, used for reporting. cfg: An AcloudConfig instance. device_factory: A factory capable of producing a single device. num: The number of devices to create. avd_type: String, the AVD type(cuttlefish, goldfish...). report_internal_ip: Boolean to report the internal ip instead of external ip. serial_log_file: String, the file path to tar the serial logs. autoconnect: Boolean, whether to auto connect to device. client_adb_port: Integer, Specify port for adb forwarding. boot_timeout_secs: Integer, boot timeout secs. unlock_screen: Boolean, whether to unlock screen after invoke vnc client. wait_for_boot: Boolean, True to check serial log include boot up message. connect_webrtc: Boolean, whether to auto connect webrtc to device. Raises: errors: Create instance fail. Returns: A Report instance. """ reporter = report.Report(command=command) try: CreateSshKeyPairIfNecessary(cfg) device_pool = DevicePool(device_factory) device_pool.CreateDevices(num) device_pool.SetDeviceBuildInfo() if wait_for_boot: failures = device_pool.WaitForBoot(boot_timeout_secs) else: failures = device_factory.GetFailures() if failures: reporter.SetStatus(report.Status.BOOT_FAIL) else: reporter.SetStatus(report.Status.SUCCESS) # Collect logs if serial_log_file: device_pool.CollectSerialPortLogs( serial_log_file, port=constants.DEFAULT_SERIAL_PORT) device_pool.UpdateReport(reporter) # Write result to report. for device in device_pool.devices: ip = (device.ip.internal if report_internal_ip else device.ip.external) device_dict = {"ip": ip, "instance_name": device.instance_name} if device.build_info: device_dict.update(device.build_info) if device.time_info: device_dict.update(device.time_info) if autoconnect: forwarded_ports = utils.AutoConnect( ip_addr=ip, rsa_key_file=cfg.ssh_private_key_path, target_vnc_port=utils.AVD_PORT_DICT[avd_type].vnc_port, target_adb_port=utils.AVD_PORT_DICT[avd_type].adb_port, ssh_user=constants.GCE_USER, client_adb_port=client_adb_port, extra_args_ssh_tunnel=cfg.extra_args_ssh_tunnel) device_dict[constants.VNC_PORT] = forwarded_ports.vnc_port device_dict[constants.ADB_PORT] = forwarded_ports.adb_port if unlock_screen: AdbTools(forwarded_ports.adb_port).AutoUnlockScreen() if connect_webrtc: utils.EstablishWebRTCSshTunnel( ip_addr=ip, rsa_key_file=cfg.ssh_private_key_path, ssh_user=constants.GCE_USER, extra_args_ssh_tunnel=cfg.extra_args_ssh_tunnel) if device.instance_name in failures: device_dict[_ERROR_TYPE] = _DICT_ERROR_TYPE[device.stage] reporter.AddData(key="devices_failing_boot", value=device_dict) reporter.AddError(str(failures[device.instance_name])) else: reporter.AddData(key="devices", value=device_dict) except errors.DriverError as e: reporter.AddError(str(e)) reporter.SetStatus(report.Status.FAIL) return reporter
def testAddError(self): """test AddError.""" test_report = report.Report("create") test_report.errors.append("some errors") test_report.errors.append("some errors") self.assertEqual(test_report.errors, ["some errors", "some errors"])
def CreateGCETypeAVD(cfg, build_target=None, build_id=None, num=1, gce_image=None, local_disk_image=None, cleanup=True, serial_log_file=None, autoconnect=False, report_internal_ip=False, avd_spec=None): """Creates one or multiple gce android devices. Args: cfg: An AcloudConfig instance. build_target: Target name, e.g. "aosp_cf_x86_phone-userdebug" build_id: Build id, a string, e.g. "2263051", "P2804227" num: Number of devices to create. gce_image: string, if given, will use this gce image instead of creating a new one. implies cleanup=False. local_disk_image: string, path to a local disk image, e.g. /tmp/avd-system.tar.gz cleanup: boolean, if True clean up compute engine image and disk image in storage after creating the instance. serial_log_file: A path to a file where serial output should be saved to. autoconnect: Create ssh tunnel(s) and adb connect after device creation. report_internal_ip: Boolean to report the internal ip instead of external ip. avd_spec: AVDSpec object for pass hw_property. Returns: A Report instance. """ r = report.Report(command="create") credentials = auth.CreateCredentials(cfg) compute_client = android_compute_client.AndroidComputeClient( cfg, credentials) try: common_operations.CreateSshKeyPairIfNecessary(cfg) device_pool = AndroidVirtualDevicePool(cfg) device_pool.CreateDevices( num, build_target, build_id, gce_image, local_disk_image, cleanup, extra_data_disk_size_gb=cfg.extra_data_disk_size_gb, precreated_data_image=cfg.precreated_data_image_map.get( cfg.extra_data_disk_size_gb), avd_spec=avd_spec, extra_scopes=cfg.extra_scopes) failures = device_pool.WaitForBoot() # Write result to report. for device in device_pool.devices: ip = (device.ip.internal if report_internal_ip else device.ip.external) device_dict = {"ip": ip, "instance_name": device.instance_name} if autoconnect: forwarded_ports = utils.AutoConnect( ip_addr=ip, rsa_key_file=cfg.ssh_private_key_path, target_vnc_port=constants.GCE_VNC_PORT, target_adb_port=constants.GCE_ADB_PORT, ssh_user=_SSH_USER, client_adb_port=avd_spec.client_adb_port, extra_args_ssh_tunnel=cfg.extra_args_ssh_tunnel) device_dict[constants.VNC_PORT] = forwarded_ports.vnc_port device_dict[constants.ADB_PORT] = forwarded_ports.adb_port if avd_spec.unlock_screen: AdbTools(forwarded_ports.adb_port).AutoUnlockScreen() if device.instance_name in failures: r.AddData(key="devices_failing_boot", value=device_dict) r.AddError(str(failures[device.instance_name])) else: r.AddData(key="devices", value=device_dict) if failures: r.SetStatus(report.Status.BOOT_FAIL) else: r.SetStatus(report.Status.SUCCESS) # Dump serial logs. if serial_log_file: _FetchSerialLogsFromDevices( compute_client, instance_names=[d.instance_name for d in device_pool.devices], port=constants.DEFAULT_SERIAL_PORT, output_file=serial_log_file) except errors.DriverError as e: r.AddError(str(e)) r.SetStatus(report.Status.FAIL) return r
def Cleanup(cfg, expiration_mins): """Cleans up stale gce images, gce instances, and disk images in storage. Args: cfg: An AcloudConfig instance. expiration_mins: Integer, resources older than |expiration_mins| will be cleaned up. Returns: A Report instance. """ r = report.Report(command="cleanup") try: cut_time = (datetime.datetime.now(dateutil.tz.tzlocal()) - datetime.timedelta(minutes=expiration_mins)) logger.info( "Cleaning up any gce images/instances and cached build artifacts." "in google storage that are older than %s", cut_time) credentials = auth.CreateCredentials(cfg, ALL_SCOPES) compute_client = android_compute_client.AndroidComputeClient( cfg, credentials) storage_client = gstorage_client.StorageClient(credentials) # Cleanup expired instances items = compute_client.ListInstances(zone=cfg.zone) cleanup_list = [ item["name"] for item in _FindOldItems(items, cut_time, "creationTimestamp") ] logger.info("Found expired instances: %s", cleanup_list) for i in range(0, len(cleanup_list), MAX_BATCH_CLEANUP_COUNT): result = compute_client.DeleteInstances( instances=cleanup_list[i:i + MAX_BATCH_CLEANUP_COUNT], zone=cfg.zone) _AddDeletionResultToReport(r, *result, resource_name="instance") # Cleanup expired images items = compute_client.ListImages() skip_list = cfg.precreated_data_image_map.viewvalues() cleanup_list = [ item["name"] for item in _FindOldItems(items, cut_time, "creationTimestamp") if item["name"] not in skip_list ] logger.info("Found expired images: %s", cleanup_list) for i in range(0, len(cleanup_list), MAX_BATCH_CLEANUP_COUNT): result = compute_client.DeleteImages( image_names=cleanup_list[i:i + MAX_BATCH_CLEANUP_COUNT]) _AddDeletionResultToReport(r, *result, resource_name="image") # Cleanup expired disks # Disks should have been attached to instances with autoDelete=True. # However, sometimes disks may not be auto deleted successfully. items = compute_client.ListDisks(zone=cfg.zone) cleanup_list = [ item["name"] for item in _FindOldItems(items, cut_time, "creationTimestamp") if not item.get("users") ] logger.info("Found expired disks: %s", cleanup_list) for i in range(0, len(cleanup_list), MAX_BATCH_CLEANUP_COUNT): result = compute_client.DeleteDisks( disk_names=cleanup_list[i:i + MAX_BATCH_CLEANUP_COUNT], zone=cfg.zone) _AddDeletionResultToReport(r, *result, resource_name="disk") # Cleanup expired google storage items = storage_client.List(bucket_name=cfg.storage_bucket_name) cleanup_list = [ item["name"] for item in _FindOldItems(items, cut_time, "timeCreated") ] logger.info("Found expired cached artifacts: %s", cleanup_list) for i in range(0, len(cleanup_list), MAX_BATCH_CLEANUP_COUNT): result = storage_client.DeleteFiles( bucket_name=cfg.storage_bucket_name, object_names=cleanup_list[i:i + MAX_BATCH_CLEANUP_COUNT]) _AddDeletionResultToReport( r, *result, resource_name="cached_build_artifact") # Everything succeeded, write status to report. if r.status == report.Status.UNKNOWN: r.SetStatus(report.Status.SUCCESS) except errors.DriverError as e: r.AddError(str(e)) r.SetStatus(report.Status.FAIL) return r
def CreateAndroidVirtualDevices(cfg, build_target=None, build_id=None, num=1, gce_image=None, local_disk_image=None, cleanup=True, serial_log_file=None, logcat_file=None): """Creates one or multiple android devices. Args: cfg: An AcloudConfig instance. build_target: Target name, e.g. "gce_x86-userdebug" build_id: Build id, a string, e.g. "2263051", "P2804227" num: Number of devices to create. gce_image: string, if given, will use this gce image instead of creating a new one. implies cleanup=False. local_disk_image: string, path to a local disk image, e.g. /tmp/avd-system.tar.gz cleanup: boolean, if True clean up compute engine image and disk image in storage after creating the instance. serial_log_file: A path to a file where serial output should be saved to. logcat_file: A path to a file where logcat logs should be saved. Returns: A Report instance. """ r = report.Report(command="create") credentials = auth.CreateCredentials(cfg, ALL_SCOPES) compute_client = android_compute_client.AndroidComputeClient(cfg, credentials) try: _CreateSshKeyPairIfNecessary(cfg) device_pool = AndroidVirtualDevicePool(cfg) device_pool.CreateDevices( num, build_target, build_id, gce_image, local_disk_image, cleanup, extra_data_disk_size_gb=cfg.extra_data_disk_size_gb, precreated_data_image=cfg.precreated_data_image_map.get( cfg.extra_data_disk_size_gb)) failures = device_pool.WaitForBoot() # Write result to report. for device in device_pool.devices: device_dict = {"ip": device.ip, "instance_name": device.instance_name} if device.instance_name in failures: r.AddData(key="devices_failing_boot", value=device_dict) r.AddError(str(failures[device.instance_name])) else: r.AddData(key="devices", value=device_dict) if failures: r.SetStatus(report.Status.BOOT_FAIL) else: r.SetStatus(report.Status.SUCCESS) # Dump serial and logcat logs. if serial_log_file: _FetchSerialLogsFromDevices( compute_client, instance_names=[d.instance_name for d in device_pool.devices], port=constants.DEFAULT_SERIAL_PORT, output_file=serial_log_file) if logcat_file: _FetchSerialLogsFromDevices( compute_client, instance_names=[d.instance_name for d in device_pool.devices], port=constants.LOGCAT_SERIAL_PORT, output_file=logcat_file) except errors.DriverError as e: r.AddError(str(e)) r.SetStatus(report.Status.FAIL) return r
def _CreateInstance(self, local_instance_id, local_image_path, host_bins_path, avd_spec, no_prompts): """Create a CVD instance. Args: local_instance_id: Integer of instance id. local_image_path: String of local image directory. host_bins_path: String of host package directory. avd_spec: AVDSpec for the instance. no_prompts: Boolean, True to skip all prompts. Returns: A Report instance. """ if avd_spec.connect_webrtc: utils.ReleasePort(constants.WEBRTC_LOCAL_PORT) launch_cvd_path = os.path.join(host_bins_path, "bin", constants.CMD_LAUNCH_CVD) cmd = self.PrepareLaunchCVDCmd(launch_cvd_path, avd_spec.hw_property, avd_spec.connect_adb, local_image_path, local_instance_id, avd_spec.connect_webrtc, avd_spec.gpu) result_report = report.Report(command="create") instance_name = instance.GetLocalInstanceName(local_instance_id) try: self._LaunchCvd(cmd, local_instance_id, host_bins_path, (avd_spec.boot_timeout_secs or constants.DEFAULT_CF_BOOT_TIMEOUT)) except errors.LaunchCVDFail as launch_error: result_report.SetStatus(report.Status.BOOT_FAIL) result_report.AddDeviceBootFailure(instance_name, constants.LOCALHOST, None, None, error=str(launch_error)) return result_report active_ins = list_instance.GetActiveCVD(local_instance_id) if active_ins: result_report.SetStatus(report.Status.SUCCESS) result_report.AddDevice(instance_name, constants.LOCALHOST, active_ins.adb_port, active_ins.vnc_port) # Launch vnc client if we're auto-connecting. if avd_spec.connect_vnc: utils.LaunchVNCFromReport(result_report, avd_spec, no_prompts) if avd_spec.connect_webrtc: utils.LaunchBrowserFromReport(result_report) if avd_spec.unlock_screen: AdbTools(active_ins.adb_port).AutoUnlockScreen() else: err_msg = "cvd_status return non-zero after launch_cvd" logger.error(err_msg) result_report.SetStatus(report.Status.BOOT_FAIL) result_report.AddDeviceBootFailure(instance_name, constants.LOCALHOST, None, None, error=err_msg) return result_report