From ada825e00e28a4c1d61cee3dcd94c570a8e69494 Mon Sep 17 00:00:00 2001 From: syntron Date: Thu, 12 Jun 2025 21:07:21 +0200 Subject: [PATCH 1/2] [OMCProcessWSL] (untested) WSL based OMPython with OMC via ZMQ --- OMPython/OMCSession.py | 78 ++++++++++++++++++++++++++++++++++++++++++ OMPython/__init__.py | 4 ++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/OMPython/OMCSession.py b/OMPython/OMCSession.py index 8bdff30a6..55b6915d8 100644 --- a/OMPython/OMCSession.py +++ b/OMPython/OMCSession.py @@ -972,3 +972,81 @@ def _omc_docker_start(self) -> Tuple[subprocess.Popen, DummyPopen]: f"/ {self._dockerCid}. Log-file says:\n{self.get_log()}") return omc_process, docker_process + + +class OMCProcessWSL(OMCProcess): + + def __init__( + self, + timeout: float = 10.00, + omhome: Optional[str] = None, + wsl_distribution: Optional[str] = None, + wsl_user: Optional[str] = None, + ) -> None: + + super().__init__(timeout=timeout) + + # get wsl base command + self._wsl_cmd = ['wsl'] + if isinstance(wsl_distribution, str): + self._wsl_cmd += ['--distribution', wsl_distribution] + if isinstance(wsl_user, str): + self._wsl_cmd += ['--user', wsl_user] + self._wsl_cmd += ['--'] + + # where to find OpenModelica + self._omhome = omhome + # start up omc executable, which is waiting for the ZMQ connection + self._omc_process = self._omc_process_get() + # connect to the running omc instance using ZMQ + self._omc_port = self._omc_port_get() + + def _omc_process_get(self) -> subprocess.Popen: + my_env = os.environ.copy() + + omc_path = 'omc' + if self._omhome is not None: + omc_path = f"{self._omhome}/{omc_path}" + + omc_command = self._wsl_cmd + [ + omc_path, + "--locale=C", + "--interactive=zmq", + f"-z={self._random_string}"] + + omc_process = subprocess.Popen(omc_command, + stdout=self._omc_loghandle, + stderr=self._omc_loghandle, + env=my_env) + return omc_process + + def _omc_port_get(self) -> str: + omc_portfile_path: Optional[pathlib.Path] = None + port = None + + # See if the omc server is running + attempts = 0 + while True: + try: + omc_portfile_path = self._get_portfile_path() + if omc_portfile_path is not None: + output = subprocess.check_output(args=self._wsl_cmd + ["cat", omc_portfile_path.as_posix()], + stderr=subprocess.DEVNULL) + port = output.decode().strip() + except subprocess.CalledProcessError: + pass + + if port is not None: + break + + attempts += 1 + if attempts == 80.0: + raise OMCSessionException(f"WSL based OMC Server did not start (timeout={self._timeout}). " + f"Could not open port file {omc_portfile_path}. " + f"Log-file says:\n{self.get_log()}") + time.sleep(self._timeout / 80.0) + + logger.info(f"WSL based OMC Server is up and running at ZMQ port {port} " + f"pid={self._omc_process.pid if isinstance(self._omc_process, subprocess.Popen) else '?'}") + + return port diff --git a/OMPython/__init__.py b/OMPython/__init__.py index 93fcdaa2d..1da0a0a36 100644 --- a/OMPython/__init__.py +++ b/OMPython/__init__.py @@ -38,7 +38,8 @@ from OMPython.ModelicaSystem import LinearizationResult, ModelicaSystem, ModelicaSystemCmd, ModelicaSystemError from OMPython.OMCSession import (OMCSessionCmd, OMCSessionException, OMCSessionZMQ, - OMCProcessPort, OMCProcessLocal, OMCProcessDocker, OMCProcessDockerContainer) + OMCProcessPort, OMCProcessLocal, OMCProcessDocker, OMCProcessDockerContainer, + OMCProcessWSL) # global names imported if import 'from OMPython import *' is used __all__ = [ @@ -54,4 +55,5 @@ 'OMCProcessLocal', 'OMCProcessDocker', 'OMCProcessDockerContainer', + 'OMCProcessWSL', ] From 58bbac07bd9b1b2ba8b680e8a891406edd57609f Mon Sep 17 00:00:00 2001 From: syntron Date: Fri, 13 Jun 2025 13:29:04 +0200 Subject: [PATCH 2/2] [OMCProcessWSL] set omc location via argument wsl_omc --- OMPython/OMCSession.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/OMPython/OMCSession.py b/OMPython/OMCSession.py index 55b6915d8..608c37273 100644 --- a/OMPython/OMCSession.py +++ b/OMPython/OMCSession.py @@ -979,7 +979,7 @@ class OMCProcessWSL(OMCProcess): def __init__( self, timeout: float = 10.00, - omhome: Optional[str] = None, + wsl_omc: str = 'omc', wsl_distribution: Optional[str] = None, wsl_user: Optional[str] = None, ) -> None: @@ -995,7 +995,7 @@ def __init__( self._wsl_cmd += ['--'] # where to find OpenModelica - self._omhome = omhome + self._wsl_omc = wsl_omc # start up omc executable, which is waiting for the ZMQ connection self._omc_process = self._omc_process_get() # connect to the running omc instance using ZMQ @@ -1004,12 +1004,8 @@ def __init__( def _omc_process_get(self) -> subprocess.Popen: my_env = os.environ.copy() - omc_path = 'omc' - if self._omhome is not None: - omc_path = f"{self._omhome}/{omc_path}" - omc_command = self._wsl_cmd + [ - omc_path, + self._wsl_omc, "--locale=C", "--interactive=zmq", f"-z={self._random_string}"] @@ -1030,8 +1026,10 @@ def _omc_port_get(self) -> str: try: omc_portfile_path = self._get_portfile_path() if omc_portfile_path is not None: - output = subprocess.check_output(args=self._wsl_cmd + ["cat", omc_portfile_path.as_posix()], - stderr=subprocess.DEVNULL) + output = subprocess.check_output( + args=self._wsl_cmd + ["cat", omc_portfile_path.as_posix()], + stderr=subprocess.DEVNULL, + ) port = output.decode().strip() except subprocess.CalledProcessError: pass