Skip to content

Commit b82b893

Browse files
committed
[OMCSessionZMQ] remove all docker related code
1 parent cf937cc commit b82b893

1 file changed

Lines changed: 85 additions & 183 deletions

File tree

OMPython/OMCSession.py

Lines changed: 85 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"""
3636

3737
import getpass
38+
import io
3839
import json
3940
import logging
4041
import os
@@ -272,25 +273,16 @@ class OMCSessionZMQ:
272273

273274
def __init__(self,
274275
timeout: float = 10.00,
275-
docker: Optional[str] = None,
276-
dockerContainer: Optional[int] = None,
277-
dockerExtraArgs: Optional[list] = None,
278-
dockerOpenModelicaPath: str = "omc",
279-
dockerNetwork: Optional[str] = None,
280-
port: Optional[int] = None,
281276
omhome: Optional[str] = None):
282-
if dockerExtraArgs is None:
283-
dockerExtraArgs = []
284277

285-
self._omhome = self._get_omhome(omhome=omhome)
278+
# store variables
279+
self._omhome = self._omc_home_get(omhome=omhome)
280+
self._timeout = timeout
281+
282+
# variables to store compiled re expressions use in self.sendExpression()
283+
self._re_log_entries = None
284+
self._re_log_raw = None
286285

287-
self._omc_process = None
288-
self._omc_command = None
289-
self._omc: Optional[Any] = None
290-
self._dockerCid: Optional[int] = None
291-
self._serverIPAddress = "127.0.0.1"
292-
self._interactivePort = None
293-
self._temp_dir = pathlib.Path(tempfile.gettempdir())
294286
# generate a random string for this session
295287
self._random_string = uuid.uuid4().hex
296288
try:
@@ -301,38 +293,50 @@ def __init__(self,
301293
# We are running as a uid not existing in the password database... Pretend we are nobody
302294
self._currentUser = "nobody"
303295

304-
self._docker = docker
305-
self._dockerContainer = dockerContainer
306-
self._dockerExtraArgs = dockerExtraArgs
307-
self._dockerOpenModelicaPath = dockerOpenModelicaPath
308-
self._dockerNetwork = dockerNetwork
309-
self._omc_log_file = self._create_omc_log_file("port")
310-
self._timeout = timeout
311296
# Locating and using the IOR
312-
if sys.platform != 'win32' or docker or dockerContainer:
313-
port_file = "openmodelica." + self._currentUser + ".port." + self._random_string
297+
self._temp_dir = pathlib.Path(tempfile.gettempdir())
298+
self._omc_file_port = self._temp_dir / self._filename_port(current_user=self._currentUser,
299+
random_str=self._random_string)
300+
301+
if sys.platform == 'win32':
302+
filename_log = f"openmodelica.port.{self._random_string}.log"
314303
else:
315-
port_file = "openmodelica.port." + self._random_string
316-
self._port_file = ((pathlib.Path("/tmp") if docker else self._temp_dir) / port_file).as_posix()
317-
self._interactivePort = port
304+
filename_log = f"openmodelica.{self._currentUser}.port.{self._random_string}.log"
305+
self._omc_file_log = self._temp_dir / filename_log
306+
# this file must be closed in the destructor
307+
self._omc_filehandle_log: Optional[io.TextIOWrapper] = None
308+
try:
309+
self._omc_filehandle_log = open(self._temp_dir / filename_log, "w+")
310+
except OSError as ex:
311+
raise OMCSessionException(f"Cannot open log file {self._omc_file_log}.") from ex
312+
318313
# set omc executable path and args
319-
self._omc_command = self._set_omc_command(omc_path_and_args_list=["--interactive=zmq",
320-
"--locale=C",
314+
self._omc_command = self._omc_command_get(omc_path_and_args_list=["--locale=C",
315+
"--interactive=zmq",
321316
f"-z={self._random_string}"])
322317
# start up omc executable, which is waiting for the ZMQ connection
323-
self._omc_process = self._start_omc_process(timeout)
318+
self._omc_process = self._omc_process_get(timeout)
324319
# connect to the running omc instance using ZMQ
325-
self._omc_port = self._connect_to_omc(timeout)
320+
self._omc_port = self._omc_port_get(timeout)
326321

327-
self._re_log_entries = None
328-
self._re_log_raw = None
322+
# Create the ZeroMQ socket and connect to OMC server
323+
context = zmq.Context.instance()
324+
omc = context.socket(zmq.REQ)
325+
omc.setsockopt(zmq.LINGER, 0) # Dismisses pending messages if closed
326+
omc.setsockopt(zmq.IMMEDIATE, True) # Queue messages only to completed connections
327+
omc.connect(self._omc_port)
328+
329+
self._omc = omc
329330

330331
def __del__(self):
331332
try:
332333
self.sendExpression("quit()")
333334
except OMCSessionException:
334335
pass
335-
self._omc_log_file.close()
336+
337+
if self._omc_filehandle_log is not None:
338+
self._omc_filehandle_log.close()
339+
336340
try:
337341
self._omc_process.wait(timeout=2.0)
338342
except subprocess.TimeoutExpired:
@@ -342,136 +346,41 @@ def __del__(self):
342346
self._omc_process.kill()
343347
self._omc_process.wait()
344348

345-
def _create_omc_log_file(self, suffix): # output?
346-
if sys.platform == 'win32':
347-
log_filename = f"openmodelica.{suffix}.{self._random_string}.log"
349+
@staticmethod
350+
def _filename_port(current_user: str, random_str: str) -> str:
351+
if sys.platform != 'win32':
352+
filename = f"openmodelica.{current_user}.port.{random_str}"
348353
else:
349-
log_filename = f"openmodelica.{self._currentUser}.{suffix}.{self._random_string}.log"
350-
# this file must be closed in the destructor
351-
omc_log_file = open(self._temp_dir / log_filename, "w+")
354+
filename = f"openmodelica.port.{random_str}"
352355

353-
return omc_log_file
356+
return filename
357+
358+
def _omc_process_get(self, timeout): # output?
359+
my_env = os.environ.copy()
354360

355-
def _start_omc_process(self, timeout): # output?
356361
if sys.platform == 'win32':
357362
omhome_bin = (self._omhome / "bin").as_posix()
358-
my_env = os.environ.copy()
359363
my_env["PATH"] = omhome_bin + os.pathsep + my_env["PATH"]
360-
omc_process = subprocess.Popen(self._omc_command, stdout=self._omc_log_file,
361-
stderr=self._omc_log_file, env=my_env)
362364
else:
363365
# set the user environment variable so omc running from wsgi has the same user as OMPython
364-
my_env = os.environ.copy()
365366
my_env["USER"] = self._currentUser
366-
omc_process = subprocess.Popen(self._omc_command, stdout=self._omc_log_file,
367-
stderr=self._omc_log_file, env=my_env)
368-
if self._docker:
369-
for i in range(0, 40):
370-
try:
371-
with open(self._dockerCidFile, "r") as fin:
372-
self._dockerCid = fin.read().strip()
373-
except IOError:
374-
pass
375-
if self._dockerCid:
376-
break
377-
time.sleep(timeout / 40.0)
378-
try:
379-
os.remove(self._dockerCidFile)
380-
except FileNotFoundError:
381-
pass
382-
if self._dockerCid is None:
383-
logger.error("Docker did not start. Log-file says:\n%s" % (open(self._omc_log_file.name).read()))
384-
raise OMCSessionException("Docker did not start (timeout=%f might be too short especially if you did "
385-
"not docker pull the image before this command)." % timeout)
386-
387-
dockerTop = None
388-
if self._docker or self._dockerContainer:
389-
if self._dockerNetwork == "separate":
390-
output = subprocess.check_output(["docker", "inspect", self._dockerCid]).decode().strip()
391-
self._serverIPAddress = json.loads(output)[0]["NetworkSettings"]["IPAddress"]
392-
for i in range(0, 40):
393-
if sys.platform == 'win32':
394-
break
395-
dockerTop = subprocess.check_output(["docker", "top", self._dockerCid]).decode().strip()
396-
omc_process = None
397-
for line in dockerTop.split("\n"):
398-
columns = line.split()
399-
if self._random_string in line:
400-
try:
401-
omc_process = DummyPopen(int(columns[1]))
402-
except psutil.NoSuchProcess:
403-
raise OMCSessionException(
404-
f"Could not find PID {dockerTop} - is this a docker instance spawned "
405-
f"without --pid=host?\nLog-file says:\n{open(self._omc_log_file.name).read()}")
406-
break
407-
if omc_process is not None:
408-
break
409-
time.sleep(timeout / 40.0)
410-
if omc_process is None:
411-
raise OMCSessionException("Docker top did not contain omc process %s:\n%s\nLog-file says:\n%s"
412-
% (self._random_string, dockerTop, open(self._omc_log_file.name).read()))
367+
368+
omc_process = subprocess.Popen(self._omc_command, stdout=self._omc_filehandle_log,
369+
stderr=self._omc_filehandle_log, env=my_env)
413370
return omc_process
414371

415-
def _getuid(self):
372+
def _omc_command_get(self, omc_path_and_args_list) -> list:
416373
"""
417-
The uid to give to docker.
418-
On Windows, volumes are mapped with all files are chmod ugo+rwx,
419-
so uid does not matter as long as it is not the root user.
374+
Define the command that will be called by the subprocess module.
420375
"""
421-
return 1000 if sys.platform == 'win32' else os.getuid()
422-
423-
def _set_omc_command(self, omc_path_and_args_list) -> list:
424-
"""Define the command that will be called by the subprocess module.
425-
426-
On Windows, use the list input style of the subprocess module to
427-
avoid problems resulting from spaces in the path string.
428-
Linux, however, only works with the string version.
429-
"""
430-
if (self._docker or self._dockerContainer) and sys.platform == "win32":
431-
extraFlags = ["-d=zmqDangerousAcceptConnectionsFromAnywhere"]
432-
if not self._interactivePort:
433-
raise OMCSessionException("docker on Windows requires knowing which port to connect to. For "
434-
"dockerContainer=..., the container needs to have already manually exposed "
435-
"this port when it was started (-p 127.0.0.1:n:n) or you get an error later.")
436-
else:
437-
extraFlags = []
438-
if self._docker:
439-
if sys.platform == "win32":
440-
p = int(self._interactivePort)
441-
dockerNetworkStr = ["-p", "127.0.0.1:%d:%d" % (p, p)]
442-
elif self._dockerNetwork == "host" or self._dockerNetwork is None:
443-
dockerNetworkStr = ["--network=host"]
444-
elif self._dockerNetwork == "separate":
445-
dockerNetworkStr = []
446-
extraFlags = ["-d=zmqDangerousAcceptConnectionsFromAnywhere"]
447-
else:
448-
raise OMCSessionException('dockerNetwork was set to %s, but only \"host\" or \"separate\" is allowed')
449-
self._dockerCidFile = self._omc_log_file.name + ".docker.cid"
450-
omcCommand = (["docker", "run",
451-
"--cidfile", self._dockerCidFile,
452-
"--rm",
453-
"--env", "USER=%s" % self._currentUser,
454-
"--user", str(self._getuid())]
455-
+ self._dockerExtraArgs
456-
+ dockerNetworkStr
457-
+ [self._docker, self._dockerOpenModelicaPath])
458-
elif self._dockerContainer:
459-
omcCommand = (["docker", "exec",
460-
"--env", "USER=%s" % self._currentUser,
461-
"--user", str(self._getuid())]
462-
+ self._dockerExtraArgs
463-
+ [self._dockerContainer, self._dockerOpenModelicaPath])
464-
self._dockerCid = self._dockerContainer
465-
else:
466-
omcCommand = [str(self._get_omc_path())]
467-
if self._interactivePort:
468-
extraFlags = extraFlags + ["--interactivePort=%d" % int(self._interactivePort)]
376+
omc_command_base = [str(self._omc_path_get())]
469377

470-
omc_command = omcCommand + omc_path_and_args_list + extraFlags
378+
omc_command = omc_command_base + omc_path_and_args_list
471379

472380
return omc_command
473381

474-
def _get_omhome(self, omhome: Optional[str] = None):
382+
@staticmethod
383+
def _omc_home_get(omhome: Optional[str] = None):
475384
# use the provided path
476385
if omhome is not None:
477386
return pathlib.Path(omhome)
@@ -488,51 +397,44 @@ def _get_omhome(self, omhome: Optional[str] = None):
488397

489398
raise OMCSessionException("Cannot find OpenModelica executable, please install from openmodelica.org")
490399

491-
def _get_omc_path(self) -> pathlib.Path:
400+
def _omc_path_get(self) -> pathlib.Path:
492401
return self._omhome / "bin" / "omc"
493402

494-
def _connect_to_omc(self, timeout) -> str:
495-
omc_zeromq_uri = "file:///" + self._port_file
403+
def _omc_port_get(self, timeout) -> str:
404+
omc_zeromq_uri = "file:///" + self._omc_file_port.as_posix()
496405
# See if the omc server is running
497406
attempts = 0
498-
port = None
499407
while True:
500-
if self._dockerCid:
501-
try:
502-
port = subprocess.check_output(args=["docker",
503-
"exec", str(self._dockerCid),
504-
"cat", str(self._port_file)],
505-
stderr=subprocess.DEVNULL).decode().strip()
506-
break
507-
except subprocess.CalledProcessError:
508-
pass
509-
else:
510-
if os.path.isfile(self._port_file):
511-
# Read the port file
512-
with open(self._port_file, 'r') as f_p:
513-
port = f_p.readline()
514-
os.remove(self._port_file)
515-
break
408+
port = self._omc_port_get_main()
409+
if port is not None:
410+
break
516411

517412
attempts += 1
518413
if attempts == 80.0:
519-
name = self._omc_log_file.name
520-
self._omc_log_file.close()
521-
logger.error("OMC Server did not start. Please start it! Log-file says:\n%s" % open(name).read())
414+
if self._omc_filehandle_log is not None:
415+
name = self._omc_filehandle_log.name
416+
self._omc_filehandle_log.close()
417+
self._omc_filehandle_log = None
418+
log_content = open(name).read()
419+
else:
420+
log_content = '(missing log file)'
522421
raise OMCSessionException(f"OMC Server did not start (timeout={timeout}). "
523-
f"Could not open file {self._port_file}")
422+
f"Could not open file {self._omc_file_port.as_posix()}. "
423+
f"Log-file says:\n{log_content}")
524424
time.sleep(timeout / 80.0)
525425

526-
port = port.replace("0.0.0.0", self._serverIPAddress)
527426
logger.info(f"OMC Server is up and running at {omc_zeromq_uri} "
528-
f"pid={self._omc_process.pid if self._omc_process else '?'} cid={self._dockerCid}")
427+
f"pid={self._omc_process.pid if self._omc_process else '?'}")
529428

530-
# Create the ZeroMQ socket and connect to OMC server
531-
context = zmq.Context.instance()
532-
self._omc = context.socket(zmq.REQ)
533-
self._omc.setsockopt(zmq.LINGER, 0) # Dismisses pending messages if closed
534-
self._omc.setsockopt(zmq.IMMEDIATE, True) # Queue messages only to completed connections
535-
self._omc.connect(port)
429+
return port
430+
431+
def _omc_port_get_main(self) -> Optional[str]:
432+
port = None
433+
if self._omc_file_port.is_file():
434+
# Read the port file
435+
with open(self._omc_file_port, 'r') as f_p:
436+
port = f_p.readline()
437+
self._omc_file_port.unlink()
536438

537439
return port
538440

@@ -561,9 +463,9 @@ def sendExpression(self, command, parsed=True):
561463
pass
562464
attempts += 1
563465
if attempts >= 50:
564-
self._omc_log_file.seek(0)
565-
log = self._omc_log_file.read()
566-
self._omc_log_file.close()
466+
self._omc_filehandle_log.seek(0)
467+
log = self._omc_filehandle_log.read()
468+
self._omc_filehandle_log.close()
567469
raise OMCSessionException(f"No connection with OMC (timeout={self._timeout}). Log-file says: \n{log}")
568470
time.sleep(self._timeout / 50.0)
569471
if command == "quit()":

0 commit comments

Comments
 (0)