|
4 | 4 | import logging |
5 | 5 | import os |
6 | 6 | import pathlib |
| 7 | +import subprocess |
7 | 8 | import sys |
| 9 | +import time |
8 | 10 | import typing |
9 | 11 | from typing import Optional |
10 | 12 |
|
|
26 | 28 |
|
27 | 29 | _logger = logging.getLogger(__name__) |
28 | 30 |
|
| 31 | +_START_SERVICE_TIMEOUT = 30.0 |
| 32 | +_START_SERVICE_POLLING_INTERVAL = 100e-3 |
| 33 | + |
29 | 34 |
|
30 | 35 | class ServiceLocation(typing.NamedTuple): |
31 | 36 | """Represents the location of a service.""" |
@@ -204,12 +209,78 @@ def resolve_service(self, provided_interface: str, service_class: str = "") -> S |
204 | 209 |
|
205 | 210 | def _get_discovery_service_address() -> str: |
206 | 211 | key_file_path = _get_key_file_path() |
| 212 | + _ensure_discovery_service_started(key_file_path) |
207 | 213 | _logger.debug("Discovery service key file path: %s", key_file_path) |
208 | 214 | with _open_key_file(str(key_file_path)) as key_file: |
209 | 215 | key_json = json.load(key_file) |
210 | 216 | return "localhost:" + key_json["InsecurePort"] |
211 | 217 |
|
212 | 218 |
|
| 219 | +def _ensure_discovery_service_started(key_file_path: pathlib.Path) -> None: |
| 220 | + """Check whether discovery service already running, if not start the discovery service.""" |
| 221 | + if _service_already_running(key_file_path): |
| 222 | + return |
| 223 | + |
| 224 | + exe_file_path = _get_discovery_service_location() |
| 225 | + _start_service(exe_file_path, key_file_path) |
| 226 | + |
| 227 | + |
| 228 | +def _get_discovery_service_location() -> pathlib.PurePath: |
| 229 | + """Gets the location of the discovery service process executable.""" |
| 230 | + registration_json_path = _get_registration_json_file_path() |
| 231 | + registration_json_obj = json.loads(registration_json_path.read_text()) |
| 232 | + return registration_json_path.parent / registration_json_obj["discovery"]["path"] |
| 233 | + |
| 234 | + |
| 235 | +def _get_registration_json_file_path() -> pathlib.Path: |
| 236 | + if sys.platform == "win32": |
| 237 | + return ( |
| 238 | + pathlib.Path(os.environ["ProgramW6432"]) |
| 239 | + / "National Instruments" |
| 240 | + / "Shared" |
| 241 | + / "MeasurementLink" |
| 242 | + / "MeasurementLinkServices.json" |
| 243 | + ) |
| 244 | + else: |
| 245 | + raise NotImplementedError("Platform not supported") |
| 246 | + |
| 247 | + |
| 248 | +def _key_file_exists(key_file_path: pathlib.Path) -> bool: |
| 249 | + return key_file_path.is_file() and key_file_path.stat().st_size > 0 |
| 250 | + |
| 251 | + |
| 252 | +def _start_service(exe_file_path: pathlib.PurePath, key_file_path: pathlib.Path) -> None: |
| 253 | + """Starts the service at the specified path and wait for the service to get up and running.""" |
| 254 | + subprocess.Popen([exe_file_path], cwd=exe_file_path.parent) |
| 255 | + # After the execution of process, check for key file existence in the path |
| 256 | + # stop checking after 30 seconds have elapsed and throw error |
| 257 | + timeout_time = time.time() + _START_SERVICE_TIMEOUT |
| 258 | + while True: |
| 259 | + try: |
| 260 | + with _open_key_file(str(key_file_path)) as _: |
| 261 | + return |
| 262 | + except IOError: |
| 263 | + pass |
| 264 | + if time.time() >= timeout_time: |
| 265 | + raise TimeoutError("Timed out waiting for discovery service to start") |
| 266 | + time.sleep(_START_SERVICE_POLLING_INTERVAL) |
| 267 | + |
| 268 | + |
| 269 | +def _service_already_running(key_file_path: pathlib.Path) -> bool: |
| 270 | + try: |
| 271 | + _delete_existing_key_file(key_file_path) |
| 272 | + except IOError: |
| 273 | + return True |
| 274 | + return False |
| 275 | + |
| 276 | + |
| 277 | +def _delete_existing_key_file(key_file_path: pathlib.Path) -> None: |
| 278 | + if _key_file_exists(key_file_path): |
| 279 | + with key_file_path.open("w") as _: |
| 280 | + pass |
| 281 | + key_file_path.unlink() |
| 282 | + |
| 283 | + |
213 | 284 | def _get_key_file_path(cluster_id: Optional[str] = None) -> pathlib.Path: |
214 | 285 | if cluster_id is not None: |
215 | 286 | return _get_key_file_directory() / f"DiscoveryService_{cluster_id}.json" |
|
0 commit comments