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