• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_CROSVM_BINARY = "crosvm_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# The adb port field name changes from "host_port" to "adb_host_port".
32_CFG_KEY_ADB_PORT = "host_port"
33_CFG_KEY_ADB_HOST_PORT = "adb_host_port"
34_CFG_KEY_ENABLE_WEBRTC = "enable_webrtc"
35# TODO(148648620): Check instance_home_[id] for backward compatible.
36_RE_LOCAL_INSTANCE_ID = re.compile(r".+(?:local-instance-|instance_home_)"
37                                   r"(?P<ins_id>\d+).+")
38
39
40def _GetIdFromInstanceDirStr(instance_dir):
41    """Look for instance id from the path of instance dir.
42
43    Args:
44        instance_dir: String, path of instance_dir.
45
46    Returns:
47        String of instance id.
48    """
49    match = _RE_LOCAL_INSTANCE_ID.match(instance_dir)
50    if match:
51        return match.group("ins_id")
52
53    # To support the device which is not created by acloud.
54    if os.path.expanduser("~") in instance_dir:
55        return "1"
56
57    return None
58
59
60class CvdRuntimeConfig():
61    """The class that hold the information from cuttlefish_config.json.
62
63    The example of cuttlefish_config.json
64    {
65    "memory_mb" : 4096,
66    "cpus" : 2,
67    "dpi" : 320,
68    "virtual_disk_paths" :
69        [
70            "/path-to-image"
71        ],
72    "adb_ip_and_port" : "0.0.0.0:6520",
73    "instance_dir" : "/path-to-instance-dir",
74    }
75
76    If we launched multiple local instances, the config will be as below:
77    {
78    "memory_mb" : 4096,
79    "cpus" : 2,
80    "dpi" : 320,
81    "instances" :
82        {
83            "1" :
84            {
85                "adb_ip_and_port" : "0.0.0.0:6520",
86                "instance_dir" : "/path-to-instance-dir",
87                "virtual_disk_paths" :
88                [
89                    "/path-to-image"
90                ],
91            }
92        }
93    }
94
95    If the avd enable the webrtc, the config will be as below:
96    {
97    "enable_webrtc" : true,
98    "vnc_server_binary" : "/home/vsoc-01/bin/vnc_server",
99    "webrtc_assets_dir" : "/home/vsoc-01/usr/share/webrtc/assets",
100    "webrtc_binary" : "/home/vsoc-01/bin/webRTC",
101    "webrtc_certs_dir" : "/home/vsoc-01/usr/share/webrtc/certs",
102    "webrtc_enable_adb_websocket" : false,
103    "webrtc_public_ip" : "0.0.0.0",
104    }
105
106    """
107
108    def __init__(self, config_path=None, raw_data=None):
109        if not config_path and not raw_data:
110            raise errors.ConfigError("No cuttlefish config found!")
111        self._config_path = config_path
112        self._instance_id = "1" if raw_data else _GetIdFromInstanceDirStr(
113            config_path)
114        self._config_dict = self._GetCuttlefishRuntimeConfig(config_path,
115                                                             raw_data)
116        self._x_res = self._config_dict.get(_CFG_KEY_X_RES)
117        self._y_res = self._config_dict.get(_CFG_KEY_Y_RES)
118        self._dpi = self._config_dict.get(_CFG_KEY_DPI)
119        crosvm_bin = self._config_dict.get(_CFG_KEY_CROSVM_BINARY)
120        self._cvd_tools_path = (os.path.dirname(crosvm_bin)
121                                if crosvm_bin else None)
122
123        # Below properties will be collected inside of instance id node if there
124        # are more than one instance.
125        self._instance_dir = self._config_dict.get(_CFG_KEY_INSTANCE_DIR)
126        self._vnc_port = self._config_dict.get(_CFG_KEY_VNC_PORT)
127        self._adb_port = (self._config_dict.get(_CFG_KEY_ADB_PORT) or
128                          self._config_dict.get(_CFG_KEY_ADB_HOST_PORT))
129        self._adb_ip_port = self._config_dict.get(_CFG_KEY_ADB_IP_PORT)
130        self._virtual_disk_paths = self._config_dict.get(
131            _CFG_KEY_VIRTUAL_DISK_PATHS)
132        self._enable_webrtc = self._config_dict.get(_CFG_KEY_ENABLE_WEBRTC)
133        if not self._instance_dir:
134            ins_cfg = self._config_dict.get(_CFG_KEY_INSTANCES)
135            ins_dict = ins_cfg.get(self._instance_id)
136            if not ins_dict:
137                raise errors.ConfigError("instances[%s] property does not exist"
138                                         " in: %s" %
139                                         (self._instance_id, config_path))
140            self._instance_dir = ins_dict.get(_CFG_KEY_INSTANCE_DIR)
141            self._vnc_port = ins_dict.get(_CFG_KEY_VNC_PORT)
142            self._adb_port = (ins_dict.get(_CFG_KEY_ADB_PORT) or
143                              ins_dict.get(_CFG_KEY_ADB_HOST_PORT))
144            self._adb_ip_port = ins_dict.get(_CFG_KEY_ADB_IP_PORT)
145            self._virtual_disk_paths = ins_dict.get(_CFG_KEY_VIRTUAL_DISK_PATHS)
146
147    @staticmethod
148    def _GetCuttlefishRuntimeConfig(runtime_cf_config_path, raw_data=None):
149        """Get and parse cuttlefish_config.json.
150
151        Args:
152            runtime_cf_config_path: String, path of the cvd runtime config.
153            raw_data: String, data of the cvd runtime config.
154
155        Returns:
156            A dictionary that parsed from cuttlefish runtime config.
157
158        Raises:
159            errors.ConfigError: if file not found or config load failed.
160        """
161        if raw_data:
162            # if remote instance couldn't fetch the config will return message such as
163            # 'cat: .../cuttlefish_config.json: No such file or directory'.
164            # Add this condition to prevent from JSONDecodeError.
165            try:
166                return json.loads(raw_data)
167            except ValueError as e:
168                raise errors.ConfigError(
169                    "An exception happened when loading the raw_data of the "
170                    "cvd runtime config:\n%s" % str(e))
171        if not os.path.exists(runtime_cf_config_path):
172            raise errors.ConfigError(
173                "file does not exist: %s" % runtime_cf_config_path)
174        with open(runtime_cf_config_path, "r") as cf_config:
175            return json.load(cf_config)
176
177    @property
178    def cvd_tools_path(self):
179        """Return string of the path to the cvd tools."""
180        return self._cvd_tools_path
181
182    @property
183    def x_res(self):
184        """Return x_res."""
185        return self._x_res
186
187    @property
188    def y_res(self):
189        """Return y_res."""
190        return self._y_res
191
192    @property
193    def dpi(self):
194        """Return dpi."""
195        return self._dpi
196
197    @property
198    def adb_ip_port(self):
199        """Return adb_ip_port."""
200        return self._adb_ip_port
201
202    @property
203    def instance_dir(self):
204        """Return instance_dir."""
205        return self._instance_dir
206
207    @property
208    def vnc_port(self):
209        """Return vnc_port."""
210        return self._vnc_port
211
212    @property
213    def adb_port(self):
214        """Return adb_port."""
215        return self._adb_port
216
217    @property
218    def config_path(self):
219        """Return config_path."""
220        return self._config_path
221
222    @property
223    def virtual_disk_paths(self):
224        """Return virtual_disk_paths"""
225        return self._virtual_disk_paths
226
227    @property
228    def instance_id(self):
229        """Return _instance_id"""
230        return self._instance_id
231
232    @property
233    def enable_webrtc(self):
234        """Return _enable_webrtc"""
235        return self._enable_webrtc
236