xref: /aosp_15_r20/tools/acloud/internal/lib/goldfish_compute_client.py (revision 800a58d989c669b8eb8a71d8df53b1ba3d411444)
1*800a58d9SAndroid Build Coastguard Worker#!/usr/bin/env python
2*800a58d9SAndroid Build Coastguard Worker#
3*800a58d9SAndroid Build Coastguard Worker# Copyright 2018 - The Android Open Source Project
4*800a58d9SAndroid Build Coastguard Worker#
5*800a58d9SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*800a58d9SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*800a58d9SAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*800a58d9SAndroid Build Coastguard Worker#
9*800a58d9SAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
10*800a58d9SAndroid Build Coastguard Worker#
11*800a58d9SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*800a58d9SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*800a58d9SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*800a58d9SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*800a58d9SAndroid Build Coastguard Worker# limitations under the License.
16*800a58d9SAndroid Build Coastguard Worker"""A client that manages Goldfish Virtual Device on compute engine.
17*800a58d9SAndroid Build Coastguard Worker
18*800a58d9SAndroid Build Coastguard Worker** GoldfishComputeClient **
19*800a58d9SAndroid Build Coastguard Worker
20*800a58d9SAndroid Build Coastguard WorkerGoldfishComputeClient derives from AndroidComputeClient. It manges a google
21*800a58d9SAndroid Build Coastguard Workercompute engine project that is setup for running Goldfish Virtual Devices.
22*800a58d9SAndroid Build Coastguard WorkerIt knows how to create a host instance from a Goldfish Stable Host Image, fetch
23*800a58d9SAndroid Build Coastguard WorkerAndroid build, an emulator build, and start Android within the host instance.
24*800a58d9SAndroid Build Coastguard Worker
25*800a58d9SAndroid Build Coastguard Worker** Class hierarchy **
26*800a58d9SAndroid Build Coastguard Worker
27*800a58d9SAndroid Build Coastguard Worker  base_cloud_client.BaseCloudApiClient
28*800a58d9SAndroid Build Coastguard Worker                ^
29*800a58d9SAndroid Build Coastguard Worker                |
30*800a58d9SAndroid Build Coastguard Worker       gcompute_client.ComputeClient
31*800a58d9SAndroid Build Coastguard Worker                ^
32*800a58d9SAndroid Build Coastguard Worker                |
33*800a58d9SAndroid Build Coastguard Worker       android_compute_client.AndroidComputeClient
34*800a58d9SAndroid Build Coastguard Worker                ^
35*800a58d9SAndroid Build Coastguard Worker                |
36*800a58d9SAndroid Build Coastguard Worker       goldfish_compute_client.GoldfishComputeClient
37*800a58d9SAndroid Build Coastguard Worker
38*800a58d9SAndroid Build Coastguard Worker
39*800a58d9SAndroid Build Coastguard WorkerTODO: This class should likely be merged with CvdComputeClient
40*800a58d9SAndroid Build Coastguard Worker"""
41*800a58d9SAndroid Build Coastguard Worker
42*800a58d9SAndroid Build Coastguard Workerimport getpass
43*800a58d9SAndroid Build Coastguard Workerimport logging
44*800a58d9SAndroid Build Coastguard Worker
45*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors
46*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal import constants
47*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import android_compute_client
48*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import gcompute_client
49*800a58d9SAndroid Build Coastguard Worker
50*800a58d9SAndroid Build Coastguard Worker
51*800a58d9SAndroid Build Coastguard Workerlogger = logging.getLogger(__name__)
52*800a58d9SAndroid Build Coastguard Worker
53*800a58d9SAndroid Build Coastguard Worker
54*800a58d9SAndroid Build Coastguard Workerclass GoldfishComputeClient(android_compute_client.AndroidComputeClient):
55*800a58d9SAndroid Build Coastguard Worker    """Client that manages Goldfish based Android Virtual Device.
56*800a58d9SAndroid Build Coastguard Worker
57*800a58d9SAndroid Build Coastguard Worker    Attributes:
58*800a58d9SAndroid Build Coastguard Worker        acloud_config: An AcloudConfig object.
59*800a58d9SAndroid Build Coastguard Worker        oauth2_credentials: An oauth2client.OAuth2Credentials instance.
60*800a58d9SAndroid Build Coastguard Worker    """
61*800a58d9SAndroid Build Coastguard Worker
62*800a58d9SAndroid Build Coastguard Worker    # To determine if the boot failed
63*800a58d9SAndroid Build Coastguard Worker    BOOT_FAILED_MSG = "VIRTUAL_DEVICE_FAILED"
64*800a58d9SAndroid Build Coastguard Worker
65*800a58d9SAndroid Build Coastguard Worker    # To determine the failure reason
66*800a58d9SAndroid Build Coastguard Worker    # If the emulator build is not available
67*800a58d9SAndroid Build Coastguard Worker    EMULATOR_FETCH_FAILED_MSG = "EMULATOR_FETCH_FAILED"
68*800a58d9SAndroid Build Coastguard Worker    # If the system image build is not available
69*800a58d9SAndroid Build Coastguard Worker    ANDROID_FETCH_FAILED_MSG = "ANDROID_FETCH_FAILED"
70*800a58d9SAndroid Build Coastguard Worker    # If the emulator could not boot in time
71*800a58d9SAndroid Build Coastguard Worker    BOOT_TIMEOUT_MSG = "VIRTUAL_DEVICE_BOOT_FAILED"
72*800a58d9SAndroid Build Coastguard Worker
73*800a58d9SAndroid Build Coastguard Worker    #pylint: disable=signature-differs
74*800a58d9SAndroid Build Coastguard Worker    def _GetDiskArgs(self, disk_name, image_name, image_project, disk_size_gb):
75*800a58d9SAndroid Build Coastguard Worker        """Helper to generate disk args that is used to create an instance.
76*800a58d9SAndroid Build Coastguard Worker
77*800a58d9SAndroid Build Coastguard Worker        Args:
78*800a58d9SAndroid Build Coastguard Worker            disk_name: String, the name of disk.
79*800a58d9SAndroid Build Coastguard Worker            image_name: String, the name of the system image.
80*800a58d9SAndroid Build Coastguard Worker            image_project: String, the name of the project where the image.
81*800a58d9SAndroid Build Coastguard Worker            disk_size_gb: Integer, size of the blank data disk in GB.
82*800a58d9SAndroid Build Coastguard Worker
83*800a58d9SAndroid Build Coastguard Worker        Returns:
84*800a58d9SAndroid Build Coastguard Worker            A dictionary representing disk args.
85*800a58d9SAndroid Build Coastguard Worker        """
86*800a58d9SAndroid Build Coastguard Worker        return [{
87*800a58d9SAndroid Build Coastguard Worker            "type": "PERSISTENT",
88*800a58d9SAndroid Build Coastguard Worker            "boot": True,
89*800a58d9SAndroid Build Coastguard Worker            "mode": "READ_WRITE",
90*800a58d9SAndroid Build Coastguard Worker            "autoDelete": True,
91*800a58d9SAndroid Build Coastguard Worker            "initializeParams": {
92*800a58d9SAndroid Build Coastguard Worker                "diskName":
93*800a58d9SAndroid Build Coastguard Worker                disk_name,
94*800a58d9SAndroid Build Coastguard Worker                "sourceImage":
95*800a58d9SAndroid Build Coastguard Worker                self.GetImage(image_name, image_project)["selfLink"],
96*800a58d9SAndroid Build Coastguard Worker                "diskSizeGb":
97*800a58d9SAndroid Build Coastguard Worker                disk_size_gb
98*800a58d9SAndroid Build Coastguard Worker            },
99*800a58d9SAndroid Build Coastguard Worker        }]
100*800a58d9SAndroid Build Coastguard Worker    #pylint: disable=signature-differs
101*800a58d9SAndroid Build Coastguard Worker
102*800a58d9SAndroid Build Coastguard Worker    def CheckBootFailure(self, serial_out, instance):
103*800a58d9SAndroid Build Coastguard Worker        """Overriding method from the parent class.
104*800a58d9SAndroid Build Coastguard Worker
105*800a58d9SAndroid Build Coastguard Worker        Args:
106*800a58d9SAndroid Build Coastguard Worker            serial_out: String
107*800a58d9SAndroid Build Coastguard Worker            instance: String
108*800a58d9SAndroid Build Coastguard Worker
109*800a58d9SAndroid Build Coastguard Worker        Raises:
110*800a58d9SAndroid Build Coastguard Worker            errors.DownloadArtifactError: If it fails to download artifact.
111*800a58d9SAndroid Build Coastguard Worker            errors.DeviceBootError: If it fails to boot up.
112*800a58d9SAndroid Build Coastguard Worker        """
113*800a58d9SAndroid Build Coastguard Worker        if self.BOOT_FAILED_MSG in serial_out:
114*800a58d9SAndroid Build Coastguard Worker            if self.EMULATOR_FETCH_FAILED_MSG in serial_out:
115*800a58d9SAndroid Build Coastguard Worker                raise errors.DownloadArtifactError(
116*800a58d9SAndroid Build Coastguard Worker                    "Failed to download emulator build. Re-run with a newer build."
117*800a58d9SAndroid Build Coastguard Worker                )
118*800a58d9SAndroid Build Coastguard Worker            if self.ANDROID_FETCH_FAILED_MSG in serial_out:
119*800a58d9SAndroid Build Coastguard Worker                raise errors.DownloadArtifactError(
120*800a58d9SAndroid Build Coastguard Worker                    "Failed to download system image build. Re-run with a newer build."
121*800a58d9SAndroid Build Coastguard Worker                )
122*800a58d9SAndroid Build Coastguard Worker            if self.BOOT_TIMEOUT_MSG in serial_out:
123*800a58d9SAndroid Build Coastguard Worker                raise errors.DeviceBootError(
124*800a58d9SAndroid Build Coastguard Worker                    "Emulator timed out while booting.")
125*800a58d9SAndroid Build Coastguard Worker
126*800a58d9SAndroid Build Coastguard Worker    @staticmethod
127*800a58d9SAndroid Build Coastguard Worker    def GetKernelBuildArtifact(target):
128*800a58d9SAndroid Build Coastguard Worker        """Get kernel build artifact name.
129*800a58d9SAndroid Build Coastguard Worker
130*800a58d9SAndroid Build Coastguard Worker        Args:
131*800a58d9SAndroid Build Coastguard Worker            target: String, kernel target name.
132*800a58d9SAndroid Build Coastguard Worker
133*800a58d9SAndroid Build Coastguard Worker        Returns:
134*800a58d9SAndroid Build Coastguard Worker            String of artifact name.
135*800a58d9SAndroid Build Coastguard Worker
136*800a58d9SAndroid Build Coastguard Worker        Raises:
137*800a58d9SAndroid Build Coastguard Worker            errors.DeviceBootError: If it fails to get artifact name.
138*800a58d9SAndroid Build Coastguard Worker        """
139*800a58d9SAndroid Build Coastguard Worker        if target == "kernel":
140*800a58d9SAndroid Build Coastguard Worker            return "bzImage"
141*800a58d9SAndroid Build Coastguard Worker        if target == "kernel_x86_64":
142*800a58d9SAndroid Build Coastguard Worker            return "bzImage"
143*800a58d9SAndroid Build Coastguard Worker        if target == "kernel_aarch64":
144*800a58d9SAndroid Build Coastguard Worker            return "Image.gz"
145*800a58d9SAndroid Build Coastguard Worker        raise errors.DeviceBootError(
146*800a58d9SAndroid Build Coastguard Worker            "Don't know the artifact name for '%s' target" % target)
147*800a58d9SAndroid Build Coastguard Worker
148*800a58d9SAndroid Build Coastguard Worker    # pylint: disable=too-many-locals,arguments-differ
149*800a58d9SAndroid Build Coastguard Worker    # TODO: Refactor CreateInstance to pass in an object instead of all these args.
150*800a58d9SAndroid Build Coastguard Worker    def CreateInstance(self,
151*800a58d9SAndroid Build Coastguard Worker                       instance,
152*800a58d9SAndroid Build Coastguard Worker                       image_name,
153*800a58d9SAndroid Build Coastguard Worker                       image_project,
154*800a58d9SAndroid Build Coastguard Worker                       build_target,
155*800a58d9SAndroid Build Coastguard Worker                       branch,
156*800a58d9SAndroid Build Coastguard Worker                       build_id,
157*800a58d9SAndroid Build Coastguard Worker                       kernel_branch=None,
158*800a58d9SAndroid Build Coastguard Worker                       kernel_build_id=None,
159*800a58d9SAndroid Build Coastguard Worker                       kernel_build_target=None,
160*800a58d9SAndroid Build Coastguard Worker                       emulator_branch=None,
161*800a58d9SAndroid Build Coastguard Worker                       emulator_build_id=None,
162*800a58d9SAndroid Build Coastguard Worker                       emulator_build_target=None,
163*800a58d9SAndroid Build Coastguard Worker                       blank_data_disk_size_gb=None,
164*800a58d9SAndroid Build Coastguard Worker                       gpu=None,
165*800a58d9SAndroid Build Coastguard Worker                       avd_spec=None,
166*800a58d9SAndroid Build Coastguard Worker                       extra_scopes=None,
167*800a58d9SAndroid Build Coastguard Worker                       tags=None,
168*800a58d9SAndroid Build Coastguard Worker                       launch_args=None):
169*800a58d9SAndroid Build Coastguard Worker        """Create a goldfish instance given a stable host image and a build id.
170*800a58d9SAndroid Build Coastguard Worker
171*800a58d9SAndroid Build Coastguard Worker        Args:
172*800a58d9SAndroid Build Coastguard Worker            instance: String, instance name.
173*800a58d9SAndroid Build Coastguard Worker            image_name: String, the name of the system image.
174*800a58d9SAndroid Build Coastguard Worker            image_project: String, name of the project where the image belongs.
175*800a58d9SAndroid Build Coastguard Worker                           Assume the default project if None.
176*800a58d9SAndroid Build Coastguard Worker            build_target: String, target name, e.g. "sdk_phone_x86_64-sdk"
177*800a58d9SAndroid Build Coastguard Worker            branch: String, branch name, e.g. "git_pi-dev"
178*800a58d9SAndroid Build Coastguard Worker            build_id: String, build id, a string, e.g. "2263051", "P2804227"
179*800a58d9SAndroid Build Coastguard Worker            kernel_branch: String, kernel branch name.
180*800a58d9SAndroid Build Coastguard Worker            kernel_build_id: String, kernel build id.
181*800a58d9SAndroid Build Coastguard Worker            kernel_build_target: kernel target, e.g. "kernel_x86_64"
182*800a58d9SAndroid Build Coastguard Worker            emulator_branch: String, emulator branch name, e.g."aosp-emu-master-dev"
183*800a58d9SAndroid Build Coastguard Worker            emulator_build_id: String, emulator build id, a string, e.g. "2263051", "P2804227"
184*800a58d9SAndroid Build Coastguard Worker            emulator_build_target: String, emulator build target.
185*800a58d9SAndroid Build Coastguard Worker            blank_data_disk_size_gb: Integer, size of the blank data disk in GB.
186*800a58d9SAndroid Build Coastguard Worker            gpu: String, GPU that should be attached to the instance, or None of no
187*800a58d9SAndroid Build Coastguard Worker                 acceleration is needed. e.g. "nvidia-tesla-k80"
188*800a58d9SAndroid Build Coastguard Worker            avd_spec: An AVDSpec instance.
189*800a58d9SAndroid Build Coastguard Worker            extra_scopes: A list of extra scopes to be passed to the instance.
190*800a58d9SAndroid Build Coastguard Worker            tags: A list of tags to associate with the instance. e.g.
191*800a58d9SAndroid Build Coastguard Worker                 ["http-server", "https-server"]
192*800a58d9SAndroid Build Coastguard Worker            launch_args: String of args for launch command.
193*800a58d9SAndroid Build Coastguard Worker        """
194*800a58d9SAndroid Build Coastguard Worker        self._VerifyZoneByQuota()
195*800a58d9SAndroid Build Coastguard Worker        self._CheckMachineSize()
196*800a58d9SAndroid Build Coastguard Worker
197*800a58d9SAndroid Build Coastguard Worker        # Add space for possible data partition.
198*800a58d9SAndroid Build Coastguard Worker        boot_disk_size_gb = (
199*800a58d9SAndroid Build Coastguard Worker            int(self.GetImage(image_name, image_project)["diskSizeGb"]) +
200*800a58d9SAndroid Build Coastguard Worker            blank_data_disk_size_gb)
201*800a58d9SAndroid Build Coastguard Worker        disk_args = self._GetDiskArgs(instance, image_name, image_project,
202*800a58d9SAndroid Build Coastguard Worker                                      boot_disk_size_gb)
203*800a58d9SAndroid Build Coastguard Worker
204*800a58d9SAndroid Build Coastguard Worker        # Goldfish instances are metadata compatible with cuttlefish devices.
205*800a58d9SAndroid Build Coastguard Worker        # See details goto/goldfish-deployment
206*800a58d9SAndroid Build Coastguard Worker        metadata = self._metadata.copy()
207*800a58d9SAndroid Build Coastguard Worker        metadata["user"] = getpass.getuser()
208*800a58d9SAndroid Build Coastguard Worker        metadata[constants.INS_KEY_AVD_TYPE] = constants.TYPE_GF
209*800a58d9SAndroid Build Coastguard Worker
210*800a58d9SAndroid Build Coastguard Worker        # Note that we use the same metadata naming conventions as cuttlefish
211*800a58d9SAndroid Build Coastguard Worker        metadata["cvd_01_fetch_android_build_target"] = build_target
212*800a58d9SAndroid Build Coastguard Worker        metadata["cvd_01_fetch_android_bid"] = "{branch}/{build_id}".format(
213*800a58d9SAndroid Build Coastguard Worker            branch=branch, build_id=build_id)
214*800a58d9SAndroid Build Coastguard Worker        if kernel_branch and kernel_build_id and kernel_build_target:
215*800a58d9SAndroid Build Coastguard Worker            metadata["cvd_01_fetch_kernel_bid"] = "{branch}/{build_id}".format(
216*800a58d9SAndroid Build Coastguard Worker                branch=kernel_branch, build_id=kernel_build_id)
217*800a58d9SAndroid Build Coastguard Worker            metadata["cvd_01_fetch_kernel_build_target"] = kernel_build_target
218*800a58d9SAndroid Build Coastguard Worker            metadata["cvd_01_fetch_kernel_build_artifact"] = (
219*800a58d9SAndroid Build Coastguard Worker                self.GetKernelBuildArtifact(kernel_build_target))
220*800a58d9SAndroid Build Coastguard Worker            metadata["cvd_01_use_custom_kernel"] = "true"
221*800a58d9SAndroid Build Coastguard Worker        if emulator_branch and emulator_build_id:
222*800a58d9SAndroid Build Coastguard Worker            metadata[
223*800a58d9SAndroid Build Coastguard Worker                "cvd_01_fetch_emulator_bid"] = "{branch}/{build_id}".format(
224*800a58d9SAndroid Build Coastguard Worker                    branch=emulator_branch, build_id=emulator_build_id)
225*800a58d9SAndroid Build Coastguard Worker        if emulator_build_target:
226*800a58d9SAndroid Build Coastguard Worker            metadata["cvd_01_fetch_emulator_build_target"] = emulator_build_target
227*800a58d9SAndroid Build Coastguard Worker        if launch_args:
228*800a58d9SAndroid Build Coastguard Worker            metadata["launch_args"] = launch_args
229*800a58d9SAndroid Build Coastguard Worker        metadata["cvd_01_launch"] = "1"
230*800a58d9SAndroid Build Coastguard Worker
231*800a58d9SAndroid Build Coastguard Worker        # Update metadata by avd_spec
232*800a58d9SAndroid Build Coastguard Worker        # for legacy create_gf cmd, we will keep using resolution.
233*800a58d9SAndroid Build Coastguard Worker        # And always use avd_spec for acloud create cmd.
234*800a58d9SAndroid Build Coastguard Worker        if avd_spec:
235*800a58d9SAndroid Build Coastguard Worker            metadata[constants.INS_KEY_AVD_FLAVOR] = avd_spec.flavor
236*800a58d9SAndroid Build Coastguard Worker            metadata["cvd_01_x_res"] = avd_spec.hw_property[constants.HW_X_RES]
237*800a58d9SAndroid Build Coastguard Worker            metadata["cvd_01_y_res"] = avd_spec.hw_property[constants.HW_Y_RES]
238*800a58d9SAndroid Build Coastguard Worker            metadata["cvd_01_dpi"] = avd_spec.hw_property[constants.HW_ALIAS_DPI]
239*800a58d9SAndroid Build Coastguard Worker            metadata[constants.INS_KEY_DISPLAY] = ("%sx%s (%s)" % (
240*800a58d9SAndroid Build Coastguard Worker                avd_spec.hw_property[constants.HW_X_RES],
241*800a58d9SAndroid Build Coastguard Worker                avd_spec.hw_property[constants.HW_Y_RES],
242*800a58d9SAndroid Build Coastguard Worker                avd_spec.hw_property[constants.HW_ALIAS_DPI]))
243*800a58d9SAndroid Build Coastguard Worker        else:
244*800a58d9SAndroid Build Coastguard Worker            resolution = self._resolution.split("x")
245*800a58d9SAndroid Build Coastguard Worker            metadata["cvd_01_x_res"] = resolution[0]
246*800a58d9SAndroid Build Coastguard Worker            metadata["cvd_01_y_res"] = resolution[1]
247*800a58d9SAndroid Build Coastguard Worker            metadata["cvd_01_dpi"] = resolution[3]
248*800a58d9SAndroid Build Coastguard Worker
249*800a58d9SAndroid Build Coastguard Worker        gcompute_client.ComputeClient.CreateInstance(
250*800a58d9SAndroid Build Coastguard Worker            self,
251*800a58d9SAndroid Build Coastguard Worker            instance=instance,
252*800a58d9SAndroid Build Coastguard Worker            image_name=image_name,
253*800a58d9SAndroid Build Coastguard Worker            image_project=image_project,
254*800a58d9SAndroid Build Coastguard Worker            disk_args=disk_args,
255*800a58d9SAndroid Build Coastguard Worker            metadata=metadata,
256*800a58d9SAndroid Build Coastguard Worker            machine_type=self._machine_type,
257*800a58d9SAndroid Build Coastguard Worker            network=self._network,
258*800a58d9SAndroid Build Coastguard Worker            zone=self._zone,
259*800a58d9SAndroid Build Coastguard Worker            gpu=gpu,
260*800a58d9SAndroid Build Coastguard Worker            tags=tags,
261*800a58d9SAndroid Build Coastguard Worker            extra_scopes=extra_scopes)
262