1*800a58d9SAndroid Build Coastguard Worker#!/usr/bin/env python 2*800a58d9SAndroid Build Coastguard Worker# 3*800a58d9SAndroid Build Coastguard Worker# Copyright 2016 - 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 17*800a58d9SAndroid Build Coastguard Worker"""Config manager. 18*800a58d9SAndroid Build Coastguard Worker 19*800a58d9SAndroid Build Coastguard WorkerThree protobuf messages are defined in 20*800a58d9SAndroid Build Coastguard Worker driver/internal/config/proto/internal_config.proto 21*800a58d9SAndroid Build Coastguard Worker driver/internal/config/proto/user_config.proto 22*800a58d9SAndroid Build Coastguard Worker 23*800a58d9SAndroid Build Coastguard WorkerInternal config file User config file 24*800a58d9SAndroid Build Coastguard Worker | | 25*800a58d9SAndroid Build Coastguard Worker v v 26*800a58d9SAndroid Build Coastguard Worker InternalConfig UserConfig 27*800a58d9SAndroid Build Coastguard Worker (proto message) (proto message) 28*800a58d9SAndroid Build Coastguard Worker | | 29*800a58d9SAndroid Build Coastguard Worker | | 30*800a58d9SAndroid Build Coastguard Worker |-> AcloudConfig <-| 31*800a58d9SAndroid Build Coastguard Worker 32*800a58d9SAndroid Build Coastguard WorkerAt runtime, AcloudConfigManager performs the following steps. 33*800a58d9SAndroid Build Coastguard Worker- Load driver config file into a InternalConfig message instance. 34*800a58d9SAndroid Build Coastguard Worker- Load user config file into a UserConfig message instance. 35*800a58d9SAndroid Build Coastguard Worker- Create AcloudConfig using InternalConfig and UserConfig. 36*800a58d9SAndroid Build Coastguard Worker 37*800a58d9SAndroid Build Coastguard WorkerTODO: 38*800a58d9SAndroid Build Coastguard Worker 1. Add support for override configs with command line args. 39*800a58d9SAndroid Build Coastguard Worker 2. Scan all configs to find the right config for given branch and build_id. 40*800a58d9SAndroid Build Coastguard Worker Raise an error if the given build_id is smaller than min_build_id 41*800a58d9SAndroid Build Coastguard Worker only applies to release build id. 42*800a58d9SAndroid Build Coastguard Worker Raise an error if the branch is not supported. 43*800a58d9SAndroid Build Coastguard Worker 44*800a58d9SAndroid Build Coastguard Worker""" 45*800a58d9SAndroid Build Coastguard Worker 46*800a58d9SAndroid Build Coastguard Workerimport logging 47*800a58d9SAndroid Build Coastguard Workerimport importlib.resources 48*800a58d9SAndroid Build Coastguard Workerimport os 49*800a58d9SAndroid Build Coastguard Worker 50*800a58d9SAndroid Build Coastguard Workerfrom google.protobuf import text_format 51*800a58d9SAndroid Build Coastguard Worker 52*800a58d9SAndroid Build Coastguard Worker# pylint: disable=no-name-in-module,import-error 53*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors 54*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal import constants 55*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.proto import internal_config_pb2 56*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.proto import user_config_pb2 57*800a58d9SAndroid Build Coastguard Workerfrom acloud.create import create_args 58*800a58d9SAndroid Build Coastguard Worker 59*800a58d9SAndroid Build Coastguard Worker 60*800a58d9SAndroid Build Coastguard Workerlogger = logging.getLogger(__name__) 61*800a58d9SAndroid Build Coastguard Worker 62*800a58d9SAndroid Build Coastguard Worker_DEFAULT_CONFIG_FILE = "acloud.config" 63*800a58d9SAndroid Build Coastguard Worker_DEFAULT_HW_PROPERTY = "cpu:4,resolution:720x1280,dpi:320,memory:4g" 64*800a58d9SAndroid Build Coastguard Worker 65*800a58d9SAndroid Build Coastguard Worker# Resources 66*800a58d9SAndroid Build Coastguard Worker_INTERNAL_CONFIG_FILE = "default.config" 67*800a58d9SAndroid Build Coastguard Worker_VERSION_FILE = "VERSION" 68*800a58d9SAndroid Build Coastguard Worker_UNKNOWN = "UNKNOWN" 69*800a58d9SAndroid Build Coastguard Worker_NUM_INSTANCES_ARG = "-num_instances" 70*800a58d9SAndroid Build Coastguard Worker 71*800a58d9SAndroid Build Coastguard Worker 72*800a58d9SAndroid Build Coastguard Workerdef _OpenTextResource(resource): 73*800a58d9SAndroid Build Coastguard Worker # Acloud binary does not have the embedded launcher, and it should be 74*800a58d9SAndroid Build Coastguard Worker # compatible with python3.7 installed on the test servers. 75*800a58d9SAndroid Build Coastguard Worker return importlib.resources.open_text("acloud.public.data", resource) 76*800a58d9SAndroid Build Coastguard Worker 77*800a58d9SAndroid Build Coastguard Worker 78*800a58d9SAndroid Build Coastguard Workerdef GetVersion(): 79*800a58d9SAndroid Build Coastguard Worker """Print the version of acloud. 80*800a58d9SAndroid Build Coastguard Worker 81*800a58d9SAndroid Build Coastguard Worker The VERSION file is built into the acloud binary. The version file path is 82*800a58d9SAndroid Build Coastguard Worker under "public/data". 83*800a58d9SAndroid Build Coastguard Worker 84*800a58d9SAndroid Build Coastguard Worker Returns: 85*800a58d9SAndroid Build Coastguard Worker String of the acloud version. 86*800a58d9SAndroid Build Coastguard Worker """ 87*800a58d9SAndroid Build Coastguard Worker try: 88*800a58d9SAndroid Build Coastguard Worker with _OpenTextResource(_VERSION_FILE) as version_file: 89*800a58d9SAndroid Build Coastguard Worker return version_file.read() 90*800a58d9SAndroid Build Coastguard Worker except FileNotFoundError: 91*800a58d9SAndroid Build Coastguard Worker return _UNKNOWN 92*800a58d9SAndroid Build Coastguard Worker 93*800a58d9SAndroid Build Coastguard Worker 94*800a58d9SAndroid Build Coastguard Workerdef GetDefaultConfigFile(): 95*800a58d9SAndroid Build Coastguard Worker """Return path to default config file.""" 96*800a58d9SAndroid Build Coastguard Worker config_path = os.path.join(os.path.expanduser("~"), ".config", "acloud") 97*800a58d9SAndroid Build Coastguard Worker # Create the default config dir if it doesn't exist. 98*800a58d9SAndroid Build Coastguard Worker if not os.path.exists(config_path): 99*800a58d9SAndroid Build Coastguard Worker os.makedirs(config_path) 100*800a58d9SAndroid Build Coastguard Worker return os.path.join(config_path, _DEFAULT_CONFIG_FILE) 101*800a58d9SAndroid Build Coastguard Worker 102*800a58d9SAndroid Build Coastguard Worker 103*800a58d9SAndroid Build Coastguard Workerdef GetUserConfigPath(config_path): 104*800a58d9SAndroid Build Coastguard Worker """Get Acloud user config file path. 105*800a58d9SAndroid Build Coastguard Worker 106*800a58d9SAndroid Build Coastguard Worker If there is no config provided, Acloud would use default config path. 107*800a58d9SAndroid Build Coastguard Worker 108*800a58d9SAndroid Build Coastguard Worker Args: 109*800a58d9SAndroid Build Coastguard Worker config_path: String, path of Acloud config file. 110*800a58d9SAndroid Build Coastguard Worker 111*800a58d9SAndroid Build Coastguard Worker Returns: 112*800a58d9SAndroid Build Coastguard Worker Path (string) of the Acloud config. 113*800a58d9SAndroid Build Coastguard Worker """ 114*800a58d9SAndroid Build Coastguard Worker if config_path: 115*800a58d9SAndroid Build Coastguard Worker return config_path 116*800a58d9SAndroid Build Coastguard Worker return GetDefaultConfigFile() 117*800a58d9SAndroid Build Coastguard Worker 118*800a58d9SAndroid Build Coastguard Worker 119*800a58d9SAndroid Build Coastguard Workerdef GetAcloudConfig(args): 120*800a58d9SAndroid Build Coastguard Worker """Helper function to initialize Config object. 121*800a58d9SAndroid Build Coastguard Worker 122*800a58d9SAndroid Build Coastguard Worker Args: 123*800a58d9SAndroid Build Coastguard Worker args: Namespace object from argparse.parse_args. 124*800a58d9SAndroid Build Coastguard Worker 125*800a58d9SAndroid Build Coastguard Worker Return: 126*800a58d9SAndroid Build Coastguard Worker An instance of AcloudConfig. 127*800a58d9SAndroid Build Coastguard Worker """ 128*800a58d9SAndroid Build Coastguard Worker config_mgr = AcloudConfigManager(args.config_file) 129*800a58d9SAndroid Build Coastguard Worker cfg = config_mgr.Load() 130*800a58d9SAndroid Build Coastguard Worker cfg.OverrideWithArgs(args) 131*800a58d9SAndroid Build Coastguard Worker return cfg 132*800a58d9SAndroid Build Coastguard Worker 133*800a58d9SAndroid Build Coastguard Worker 134*800a58d9SAndroid Build Coastguard Workerclass AcloudConfig(): 135*800a58d9SAndroid Build Coastguard Worker """A class that holds all configurations for acloud.""" 136*800a58d9SAndroid Build Coastguard Worker 137*800a58d9SAndroid Build Coastguard Worker REQUIRED_FIELD = [ 138*800a58d9SAndroid Build Coastguard Worker "machine_type", "network", "min_machine_size", 139*800a58d9SAndroid Build Coastguard Worker "disk_image_name", "disk_image_mime_type" 140*800a58d9SAndroid Build Coastguard Worker ] 141*800a58d9SAndroid Build Coastguard Worker 142*800a58d9SAndroid Build Coastguard Worker # pylint: disable=too-many-statements 143*800a58d9SAndroid Build Coastguard Worker def __init__(self, usr_cfg, internal_cfg): 144*800a58d9SAndroid Build Coastguard Worker """Initialize. 145*800a58d9SAndroid Build Coastguard Worker 146*800a58d9SAndroid Build Coastguard Worker Args: 147*800a58d9SAndroid Build Coastguard Worker usr_cfg: A protobuf object that holds the user configurations. 148*800a58d9SAndroid Build Coastguard Worker internal_cfg: A protobuf object that holds internal configurations. 149*800a58d9SAndroid Build Coastguard Worker """ 150*800a58d9SAndroid Build Coastguard Worker self.service_account_name = usr_cfg.service_account_name 151*800a58d9SAndroid Build Coastguard Worker # pylint: disable=invalid-name 152*800a58d9SAndroid Build Coastguard Worker self.service_account_private_key_path = ( 153*800a58d9SAndroid Build Coastguard Worker usr_cfg.service_account_private_key_path) 154*800a58d9SAndroid Build Coastguard Worker self.service_account_json_private_key_path = ( 155*800a58d9SAndroid Build Coastguard Worker usr_cfg.service_account_json_private_key_path) 156*800a58d9SAndroid Build Coastguard Worker self.creds_cache_file = internal_cfg.creds_cache_file 157*800a58d9SAndroid Build Coastguard Worker self.user_agent = internal_cfg.user_agent 158*800a58d9SAndroid Build Coastguard Worker self.client_id = usr_cfg.client_id 159*800a58d9SAndroid Build Coastguard Worker self.client_secret = usr_cfg.client_secret 160*800a58d9SAndroid Build Coastguard Worker 161*800a58d9SAndroid Build Coastguard Worker self.project = usr_cfg.project 162*800a58d9SAndroid Build Coastguard Worker self.zone = usr_cfg.zone 163*800a58d9SAndroid Build Coastguard Worker self.machine_type = (usr_cfg.machine_type or 164*800a58d9SAndroid Build Coastguard Worker internal_cfg.default_usr_cfg.machine_type) 165*800a58d9SAndroid Build Coastguard Worker self.network = usr_cfg.network or internal_cfg.default_usr_cfg.network 166*800a58d9SAndroid Build Coastguard Worker self.ssh_private_key_path = usr_cfg.ssh_private_key_path 167*800a58d9SAndroid Build Coastguard Worker self.ssh_public_key_path = usr_cfg.ssh_public_key_path 168*800a58d9SAndroid Build Coastguard Worker self.storage_bucket_name = usr_cfg.storage_bucket_name 169*800a58d9SAndroid Build Coastguard Worker self.metadata_variable = dict( 170*800a58d9SAndroid Build Coastguard Worker internal_cfg.default_usr_cfg.metadata_variable.items()) 171*800a58d9SAndroid Build Coastguard Worker self.metadata_variable.update(usr_cfg.metadata_variable) 172*800a58d9SAndroid Build Coastguard Worker 173*800a58d9SAndroid Build Coastguard Worker self.device_resolution_map = dict( 174*800a58d9SAndroid Build Coastguard Worker internal_cfg.device_resolution_map.items()) 175*800a58d9SAndroid Build Coastguard Worker self.device_default_orientation_map = dict( 176*800a58d9SAndroid Build Coastguard Worker internal_cfg.device_default_orientation_map.items()) 177*800a58d9SAndroid Build Coastguard Worker self.no_project_access_msg_map = dict( 178*800a58d9SAndroid Build Coastguard Worker internal_cfg.no_project_access_msg_map.items()) 179*800a58d9SAndroid Build Coastguard Worker self.min_machine_size = internal_cfg.min_machine_size 180*800a58d9SAndroid Build Coastguard Worker self.disk_image_name = internal_cfg.disk_image_name 181*800a58d9SAndroid Build Coastguard Worker self.disk_image_mime_type = internal_cfg.disk_image_mime_type 182*800a58d9SAndroid Build Coastguard Worker self.disk_image_extension = internal_cfg.disk_image_extension 183*800a58d9SAndroid Build Coastguard Worker self.disk_raw_image_name = internal_cfg.disk_raw_image_name 184*800a58d9SAndroid Build Coastguard Worker self.disk_raw_image_extension = internal_cfg.disk_raw_image_extension 185*800a58d9SAndroid Build Coastguard Worker self.valid_branch_and_min_build_id = dict( 186*800a58d9SAndroid Build Coastguard Worker internal_cfg.valid_branch_and_min_build_id.items()) 187*800a58d9SAndroid Build Coastguard Worker self.precreated_data_image_map = dict( 188*800a58d9SAndroid Build Coastguard Worker internal_cfg.precreated_data_image.items()) 189*800a58d9SAndroid Build Coastguard Worker self.extra_data_disk_size_gb = ( 190*800a58d9SAndroid Build Coastguard Worker usr_cfg.extra_data_disk_size_gb or 191*800a58d9SAndroid Build Coastguard Worker internal_cfg.default_usr_cfg.extra_data_disk_size_gb) 192*800a58d9SAndroid Build Coastguard Worker if self.extra_data_disk_size_gb > 0: 193*800a58d9SAndroid Build Coastguard Worker if "cfg_sta_persistent_data_device" not in usr_cfg.metadata_variable: 194*800a58d9SAndroid Build Coastguard Worker # If user did not set it explicity, use default. 195*800a58d9SAndroid Build Coastguard Worker self.metadata_variable["cfg_sta_persistent_data_device"] = ( 196*800a58d9SAndroid Build Coastguard Worker internal_cfg.default_extra_data_disk_device) 197*800a58d9SAndroid Build Coastguard Worker if "cfg_sta_ephemeral_data_size_mb" in usr_cfg.metadata_variable: 198*800a58d9SAndroid Build Coastguard Worker raise errors.ConfigError( 199*800a58d9SAndroid Build Coastguard Worker "The following settings can't be set at the same time: " 200*800a58d9SAndroid Build Coastguard Worker "extra_data_disk_size_gb and" 201*800a58d9SAndroid Build Coastguard Worker "metadata variable cfg_sta_ephemeral_data_size_mb.") 202*800a58d9SAndroid Build Coastguard Worker if "cfg_sta_ephemeral_data_size_mb" in self.metadata_variable: 203*800a58d9SAndroid Build Coastguard Worker del self.metadata_variable["cfg_sta_ephemeral_data_size_mb"] 204*800a58d9SAndroid Build Coastguard Worker 205*800a58d9SAndroid Build Coastguard Worker # Additional scopes to be passed to the created instance 206*800a58d9SAndroid Build Coastguard Worker self.extra_scopes = usr_cfg.extra_scopes 207*800a58d9SAndroid Build Coastguard Worker 208*800a58d9SAndroid Build Coastguard Worker # Fields that can be overriden by args 209*800a58d9SAndroid Build Coastguard Worker self.orientation = usr_cfg.orientation 210*800a58d9SAndroid Build Coastguard Worker self.resolution = usr_cfg.resolution 211*800a58d9SAndroid Build Coastguard Worker 212*800a58d9SAndroid Build Coastguard Worker self.stable_host_image_family = usr_cfg.stable_host_image_family 213*800a58d9SAndroid Build Coastguard Worker self.stable_host_image_name = ( 214*800a58d9SAndroid Build Coastguard Worker usr_cfg.stable_host_image_name or 215*800a58d9SAndroid Build Coastguard Worker internal_cfg.default_usr_cfg.stable_host_image_name) 216*800a58d9SAndroid Build Coastguard Worker self.stable_host_image_project = ( 217*800a58d9SAndroid Build Coastguard Worker usr_cfg.stable_host_image_project or 218*800a58d9SAndroid Build Coastguard Worker internal_cfg.default_usr_cfg.stable_host_image_project) 219*800a58d9SAndroid Build Coastguard Worker self.kernel_build_target = internal_cfg.kernel_build_target 220*800a58d9SAndroid Build Coastguard Worker 221*800a58d9SAndroid Build Coastguard Worker self.emulator_build_target = internal_cfg.emulator_build_target 222*800a58d9SAndroid Build Coastguard Worker self.stable_goldfish_host_image_name = ( 223*800a58d9SAndroid Build Coastguard Worker usr_cfg.stable_goldfish_host_image_name or 224*800a58d9SAndroid Build Coastguard Worker internal_cfg.default_usr_cfg.stable_goldfish_host_image_name) 225*800a58d9SAndroid Build Coastguard Worker self.stable_goldfish_host_image_project = ( 226*800a58d9SAndroid Build Coastguard Worker usr_cfg.stable_goldfish_host_image_project or 227*800a58d9SAndroid Build Coastguard Worker internal_cfg.default_usr_cfg.stable_goldfish_host_image_project) 228*800a58d9SAndroid Build Coastguard Worker 229*800a58d9SAndroid Build Coastguard Worker self.stable_cheeps_host_image_name = ( 230*800a58d9SAndroid Build Coastguard Worker usr_cfg.stable_cheeps_host_image_name or 231*800a58d9SAndroid Build Coastguard Worker internal_cfg.default_usr_cfg.stable_cheeps_host_image_name) 232*800a58d9SAndroid Build Coastguard Worker self.stable_cheeps_host_image_project = ( 233*800a58d9SAndroid Build Coastguard Worker usr_cfg.stable_cheeps_host_image_project or 234*800a58d9SAndroid Build Coastguard Worker internal_cfg.default_usr_cfg.stable_cheeps_host_image_project) 235*800a58d9SAndroid Build Coastguard Worker self.betty_image = usr_cfg.betty_image 236*800a58d9SAndroid Build Coastguard Worker 237*800a58d9SAndroid Build Coastguard Worker self.extra_args_ssh_tunnel = usr_cfg.extra_args_ssh_tunnel 238*800a58d9SAndroid Build Coastguard Worker 239*800a58d9SAndroid Build Coastguard Worker self.common_hw_property_map = internal_cfg.common_hw_property_map 240*800a58d9SAndroid Build Coastguard Worker self.hw_property = usr_cfg.hw_property 241*800a58d9SAndroid Build Coastguard Worker 242*800a58d9SAndroid Build Coastguard Worker self.launch_args = usr_cfg.launch_args 243*800a58d9SAndroid Build Coastguard Worker self.oxygen_client = usr_cfg.oxygen_client 244*800a58d9SAndroid Build Coastguard Worker self.oxygen_lease_args = usr_cfg.oxygen_lease_args 245*800a58d9SAndroid Build Coastguard Worker self.connect_hostname = usr_cfg.connect_hostname 246*800a58d9SAndroid Build Coastguard Worker self.instance_name_pattern = ( 247*800a58d9SAndroid Build Coastguard Worker usr_cfg.instance_name_pattern or 248*800a58d9SAndroid Build Coastguard Worker internal_cfg.default_usr_cfg.instance_name_pattern) 249*800a58d9SAndroid Build Coastguard Worker self.fetch_cvd_version = ( 250*800a58d9SAndroid Build Coastguard Worker usr_cfg.fetch_cvd_version or 251*800a58d9SAndroid Build Coastguard Worker internal_cfg.default_usr_cfg.fetch_cvd_version) 252*800a58d9SAndroid Build Coastguard Worker if usr_cfg.HasField("enable_multi_stage") is not None: 253*800a58d9SAndroid Build Coastguard Worker self.enable_multi_stage = usr_cfg.enable_multi_stage 254*800a58d9SAndroid Build Coastguard Worker elif internal_cfg.default_usr_cfg.HasField("enable_multi_stage"): 255*800a58d9SAndroid Build Coastguard Worker self.enable_multi_stage = internal_cfg.default_usr_cfg.enable_multi_stage 256*800a58d9SAndroid Build Coastguard Worker else: 257*800a58d9SAndroid Build Coastguard Worker self.enable_multi_stage = False 258*800a58d9SAndroid Build Coastguard Worker self.disk_type = usr_cfg.disk_type 259*800a58d9SAndroid Build Coastguard Worker self.use_cvdr = usr_cfg.use_cvdr 260*800a58d9SAndroid Build Coastguard Worker self.use_legacy_acloud = usr_cfg.use_legacy_acloud 261*800a58d9SAndroid Build Coastguard Worker 262*800a58d9SAndroid Build Coastguard Worker # Verify validity of configurations. 263*800a58d9SAndroid Build Coastguard Worker self.Verify() 264*800a58d9SAndroid Build Coastguard Worker 265*800a58d9SAndroid Build Coastguard Worker # pylint: disable=too-many-branches 266*800a58d9SAndroid Build Coastguard Worker def OverrideWithArgs(self, parsed_args): 267*800a58d9SAndroid Build Coastguard Worker """Override configuration values with args passed in from cmd line. 268*800a58d9SAndroid Build Coastguard Worker 269*800a58d9SAndroid Build Coastguard Worker Args: 270*800a58d9SAndroid Build Coastguard Worker parsed_args: Args parsed from command line. 271*800a58d9SAndroid Build Coastguard Worker """ 272*800a58d9SAndroid Build Coastguard Worker if parsed_args.which == create_args.CMD_CREATE and parsed_args.spec: 273*800a58d9SAndroid Build Coastguard Worker if not self.resolution: 274*800a58d9SAndroid Build Coastguard Worker self.resolution = self.device_resolution_map.get( 275*800a58d9SAndroid Build Coastguard Worker parsed_args.spec, "") 276*800a58d9SAndroid Build Coastguard Worker if not self.orientation: 277*800a58d9SAndroid Build Coastguard Worker self.orientation = self.device_default_orientation_map.get( 278*800a58d9SAndroid Build Coastguard Worker parsed_args.spec, "") 279*800a58d9SAndroid Build Coastguard Worker if parsed_args.email: 280*800a58d9SAndroid Build Coastguard Worker self.service_account_name = parsed_args.email 281*800a58d9SAndroid Build Coastguard Worker if parsed_args.service_account_json_private_key_path: 282*800a58d9SAndroid Build Coastguard Worker self.service_account_json_private_key_path = ( 283*800a58d9SAndroid Build Coastguard Worker parsed_args.service_account_json_private_key_path) 284*800a58d9SAndroid Build Coastguard Worker if parsed_args.which == "create_gf" and parsed_args.base_image: 285*800a58d9SAndroid Build Coastguard Worker self.stable_goldfish_host_image_name = parsed_args.base_image 286*800a58d9SAndroid Build Coastguard Worker if parsed_args.which in [create_args.CMD_CREATE, "create_cf"]: 287*800a58d9SAndroid Build Coastguard Worker if parsed_args.network: 288*800a58d9SAndroid Build Coastguard Worker self.network = parsed_args.network 289*800a58d9SAndroid Build Coastguard Worker if parsed_args.multi_stage_launch is not None: 290*800a58d9SAndroid Build Coastguard Worker self.enable_multi_stage = parsed_args.multi_stage_launch 291*800a58d9SAndroid Build Coastguard Worker if parsed_args.which in [create_args.CMD_CREATE, "create_cf", "create_gf"]: 292*800a58d9SAndroid Build Coastguard Worker if parsed_args.zone: 293*800a58d9SAndroid Build Coastguard Worker self.zone = parsed_args.zone 294*800a58d9SAndroid Build Coastguard Worker if (parsed_args.which == "create_cf" and 295*800a58d9SAndroid Build Coastguard Worker parsed_args.num_avds_per_instance > 1): 296*800a58d9SAndroid Build Coastguard Worker scrubbed_args = [arg for arg in self.launch_args.split() 297*800a58d9SAndroid Build Coastguard Worker if _NUM_INSTANCES_ARG not in arg] 298*800a58d9SAndroid Build Coastguard Worker scrubbed_args.append("%s=%d" % (_NUM_INSTANCES_ARG, 299*800a58d9SAndroid Build Coastguard Worker parsed_args.num_avds_per_instance)) 300*800a58d9SAndroid Build Coastguard Worker 301*800a58d9SAndroid Build Coastguard Worker self.launch_args = " ".join(scrubbed_args) 302*800a58d9SAndroid Build Coastguard Worker 303*800a58d9SAndroid Build Coastguard Worker def GetDefaultHwProperty(self, flavor, instance_type=None): 304*800a58d9SAndroid Build Coastguard Worker """Get default hw configuration values. 305*800a58d9SAndroid Build Coastguard Worker 306*800a58d9SAndroid Build Coastguard Worker HwProperty will be overrided according to the change of flavor and 307*800a58d9SAndroid Build Coastguard Worker instance type. The format of key is flavor or instance_type-flavor. 308*800a58d9SAndroid Build Coastguard Worker e.g: 'phone' or 'local-phone'. 309*800a58d9SAndroid Build Coastguard Worker If the giving key is not found, get hw configuration with a default 310*800a58d9SAndroid Build Coastguard Worker phone property. 311*800a58d9SAndroid Build Coastguard Worker 312*800a58d9SAndroid Build Coastguard Worker Args: 313*800a58d9SAndroid Build Coastguard Worker flavor: String of flavor name. 314*800a58d9SAndroid Build Coastguard Worker instance_type: String of instance type. 315*800a58d9SAndroid Build Coastguard Worker 316*800a58d9SAndroid Build Coastguard Worker Returns: 317*800a58d9SAndroid Build Coastguard Worker String of device hardware property, it would be like 318*800a58d9SAndroid Build Coastguard Worker "cpu:4,resolution:720x1280,dpi:320,memory:4g". 319*800a58d9SAndroid Build Coastguard Worker """ 320*800a58d9SAndroid Build Coastguard Worker hw_key = ("%s-%s" % (instance_type, flavor) 321*800a58d9SAndroid Build Coastguard Worker if instance_type == constants.INSTANCE_TYPE_LOCAL else flavor) 322*800a58d9SAndroid Build Coastguard Worker return self.common_hw_property_map.get(hw_key, _DEFAULT_HW_PROPERTY) 323*800a58d9SAndroid Build Coastguard Worker 324*800a58d9SAndroid Build Coastguard Worker def Verify(self): 325*800a58d9SAndroid Build Coastguard Worker """Verify configuration fields.""" 326*800a58d9SAndroid Build Coastguard Worker missing = self.GetMissingFields(self.REQUIRED_FIELD) 327*800a58d9SAndroid Build Coastguard Worker if missing: 328*800a58d9SAndroid Build Coastguard Worker raise errors.ConfigError( 329*800a58d9SAndroid Build Coastguard Worker "Missing required configuration fields: %s" % missing) 330*800a58d9SAndroid Build Coastguard Worker if (self.extra_data_disk_size_gb and self.extra_data_disk_size_gb not in 331*800a58d9SAndroid Build Coastguard Worker self.precreated_data_image_map): 332*800a58d9SAndroid Build Coastguard Worker raise errors.ConfigError( 333*800a58d9SAndroid Build Coastguard Worker "Supported extra_data_disk_size_gb options(gb): %s, " 334*800a58d9SAndroid Build Coastguard Worker "invalid value: %d" % (self.precreated_data_image_map.keys(), 335*800a58d9SAndroid Build Coastguard Worker self.extra_data_disk_size_gb)) 336*800a58d9SAndroid Build Coastguard Worker 337*800a58d9SAndroid Build Coastguard Worker def GetMissingFields(self, fields): 338*800a58d9SAndroid Build Coastguard Worker """Get missing required fields. 339*800a58d9SAndroid Build Coastguard Worker 340*800a58d9SAndroid Build Coastguard Worker Args: 341*800a58d9SAndroid Build Coastguard Worker fields: List of field names. 342*800a58d9SAndroid Build Coastguard Worker 343*800a58d9SAndroid Build Coastguard Worker Returns: 344*800a58d9SAndroid Build Coastguard Worker List of missing field names. 345*800a58d9SAndroid Build Coastguard Worker """ 346*800a58d9SAndroid Build Coastguard Worker return [f for f in fields if not getattr(self, f)] 347*800a58d9SAndroid Build Coastguard Worker 348*800a58d9SAndroid Build Coastguard Worker def SupportRemoteInstance(self): 349*800a58d9SAndroid Build Coastguard Worker """Return True if gcp project is provided in config.""" 350*800a58d9SAndroid Build Coastguard Worker return bool(self.project) 351*800a58d9SAndroid Build Coastguard Worker 352*800a58d9SAndroid Build Coastguard Worker 353*800a58d9SAndroid Build Coastguard Workerclass AcloudConfigManager(): 354*800a58d9SAndroid Build Coastguard Worker """A class that loads configurations.""" 355*800a58d9SAndroid Build Coastguard Worker 356*800a58d9SAndroid Build Coastguard Worker def __init__(self, user_config_path): 357*800a58d9SAndroid Build Coastguard Worker """Initialize with user specified paths to configs. 358*800a58d9SAndroid Build Coastguard Worker 359*800a58d9SAndroid Build Coastguard Worker Args: 360*800a58d9SAndroid Build Coastguard Worker user_config_path: path to the user config. 361*800a58d9SAndroid Build Coastguard Worker """ 362*800a58d9SAndroid Build Coastguard Worker self.user_config_path = user_config_path 363*800a58d9SAndroid Build Coastguard Worker 364*800a58d9SAndroid Build Coastguard Worker def Load(self): 365*800a58d9SAndroid Build Coastguard Worker """Load the configurations. 366*800a58d9SAndroid Build Coastguard Worker 367*800a58d9SAndroid Build Coastguard Worker Load user config with some special design. 368*800a58d9SAndroid Build Coastguard Worker 1. User specified user config: 369*800a58d9SAndroid Build Coastguard Worker a.User config exist: Load config. 370*800a58d9SAndroid Build Coastguard Worker b.User config didn't exist: Raise exception. 371*800a58d9SAndroid Build Coastguard Worker 2. User didn't specify user config, use default config: 372*800a58d9SAndroid Build Coastguard Worker a.Default config exist: Load config. 373*800a58d9SAndroid Build Coastguard Worker b.Default config didn't exist: provide empty usr_cfg. 374*800a58d9SAndroid Build Coastguard Worker 375*800a58d9SAndroid Build Coastguard Worker Raises: 376*800a58d9SAndroid Build Coastguard Worker errors.ConfigError: If config file doesn't exist. 377*800a58d9SAndroid Build Coastguard Worker 378*800a58d9SAndroid Build Coastguard Worker Returns: 379*800a58d9SAndroid Build Coastguard Worker An instance of AcloudConfig. 380*800a58d9SAndroid Build Coastguard Worker """ 381*800a58d9SAndroid Build Coastguard Worker internal_cfg = None 382*800a58d9SAndroid Build Coastguard Worker usr_cfg = None 383*800a58d9SAndroid Build Coastguard Worker try: 384*800a58d9SAndroid Build Coastguard Worker with _OpenTextResource(_INTERNAL_CONFIG_FILE) as cfg_file: 385*800a58d9SAndroid Build Coastguard Worker internal_cfg = self.LoadConfigFromProtocolBuffer( 386*800a58d9SAndroid Build Coastguard Worker cfg_file, internal_config_pb2.InternalConfig) 387*800a58d9SAndroid Build Coastguard Worker except OSError as e: 388*800a58d9SAndroid Build Coastguard Worker raise errors.ConfigError("Could not load config files: %s" % str(e)) 389*800a58d9SAndroid Build Coastguard Worker # Load user config file 390*800a58d9SAndroid Build Coastguard Worker self.user_config_path = GetUserConfigPath(self.user_config_path) 391*800a58d9SAndroid Build Coastguard Worker if os.path.exists(self.user_config_path): 392*800a58d9SAndroid Build Coastguard Worker with open(self.user_config_path, "r") as config_file: 393*800a58d9SAndroid Build Coastguard Worker usr_cfg = self.LoadConfigFromProtocolBuffer( 394*800a58d9SAndroid Build Coastguard Worker config_file, user_config_pb2.UserConfig) 395*800a58d9SAndroid Build Coastguard Worker else: 396*800a58d9SAndroid Build Coastguard Worker if self.user_config_path != GetDefaultConfigFile(): 397*800a58d9SAndroid Build Coastguard Worker raise errors.ConfigError( 398*800a58d9SAndroid Build Coastguard Worker "The config file doesn't exist: %s. For reset config " 399*800a58d9SAndroid Build Coastguard Worker "information: go/acloud-googler-setup#reset-configuration" % 400*800a58d9SAndroid Build Coastguard Worker (self.user_config_path)) 401*800a58d9SAndroid Build Coastguard Worker usr_cfg = user_config_pb2.UserConfig() 402*800a58d9SAndroid Build Coastguard Worker return AcloudConfig(usr_cfg, internal_cfg) 403*800a58d9SAndroid Build Coastguard Worker 404*800a58d9SAndroid Build Coastguard Worker @staticmethod 405*800a58d9SAndroid Build Coastguard Worker def LoadConfigFromProtocolBuffer(config_file, message_type): 406*800a58d9SAndroid Build Coastguard Worker """Load config from a text-based protocol buffer file. 407*800a58d9SAndroid Build Coastguard Worker 408*800a58d9SAndroid Build Coastguard Worker Args: 409*800a58d9SAndroid Build Coastguard Worker config_file: A python File object. 410*800a58d9SAndroid Build Coastguard Worker message_type: A proto message class. 411*800a58d9SAndroid Build Coastguard Worker 412*800a58d9SAndroid Build Coastguard Worker Returns: 413*800a58d9SAndroid Build Coastguard Worker An instance of type "message_type" populated with data 414*800a58d9SAndroid Build Coastguard Worker from the file. 415*800a58d9SAndroid Build Coastguard Worker """ 416*800a58d9SAndroid Build Coastguard Worker try: 417*800a58d9SAndroid Build Coastguard Worker config = message_type() 418*800a58d9SAndroid Build Coastguard Worker text_format.Merge(config_file.read(), config) 419*800a58d9SAndroid Build Coastguard Worker return config 420*800a58d9SAndroid Build Coastguard Worker except text_format.ParseError as e: 421*800a58d9SAndroid Build Coastguard Worker raise errors.ConfigError("Could not parse config: %s" % str(e)) 422