1# Copyright 2020 - 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"""cvd_runtime_config class.""" 15 16import json 17import os 18import re 19 20from acloud import errors 21 22_CFG_KEY_ADB_CONNECTOR_BINARY = "adb_connector_binary" 23_CFG_KEY_X_RES = "x_res" 24_CFG_KEY_Y_RES = "y_res" 25_CFG_KEY_DPI = "dpi" 26_CFG_KEY_VIRTUAL_DISK_PATHS = "virtual_disk_paths" 27_CFG_KEY_INSTANCES = "instances" 28_CFG_KEY_ADB_IP_PORT = "adb_ip_and_port" 29_CFG_KEY_INSTANCE_DIR = "instance_dir" 30_CFG_KEY_VNC_PORT = "vnc_server_port" 31_CFG_KEY_ADB_PORT = "host_port" 32# TODO(148648620): Check instance_home_[id] for backward compatible. 33_RE_LOCAL_INSTANCE_ID = re.compile(r".+(?:local-instance-|instance_home_)" 34 r"(?P<ins_id>\d+).+") 35 36 37def _GetIdFromInstanceDirStr(instance_dir): 38 """Look for instance id from the path of instance dir. 39 40 Args: 41 instance_dir: String, path of instance_dir. 42 43 Returns: 44 String of instance id. 45 """ 46 match = _RE_LOCAL_INSTANCE_ID.match(instance_dir) 47 if match: 48 return match.group("ins_id") 49 else: 50 # To support the device which is not created by acloud. 51 if os.path.expanduser("~") in instance_dir: 52 return "1" 53 54 return None 55 56 57class CvdRuntimeConfig(object): 58 """The class that hold the information from cuttlefish_config.json. 59 60 The example of cuttlefish_config.json 61 { 62 "memory_mb" : 4096, 63 "cpus" : 2, 64 "dpi" : 320, 65 "virtual_disk_paths" : 66 [ 67 "/path-to-image" 68 ], 69 "adb_ip_and_port" : "127.0.0.1:6520", 70 "instance_dir" : "/path-to-instance-dir", 71 } 72 73 If we launched multiple local instances, the config will be as below: 74 { 75 "memory_mb" : 4096, 76 "cpus" : 2, 77 "dpi" : 320, 78 "instances" : 79 { 80 "1" : 81 { 82 "adb_ip_and_port" : "127.0.0.1:6520", 83 "instance_dir" : "/path-to-instance-dir", 84 "virtual_disk_paths" : 85 [ 86 "/path-to-image" 87 ], 88 } 89 } 90 } 91 92 """ 93 94 def __init__(self, config_path): 95 self._config_path = config_path 96 self._config_dict = self._GetCuttlefishRuntimeConfig(config_path) 97 self._instance_id = _GetIdFromInstanceDirStr(self._config_path) 98 self._x_res = self._config_dict.get(_CFG_KEY_X_RES) 99 self._y_res = self._config_dict.get(_CFG_KEY_Y_RES) 100 self._dpi = self._config_dict.get(_CFG_KEY_DPI) 101 adb_connector = self._config_dict.get(_CFG_KEY_ADB_CONNECTOR_BINARY) 102 self._cvd_tools_path = (os.path.dirname(adb_connector) 103 if adb_connector else None) 104 105 # Below properties will be collected inside of instance id node if there 106 # are more than one instance. 107 self._instance_dir = self._config_dict.get(_CFG_KEY_INSTANCE_DIR) 108 self._vnc_port = self._config_dict.get(_CFG_KEY_VNC_PORT) 109 self._adb_port = self._config_dict.get(_CFG_KEY_ADB_PORT) 110 self._adb_ip_port = self._config_dict.get(_CFG_KEY_ADB_IP_PORT) 111 self._virtual_disk_paths = self._config_dict.get( 112 _CFG_KEY_VIRTUAL_DISK_PATHS) 113 if not self._instance_dir: 114 ins_cfg = self._config_dict.get(_CFG_KEY_INSTANCES) 115 ins_dict = ins_cfg.get(self._instance_id) 116 if not ins_dict: 117 raise errors.ConfigError("instances[%s] property does not exist" 118 " in: %s" % 119 (self._instance_id, config_path)) 120 self._instance_dir = ins_dict.get(_CFG_KEY_INSTANCE_DIR) 121 self._vnc_port = ins_dict.get(_CFG_KEY_VNC_PORT) 122 self._adb_port = ins_dict.get(_CFG_KEY_ADB_PORT) 123 self._adb_ip_port = ins_dict.get(_CFG_KEY_ADB_IP_PORT) 124 self._virtual_disk_paths = ins_dict.get(_CFG_KEY_VIRTUAL_DISK_PATHS) 125 126 @staticmethod 127 def _GetCuttlefishRuntimeConfig(runtime_cf_config_path): 128 """Get and parse cuttlefish_config.json. 129 130 Args: 131 runtime_cf_config_path: String, path of the cvd runtime config. 132 133 Returns: 134 A dictionary that parsed from cuttlefish runtime config. 135 136 Raises: 137 errors.ConfigError: if file not found or config load failed. 138 """ 139 if not os.path.exists(runtime_cf_config_path): 140 raise errors.ConfigError( 141 "file does not exist: %s" % runtime_cf_config_path) 142 with open(runtime_cf_config_path, "r") as cf_config: 143 return json.load(cf_config) 144 145 @property 146 def cvd_tools_path(self): 147 """Return string of the path to the cvd tools.""" 148 return self._cvd_tools_path 149 150 @property 151 def x_res(self): 152 """Return x_res.""" 153 return self._x_res 154 155 @property 156 def y_res(self): 157 """Return y_res.""" 158 return self._y_res 159 160 @property 161 def dpi(self): 162 """Return dpi.""" 163 return self._dpi 164 165 @property 166 def adb_ip_port(self): 167 """Return adb_ip_port.""" 168 return self._adb_ip_port 169 170 @property 171 def instance_dir(self): 172 """Return instance_dir.""" 173 return self._instance_dir 174 175 @property 176 def vnc_port(self): 177 """Return vnc_port.""" 178 return self._vnc_port 179 180 @property 181 def adb_port(self): 182 """Return adb_port.""" 183 return self._adb_port 184 185 @property 186 def config_path(self): 187 """Return config_path.""" 188 return self._config_path 189 190 @property 191 def virtual_disk_paths(self): 192 """Return virtual_disk_paths""" 193 return self._virtual_disk_paths 194 195 @property 196 def instance_id(self): 197 """Return _instance_id""" 198 return self._instance_id 199