• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2#
3# Copyright 2018 - The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""GCE device factory.
18
19GCEDeviceFactory provides a base class for AVDs that run on GCE.
20"""
21
22import os
23
24from acloud.internal import constants
25from acloud.internal.lib import auth
26from acloud.internal.lib import cvd_compute_client_multi_stage
27from acloud.internal.lib import ssh
28from acloud.public.actions import base_device_factory
29
30
31class GCEDeviceFactory(base_device_factory.BaseDeviceFactory):
32    """A base class for AVDs that run on GCE."""
33
34    _USER_BUILD = "userbuild"
35
36    def __init__(self, avd_spec, local_image_artifact=None):
37        """Constructs a new remote instance device factory."""
38        self._avd_spec = avd_spec
39        self._cfg = avd_spec.cfg
40        self._local_image_artifact = local_image_artifact
41        self._report_internal_ip = avd_spec.report_internal_ip
42        self.credentials = auth.CreateCredentials(avd_spec.cfg)
43        # Control compute_client with enable_multi_stage
44        compute_client = cvd_compute_client_multi_stage.CvdComputeClient(
45            acloud_config=avd_spec.cfg,
46            oauth2_credentials=self.credentials,
47            ins_timeout_secs=avd_spec.ins_timeout_secs,
48            report_internal_ip=avd_spec.report_internal_ip,
49            gpu=avd_spec.gpu)
50        super(GCEDeviceFactory, self).__init__(compute_client)
51        self._ssh = None
52
53    def _CreateGceInstance(self):
54        """Create a single configured GCE instance.
55
56        build_target: The format is like "aosp_cf_x86_phone". We only get info
57                      from the user build image file name. If the file name is
58                      not custom format (no "-"), we will use $TARGET_PRODUCT
59                      from environment variable as build_target.
60
61        Returns:
62            A string, representing instance name.
63        """
64        image_name = os.path.basename(
65            self._local_image_artifact) if self._local_image_artifact else ""
66        build_target = (os.environ.get(constants.ENV_BUILD_TARGET) if "-" not
67                        in image_name else image_name.split("-")[0])
68        build_id = self._USER_BUILD
69        if self._avd_spec.image_source == constants.IMAGE_SRC_REMOTE:
70            build_id = self._avd_spec.remote_image[constants.BUILD_ID]
71            build_target = self._avd_spec.remote_image[constants.BUILD_TARGET]
72
73        if self._avd_spec.instance_name_to_reuse:
74            instance = self._avd_spec.instance_name_to_reuse
75        else:
76            instance = self._compute_client.GenerateInstanceName(
77                build_target=build_target, build_id=build_id)
78
79        host_image_name = self._compute_client.GetHostImageName(
80            self._cfg.stable_host_image_name,
81            self._cfg.stable_host_image_family,
82            self._cfg.stable_host_image_project)
83
84        # Create an instance from Stable Host Image
85        self._compute_client.CreateInstance(
86            instance=instance,
87            image_name=host_image_name,
88            image_project=self._cfg.stable_host_image_project,
89            blank_data_disk_size_gb=self._cfg.extra_data_disk_size_gb,
90            avd_spec=self._avd_spec)
91        ip = self._compute_client.GetInstanceIP(instance)
92        self._ssh = ssh.Ssh(ip=ip,
93                            user=constants.GCE_USER,
94                            ssh_private_key_path=self._cfg.ssh_private_key_path,
95                            extra_args_ssh_tunnel=self._cfg.extra_args_ssh_tunnel,
96                            report_internal_ip=self._report_internal_ip)
97        return instance
98
99    def GetFailures(self):
100        """Get failures from all devices.
101
102        Returns:
103            A dictionary that contains all the failures.
104            The key is the name of the instance that fails to boot,
105            and the value is an errors.DeviceBootError object.
106        """
107        return self._compute_client.all_failures
108
109    def _SetFailures(self, instance, error_msg):
110        """Set failures from this device.
111
112        Record the failures for any steps in AVD creation.
113
114        Args:
115            instance: String of instance name.
116            error_msg: String of error message.
117        """
118        self._compute_client.all_failures[instance] = error_msg
119