# Copyright 2019 - The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A client that manages Cheeps Virtual Device on compute engine. ** CheepsComputeClient ** CheepsComputeClient derives from AndroidComputeClient. It manges a google compute engine project that is setup for running Cheeps Virtual Devices. It knows how to create a host instance from a Cheeps Stable Host Image, fetch Android build, and start Android within the host instance. ** Class hierarchy ** base_cloud_client.BaseCloudApiClient ^ | gcompute_client.ComputeClient ^ | android_compute_client.AndroidComputeClient ^ | cheeps_compute_client.CheepsComputeClient """ import logging from acloud import errors from acloud.internal import constants from acloud.internal.lib import android_compute_client from acloud.internal.lib import gcompute_client logger = logging.getLogger(__name__) class CheepsComputeClient(android_compute_client.AndroidComputeClient): """Client that manages Cheeps based Android Virtual Device. Cheeps is a VM that run Chrome OS which runs on GCE. """ # This is the timeout for betty to start. BOOT_TIMEOUT_SECS = 15*60 # This is printed by betty.sh. BOOT_COMPLETED_MSG = "VM successfully started" # systemd prints this if betty.sh returns nonzero status code. BOOT_FAILED_MSG = "betty.service: Failed with result 'exit-code'" def CheckBootFailure(self, serial_out, instance): """Overrides superclass. Determines if there's a boot failure.""" if self.BOOT_FAILED_MSG in serial_out: raise errors.DeviceBootError("Betty failed to start") # pylint: disable=too-many-locals,arguments-differ def CreateInstance(self, instance, image_name, image_project, avd_spec): """ Creates a cheeps instance in GCE. Args: instance: name of the VM image_name: the GCE image to use image_project: project the GCE image is in avd_spec: An AVDSpec instance. """ metadata = self._metadata.copy() metadata[constants.INS_KEY_AVD_TYPE] = constants.TYPE_CHEEPS # Update metadata by avd_spec if avd_spec: metadata["cvd_01_x_res"] = avd_spec.hw_property[constants.HW_X_RES] metadata["cvd_01_y_res"] = avd_spec.hw_property[constants.HW_Y_RES] metadata["cvd_01_dpi"] = avd_spec.hw_property[constants.HW_ALIAS_DPI] metadata[constants.INS_KEY_DISPLAY] = ("%sx%s (%s)" % ( avd_spec.hw_property[constants.HW_X_RES], avd_spec.hw_property[constants.HW_Y_RES], avd_spec.hw_property[constants.HW_ALIAS_DPI])) if avd_spec.username: metadata["user"] = avd_spec.username metadata["password"] = avd_spec.password metadata["android_build_id"] = avd_spec.remote_image[constants.BUILD_ID] metadata["android_build_target"] = avd_spec.remote_image[constants.BUILD_TARGET] metadata["betty_image"] = avd_spec.remote_image[constants.CHEEPS_BETTY_IMAGE] gcompute_client.ComputeClient.CreateInstance( self, instance=instance, image_name=image_name, image_project=image_project, disk_args=None, metadata=metadata, machine_type=self._machine_type, network=self._network, zone=self._zone)