xref: /aosp_15_r20/tools/acloud/internal/lib/cvd_runtime_config.py (revision 800a58d989c669b8eb8a71d8df53b1ba3d411444)
1*800a58d9SAndroid Build Coastguard Worker# Copyright 2020 - The Android Open Source Project
2*800a58d9SAndroid Build Coastguard Worker#
3*800a58d9SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*800a58d9SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*800a58d9SAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*800a58d9SAndroid Build Coastguard Worker#
7*800a58d9SAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*800a58d9SAndroid Build Coastguard Worker#
9*800a58d9SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*800a58d9SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*800a58d9SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*800a58d9SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*800a58d9SAndroid Build Coastguard Worker# limitations under the License.
14*800a58d9SAndroid Build Coastguard Worker"""cvd_runtime_config class."""
15*800a58d9SAndroid Build Coastguard Worker
16*800a58d9SAndroid Build Coastguard Workerimport json
17*800a58d9SAndroid Build Coastguard Workerimport os
18*800a58d9SAndroid Build Coastguard Workerimport re
19*800a58d9SAndroid Build Coastguard Worker
20*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors
21*800a58d9SAndroid Build Coastguard Worker
22*800a58d9SAndroid Build Coastguard Worker_CFG_KEY_CROSVM_BINARY = "crosvm_binary"
23*800a58d9SAndroid Build Coastguard Worker_CFG_KEY_DISPLAY_CONFIGS = "display_configs"
24*800a58d9SAndroid Build Coastguard Worker_CFG_KEY_VIRTUAL_DISK_PATHS = "virtual_disk_paths"
25*800a58d9SAndroid Build Coastguard Worker_CFG_KEY_INSTANCES = "instances"
26*800a58d9SAndroid Build Coastguard Worker_CFG_KEY_ADB_IP_PORT = "adb_ip_and_port"
27*800a58d9SAndroid Build Coastguard Worker_CFG_KEY_INSTANCE_DIR = "instance_dir"
28*800a58d9SAndroid Build Coastguard Worker_CFG_KEY_ROOT_DIR = "root_dir"
29*800a58d9SAndroid Build Coastguard Worker_CFG_KEY_VNC_PORT = "vnc_server_port"
30*800a58d9SAndroid Build Coastguard Worker# The adb port field name changes from "host_port" to "adb_host_port".
31*800a58d9SAndroid Build Coastguard Worker_CFG_KEY_ADB_PORT = "host_port"
32*800a58d9SAndroid Build Coastguard Worker_CFG_KEY_ADB_HOST_PORT = "adb_host_port"
33*800a58d9SAndroid Build Coastguard Worker_CFG_KEY_ENABLE_WEBRTC = "enable_webrtc"
34*800a58d9SAndroid Build Coastguard Worker# TODO(148648620): Check instance_home_[id] for backward compatible.
35*800a58d9SAndroid Build Coastguard Worker_RE_LOCAL_INSTANCE_ID = re.compile(r".+(?:local-instance-|instance_home_)"
36*800a58d9SAndroid Build Coastguard Worker                                   r"(?P<ins_id>\d+).+")
37*800a58d9SAndroid Build Coastguard Worker
38*800a58d9SAndroid Build Coastguard Worker
39*800a58d9SAndroid Build Coastguard Workerdef _GetIdFromInstanceDirStr(instance_dir, config_dict):
40*800a58d9SAndroid Build Coastguard Worker    """Look for instance id from the path of instance dir.
41*800a58d9SAndroid Build Coastguard Worker
42*800a58d9SAndroid Build Coastguard Worker    Args:
43*800a58d9SAndroid Build Coastguard Worker        instance_dir: String, path of instance_dir.
44*800a58d9SAndroid Build Coastguard Worker
45*800a58d9SAndroid Build Coastguard Worker    Returns:
46*800a58d9SAndroid Build Coastguard Worker        String of instance id.
47*800a58d9SAndroid Build Coastguard Worker    """
48*800a58d9SAndroid Build Coastguard Worker    match = _RE_LOCAL_INSTANCE_ID.match(instance_dir)
49*800a58d9SAndroid Build Coastguard Worker    if match:
50*800a58d9SAndroid Build Coastguard Worker        return match.group("ins_id")
51*800a58d9SAndroid Build Coastguard Worker
52*800a58d9SAndroid Build Coastguard Worker    # To support the device which is not created by acloud.
53*800a58d9SAndroid Build Coastguard Worker    if os.path.expanduser("~") in instance_dir:
54*800a58d9SAndroid Build Coastguard Worker        if config_dict:
55*800a58d9SAndroid Build Coastguard Worker            instances = config_dict.get(_CFG_KEY_INSTANCES)
56*800a58d9SAndroid Build Coastguard Worker            if instances:
57*800a58d9SAndroid Build Coastguard Worker                return min(instances.keys())
58*800a58d9SAndroid Build Coastguard Worker            else:
59*800a58d9SAndroid Build Coastguard Worker                # Old runtime config doesn't have "instances" information.
60*800a58d9SAndroid Build Coastguard Worker                return "1"
61*800a58d9SAndroid Build Coastguard Worker        else:
62*800a58d9SAndroid Build Coastguard Worker            return "1"
63*800a58d9SAndroid Build Coastguard Worker
64*800a58d9SAndroid Build Coastguard Worker    return None
65*800a58d9SAndroid Build Coastguard Worker
66*800a58d9SAndroid Build Coastguard Worker
67*800a58d9SAndroid Build Coastguard Workerclass CvdRuntimeConfig():
68*800a58d9SAndroid Build Coastguard Worker    """The class that hold the information from cuttlefish_config.json.
69*800a58d9SAndroid Build Coastguard Worker
70*800a58d9SAndroid Build Coastguard Worker    The example of cuttlefish_config.json
71*800a58d9SAndroid Build Coastguard Worker    {
72*800a58d9SAndroid Build Coastguard Worker    "memory_mb" : 4096,
73*800a58d9SAndroid Build Coastguard Worker    "cpus" : 2,
74*800a58d9SAndroid Build Coastguard Worker    "display_configs" :
75*800a58d9SAndroid Build Coastguard Worker    [
76*800a58d9SAndroid Build Coastguard Worker        {
77*800a58d9SAndroid Build Coastguard Worker            "dpi" : 160,
78*800a58d9SAndroid Build Coastguard Worker            "x_res" : 1280,
79*800a58d9SAndroid Build Coastguard Worker            "y_res" : 700
80*800a58d9SAndroid Build Coastguard Worker        }
81*800a58d9SAndroid Build Coastguard Worker    ],
82*800a58d9SAndroid Build Coastguard Worker    "dpi" : 320,
83*800a58d9SAndroid Build Coastguard Worker    "virtual_disk_paths" :
84*800a58d9SAndroid Build Coastguard Worker        [
85*800a58d9SAndroid Build Coastguard Worker            "/path-to-image"
86*800a58d9SAndroid Build Coastguard Worker        ],
87*800a58d9SAndroid Build Coastguard Worker    "adb_ip_and_port" : "0.0.0.0:6520",
88*800a58d9SAndroid Build Coastguard Worker    "instance_dir" : "/path-to-instance-dir",
89*800a58d9SAndroid Build Coastguard Worker    }
90*800a58d9SAndroid Build Coastguard Worker
91*800a58d9SAndroid Build Coastguard Worker    If we launched multiple local instances, the config will be as below:
92*800a58d9SAndroid Build Coastguard Worker    {
93*800a58d9SAndroid Build Coastguard Worker    "memory_mb" : 4096,
94*800a58d9SAndroid Build Coastguard Worker    "cpus" : 2,
95*800a58d9SAndroid Build Coastguard Worker    "dpi" : 320,
96*800a58d9SAndroid Build Coastguard Worker    "instances" :
97*800a58d9SAndroid Build Coastguard Worker        {
98*800a58d9SAndroid Build Coastguard Worker            "1" :
99*800a58d9SAndroid Build Coastguard Worker            {
100*800a58d9SAndroid Build Coastguard Worker                "adb_ip_and_port" : "0.0.0.0:6520",
101*800a58d9SAndroid Build Coastguard Worker                "instance_dir" : "/path-to-instance-dir",
102*800a58d9SAndroid Build Coastguard Worker                "webrtc_device_id" : "cvd-1",
103*800a58d9SAndroid Build Coastguard Worker                "virtual_disk_paths" :
104*800a58d9SAndroid Build Coastguard Worker                [
105*800a58d9SAndroid Build Coastguard Worker                    "/path-to-image"
106*800a58d9SAndroid Build Coastguard Worker                ],
107*800a58d9SAndroid Build Coastguard Worker            }
108*800a58d9SAndroid Build Coastguard Worker        }
109*800a58d9SAndroid Build Coastguard Worker    }
110*800a58d9SAndroid Build Coastguard Worker
111*800a58d9SAndroid Build Coastguard Worker    If the avd enable the webrtc, the config will be as below:
112*800a58d9SAndroid Build Coastguard Worker    {
113*800a58d9SAndroid Build Coastguard Worker    "enable_webrtc" : true,
114*800a58d9SAndroid Build Coastguard Worker    "vnc_server_binary" : "/home/vsoc-01/bin/vnc_server",
115*800a58d9SAndroid Build Coastguard Worker    "webrtc_assets_dir" : "/home/vsoc-01/usr/share/webrtc/assets",
116*800a58d9SAndroid Build Coastguard Worker    "webrtc_binary" : "/home/vsoc-01/bin/webRTC",
117*800a58d9SAndroid Build Coastguard Worker    "webrtc_certs_dir" : "/home/vsoc-01/usr/share/webrtc/certs",
118*800a58d9SAndroid Build Coastguard Worker    "webrtc_public_ip" : "0.0.0.0",
119*800a58d9SAndroid Build Coastguard Worker    }
120*800a58d9SAndroid Build Coastguard Worker
121*800a58d9SAndroid Build Coastguard Worker    """
122*800a58d9SAndroid Build Coastguard Worker
123*800a58d9SAndroid Build Coastguard Worker    def __init__(self, config_path=None, raw_data=None):
124*800a58d9SAndroid Build Coastguard Worker        if not config_path and not raw_data:
125*800a58d9SAndroid Build Coastguard Worker            raise errors.ConfigError("No cuttlefish config found!")
126*800a58d9SAndroid Build Coastguard Worker        self._config_path = config_path
127*800a58d9SAndroid Build Coastguard Worker        self._config_dict = self._GetCuttlefishRuntimeConfig(config_path,
128*800a58d9SAndroid Build Coastguard Worker                                                             raw_data)
129*800a58d9SAndroid Build Coastguard Worker        self._instance_id = "1" if raw_data else _GetIdFromInstanceDirStr(
130*800a58d9SAndroid Build Coastguard Worker            config_path, self._config_dict)
131*800a58d9SAndroid Build Coastguard Worker        self._instances = self._config_dict.get(_CFG_KEY_INSTANCES)
132*800a58d9SAndroid Build Coastguard Worker        # Old runtime config doesn't have "instances" information.
133*800a58d9SAndroid Build Coastguard Worker        self._instance_ids = list(self._instances.keys()) if self._instances else ["1"]
134*800a58d9SAndroid Build Coastguard Worker        self._display_configs = self._config_dict.get(_CFG_KEY_DISPLAY_CONFIGS, {})
135*800a58d9SAndroid Build Coastguard Worker        self._root_dir = self._config_dict.get(_CFG_KEY_ROOT_DIR)
136*800a58d9SAndroid Build Coastguard Worker        crosvm_bin = self._config_dict.get(_CFG_KEY_CROSVM_BINARY)
137*800a58d9SAndroid Build Coastguard Worker        self._cvd_tools_path = (os.path.dirname(crosvm_bin)
138*800a58d9SAndroid Build Coastguard Worker                                if crosvm_bin else None)
139*800a58d9SAndroid Build Coastguard Worker
140*800a58d9SAndroid Build Coastguard Worker        # Below properties will be collected inside of instance id node if there
141*800a58d9SAndroid Build Coastguard Worker        # are more than one instance.
142*800a58d9SAndroid Build Coastguard Worker        self._instance_dir = self._config_dict.get(_CFG_KEY_INSTANCE_DIR)
143*800a58d9SAndroid Build Coastguard Worker        self._vnc_port = self._config_dict.get(_CFG_KEY_VNC_PORT)
144*800a58d9SAndroid Build Coastguard Worker        self._adb_port = (self._config_dict.get(_CFG_KEY_ADB_PORT) or
145*800a58d9SAndroid Build Coastguard Worker                          self._config_dict.get(_CFG_KEY_ADB_HOST_PORT))
146*800a58d9SAndroid Build Coastguard Worker        self._adb_ip_port = self._config_dict.get(_CFG_KEY_ADB_IP_PORT)
147*800a58d9SAndroid Build Coastguard Worker        self._virtual_disk_paths = self._config_dict.get(
148*800a58d9SAndroid Build Coastguard Worker            _CFG_KEY_VIRTUAL_DISK_PATHS)
149*800a58d9SAndroid Build Coastguard Worker        self._enable_webrtc = self._config_dict.get(_CFG_KEY_ENABLE_WEBRTC)
150*800a58d9SAndroid Build Coastguard Worker        if not self._instance_dir:
151*800a58d9SAndroid Build Coastguard Worker            ins_dict = self._instances.get(self._instance_id)
152*800a58d9SAndroid Build Coastguard Worker            if not ins_dict:
153*800a58d9SAndroid Build Coastguard Worker                raise errors.ConfigError("instances[%s] property does not exist"
154*800a58d9SAndroid Build Coastguard Worker                                         " in: %s" %
155*800a58d9SAndroid Build Coastguard Worker                                         (self._instance_id, config_path))
156*800a58d9SAndroid Build Coastguard Worker            self._instance_dir = ins_dict.get(_CFG_KEY_INSTANCE_DIR)
157*800a58d9SAndroid Build Coastguard Worker            self._vnc_port = ins_dict.get(_CFG_KEY_VNC_PORT)
158*800a58d9SAndroid Build Coastguard Worker            self._adb_port = (ins_dict.get(_CFG_KEY_ADB_PORT) or
159*800a58d9SAndroid Build Coastguard Worker                              ins_dict.get(_CFG_KEY_ADB_HOST_PORT))
160*800a58d9SAndroid Build Coastguard Worker            self._adb_ip_port = ins_dict.get(_CFG_KEY_ADB_IP_PORT)
161*800a58d9SAndroid Build Coastguard Worker            self._virtual_disk_paths = ins_dict.get(_CFG_KEY_VIRTUAL_DISK_PATHS)
162*800a58d9SAndroid Build Coastguard Worker            if not self._cvd_tools_path:
163*800a58d9SAndroid Build Coastguard Worker                self._cvd_tools_path = os.path.dirname(
164*800a58d9SAndroid Build Coastguard Worker                    ins_dict.get(_CFG_KEY_CROSVM_BINARY))
165*800a58d9SAndroid Build Coastguard Worker
166*800a58d9SAndroid Build Coastguard Worker    @staticmethod
167*800a58d9SAndroid Build Coastguard Worker    def _GetCuttlefishRuntimeConfig(runtime_cf_config_path, raw_data=None):
168*800a58d9SAndroid Build Coastguard Worker        """Get and parse cuttlefish_config.json.
169*800a58d9SAndroid Build Coastguard Worker
170*800a58d9SAndroid Build Coastguard Worker        Args:
171*800a58d9SAndroid Build Coastguard Worker            runtime_cf_config_path: String, path of the cvd runtime config.
172*800a58d9SAndroid Build Coastguard Worker            raw_data: String, data of the cvd runtime config.
173*800a58d9SAndroid Build Coastguard Worker
174*800a58d9SAndroid Build Coastguard Worker        Returns:
175*800a58d9SAndroid Build Coastguard Worker            A dictionary that parsed from cuttlefish runtime config.
176*800a58d9SAndroid Build Coastguard Worker
177*800a58d9SAndroid Build Coastguard Worker        Raises:
178*800a58d9SAndroid Build Coastguard Worker            errors.ConfigError: if file not found or config load failed.
179*800a58d9SAndroid Build Coastguard Worker        """
180*800a58d9SAndroid Build Coastguard Worker        if raw_data:
181*800a58d9SAndroid Build Coastguard Worker            # if remote instance couldn't fetch the config will return message such as
182*800a58d9SAndroid Build Coastguard Worker            # 'cat: .../cuttlefish_config.json: No such file or directory'.
183*800a58d9SAndroid Build Coastguard Worker            # Add this condition to prevent from JSONDecodeError.
184*800a58d9SAndroid Build Coastguard Worker            try:
185*800a58d9SAndroid Build Coastguard Worker                return json.loads(raw_data)
186*800a58d9SAndroid Build Coastguard Worker            except ValueError as e:
187*800a58d9SAndroid Build Coastguard Worker                raise errors.ConfigError(
188*800a58d9SAndroid Build Coastguard Worker                    "An exception happened when loading the raw_data of the "
189*800a58d9SAndroid Build Coastguard Worker                    "cvd runtime config:\n%s" % str(e))
190*800a58d9SAndroid Build Coastguard Worker        if not os.path.exists(runtime_cf_config_path):
191*800a58d9SAndroid Build Coastguard Worker            raise errors.ConfigError(
192*800a58d9SAndroid Build Coastguard Worker                "file does not exist: %s" % runtime_cf_config_path)
193*800a58d9SAndroid Build Coastguard Worker        with open(runtime_cf_config_path, "r") as cf_config:
194*800a58d9SAndroid Build Coastguard Worker            return json.load(cf_config)
195*800a58d9SAndroid Build Coastguard Worker
196*800a58d9SAndroid Build Coastguard Worker    @property
197*800a58d9SAndroid Build Coastguard Worker    def cvd_tools_path(self):
198*800a58d9SAndroid Build Coastguard Worker        """Return string of the path to the cvd tools."""
199*800a58d9SAndroid Build Coastguard Worker        return self._cvd_tools_path
200*800a58d9SAndroid Build Coastguard Worker
201*800a58d9SAndroid Build Coastguard Worker    @property
202*800a58d9SAndroid Build Coastguard Worker    def display_configs(self):
203*800a58d9SAndroid Build Coastguard Worker        """Return display_configs."""
204*800a58d9SAndroid Build Coastguard Worker        return self._display_configs
205*800a58d9SAndroid Build Coastguard Worker
206*800a58d9SAndroid Build Coastguard Worker    @property
207*800a58d9SAndroid Build Coastguard Worker    def adb_ip_port(self):
208*800a58d9SAndroid Build Coastguard Worker        """Return adb_ip_port."""
209*800a58d9SAndroid Build Coastguard Worker        return self._adb_ip_port
210*800a58d9SAndroid Build Coastguard Worker
211*800a58d9SAndroid Build Coastguard Worker    @property
212*800a58d9SAndroid Build Coastguard Worker    def instance_dir(self):
213*800a58d9SAndroid Build Coastguard Worker        """Return instance_dir."""
214*800a58d9SAndroid Build Coastguard Worker        return self._instance_dir
215*800a58d9SAndroid Build Coastguard Worker
216*800a58d9SAndroid Build Coastguard Worker    @property
217*800a58d9SAndroid Build Coastguard Worker    def root_dir(self):
218*800a58d9SAndroid Build Coastguard Worker        """Return root_dir."""
219*800a58d9SAndroid Build Coastguard Worker        return self._root_dir
220*800a58d9SAndroid Build Coastguard Worker
221*800a58d9SAndroid Build Coastguard Worker    @property
222*800a58d9SAndroid Build Coastguard Worker    def vnc_port(self):
223*800a58d9SAndroid Build Coastguard Worker        """Return vnc_port."""
224*800a58d9SAndroid Build Coastguard Worker        return self._vnc_port
225*800a58d9SAndroid Build Coastguard Worker
226*800a58d9SAndroid Build Coastguard Worker    @property
227*800a58d9SAndroid Build Coastguard Worker    def adb_port(self):
228*800a58d9SAndroid Build Coastguard Worker        """Return adb_port."""
229*800a58d9SAndroid Build Coastguard Worker        return self._adb_port
230*800a58d9SAndroid Build Coastguard Worker
231*800a58d9SAndroid Build Coastguard Worker    @property
232*800a58d9SAndroid Build Coastguard Worker    def config_path(self):
233*800a58d9SAndroid Build Coastguard Worker        """Return config_path."""
234*800a58d9SAndroid Build Coastguard Worker        return self._config_path
235*800a58d9SAndroid Build Coastguard Worker
236*800a58d9SAndroid Build Coastguard Worker    @property
237*800a58d9SAndroid Build Coastguard Worker    def virtual_disk_paths(self):
238*800a58d9SAndroid Build Coastguard Worker        """Return virtual_disk_paths"""
239*800a58d9SAndroid Build Coastguard Worker        return self._virtual_disk_paths
240*800a58d9SAndroid Build Coastguard Worker
241*800a58d9SAndroid Build Coastguard Worker    @property
242*800a58d9SAndroid Build Coastguard Worker    def instance_id(self):
243*800a58d9SAndroid Build Coastguard Worker        """Return _instance_id"""
244*800a58d9SAndroid Build Coastguard Worker        return self._instance_id
245*800a58d9SAndroid Build Coastguard Worker
246*800a58d9SAndroid Build Coastguard Worker    @property
247*800a58d9SAndroid Build Coastguard Worker    def instance_ids(self):
248*800a58d9SAndroid Build Coastguard Worker        """Return _instance_ids"""
249*800a58d9SAndroid Build Coastguard Worker        return self._instance_ids
250*800a58d9SAndroid Build Coastguard Worker
251*800a58d9SAndroid Build Coastguard Worker    @property
252*800a58d9SAndroid Build Coastguard Worker    def instances(self):
253*800a58d9SAndroid Build Coastguard Worker        """Return _instances"""
254*800a58d9SAndroid Build Coastguard Worker        return self._instances
255*800a58d9SAndroid Build Coastguard Worker
256*800a58d9SAndroid Build Coastguard Worker    @property
257*800a58d9SAndroid Build Coastguard Worker    def enable_webrtc(self):
258*800a58d9SAndroid Build Coastguard Worker        """Return _enable_webrtc"""
259*800a58d9SAndroid Build Coastguard Worker        return self._enable_webrtc
260