1# Copyright 2019 - 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. 14"""A client that manages Cheeps Virtual Device on compute engine. 15 16** CheepsComputeClient ** 17 18CheepsComputeClient derives from AndroidComputeClient. It manges a google 19compute engine project that is setup for running Cheeps Virtual Devices. 20It knows how to create a host instance from a Cheeps Stable Host Image, fetch 21Android build, and start Android within the host instance. 22 23** Class hierarchy ** 24 25 base_cloud_client.BaseCloudApiClient 26 ^ 27 | 28 gcompute_client.ComputeClient 29 ^ 30 | 31 android_compute_client.AndroidComputeClient 32 ^ 33 | 34 cheeps_compute_client.CheepsComputeClient 35""" 36 37import logging 38 39from acloud import errors 40from acloud.internal import constants 41from acloud.internal.lib import android_compute_client 42from acloud.internal.lib import gcompute_client 43 44 45logger = logging.getLogger(__name__) 46 47 48class CheepsComputeClient(android_compute_client.AndroidComputeClient): 49 """Client that manages Cheeps based Android Virtual Device. 50 51 Cheeps is a VM that run Chrome OS which runs on GCE. 52 """ 53 # This is the timeout for betty to start. 54 BOOT_TIMEOUT_SECS = 15*60 55 # This is printed by betty.sh. 56 BOOT_COMPLETED_MSG = "VM successfully started" 57 # systemd prints this if betty.sh returns nonzero status code. 58 BOOT_FAILED_MSG = "betty.service: Failed with result 'exit-code'" 59 60 def CheckBootFailure(self, serial_out, instance): 61 """Overrides superclass. Determines if there's a boot failure.""" 62 if self.BOOT_FAILED_MSG in serial_out: 63 raise errors.DeviceBootError("Betty failed to start") 64 65 # pylint: disable=too-many-locals,arguments-differ 66 def CreateInstance(self, instance, image_name, image_project, avd_spec): 67 """ Creates a cheeps instance in GCE. 68 69 Args: 70 instance: name of the VM 71 image_name: the GCE image to use 72 image_project: project the GCE image is in 73 avd_spec: An AVDSpec instance. 74 """ 75 metadata = self._metadata.copy() 76 metadata[constants.INS_KEY_AVD_TYPE] = constants.TYPE_CHEEPS 77 # Update metadata by avd_spec 78 if avd_spec: 79 metadata["cvd_01_x_res"] = avd_spec.hw_property[constants.HW_X_RES] 80 metadata["cvd_01_y_res"] = avd_spec.hw_property[constants.HW_Y_RES] 81 metadata["cvd_01_dpi"] = avd_spec.hw_property[constants.HW_ALIAS_DPI] 82 metadata[constants.INS_KEY_DISPLAY] = ("%sx%s (%s)" % ( 83 avd_spec.hw_property[constants.HW_X_RES], 84 avd_spec.hw_property[constants.HW_Y_RES], 85 avd_spec.hw_property[constants.HW_ALIAS_DPI])) 86 87 if avd_spec.username: 88 metadata["user"] = avd_spec.username 89 metadata["password"] = avd_spec.password 90 91 metadata["android_build_id"] = avd_spec.remote_image[constants.BUILD_ID] 92 metadata["android_build_target"] = avd_spec.remote_image[constants.BUILD_TARGET] 93 metadata["betty_image"] = avd_spec.cheeps_betty_image 94 metadata["cheeps_features"] = ','.join(avd_spec.cheeps_features) 95 96 gcompute_client.ComputeClient.CreateInstance( 97 self, 98 instance=instance, 99 image_name=image_name, 100 image_project=image_project, 101 disk_args=None, 102 metadata=metadata, 103 machine_type=self._machine_type, 104 network=self._network, 105 zone=self._zone) 106