Skip to content

Commit 5bd67da

Browse files
committed
merge (parts of) OMCSessionBase into OMCSessionZMQ
* class OMCSessionBase only contains ask() and derived functions to call OM * the moved functions were using variables of class OMCSessionZMQ * this change splits the class definitions into (1) code to connect to OM => OMCSessionBase (2) code to execute OM / connect to running OM => OMCSessionZMQ
1 parent e16f3b7 commit 5bd67da

File tree

1 file changed

+165
-167
lines changed

1 file changed

+165
-167
lines changed

OMPython/__init__.py

Lines changed: 165 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -104,171 +104,6 @@ def wait(self, timeout):
104104

105105
class OMCSessionBase(metaclass=abc.ABCMeta):
106106

107-
def __init__(self, readonly=False):
108-
self.readonly = readonly
109-
self.omc_cache = {}
110-
self._omc_process = None
111-
self._omc_command = None
112-
self._omc = None
113-
self._dockerCid = None
114-
self._serverIPAddress = "127.0.0.1"
115-
self._interactivePort = None
116-
# FIXME: this code is not well written... need to be refactored
117-
self._temp_dir = tempfile.gettempdir()
118-
# generate a random string for this session
119-
self._random_string = uuid.uuid4().hex
120-
# omc log file
121-
self._omc_log_file = None
122-
try:
123-
self._currentUser = getpass.getuser()
124-
if not self._currentUser:
125-
self._currentUser = "nobody"
126-
except KeyError:
127-
# We are running as a uid not existing in the password database... Pretend we are nobody
128-
self._currentUser = "nobody"
129-
130-
def __del__(self):
131-
try:
132-
self.sendExpression("quit()")
133-
except Exception:
134-
pass
135-
self._omc_log_file.close()
136-
if sys.version_info.major >= 3:
137-
try:
138-
self._omc_process.wait(timeout=2.0)
139-
except Exception:
140-
if self._omc_process:
141-
self._omc_process.kill()
142-
else:
143-
for i in range(0, 100):
144-
time.sleep(0.02)
145-
if self._omc_process and (self._omc_process.poll() is not None):
146-
break
147-
# kill self._omc_process process if it is still running/exists
148-
if self._omc_process is not None and self._omc_process.returncode is None:
149-
logger.warning("OMC did not exit after being sent the quit() command; killing the process with pid=%s" % str(self._omc_process.pid))
150-
if sys.platform == "win32":
151-
self._omc_process.kill()
152-
self._omc_process.wait()
153-
else:
154-
os.killpg(os.getpgid(self._omc_process.pid), signal.SIGTERM)
155-
self._omc_process.kill()
156-
self._omc_process.wait()
157-
158-
def _create_omc_log_file(self, suffix):
159-
if sys.platform == 'win32':
160-
self._omc_log_file = open(os.path.join(self._temp_dir, "openmodelica.{0}.{1}.log".format(suffix, self._random_string)), 'w')
161-
else:
162-
# this file must be closed in the destructor
163-
self._omc_log_file = open(os.path.join(self._temp_dir, "openmodelica.{0}.{1}.{2}.log".format(self._currentUser, suffix, self._random_string)), 'w')
164-
165-
def _start_omc_process(self, timeout):
166-
if sys.platform == 'win32':
167-
omhome_bin = os.path.join(self.omhome, 'bin').replace("\\", "/")
168-
my_env = os.environ.copy()
169-
my_env["PATH"] = omhome_bin + os.pathsep + my_env["PATH"]
170-
self._omc_process = subprocess.Popen(self._omc_command, stdout=self._omc_log_file, stderr=self._omc_log_file, env=my_env)
171-
else:
172-
# set the user environment variable so omc running from wsgi has the same user as OMPython
173-
my_env = os.environ.copy()
174-
my_env["USER"] = self._currentUser
175-
# Because we spawned a shell, and we need to be able to kill OMC, create a new process group for this
176-
self._omc_process = subprocess.Popen(self._omc_command, shell=True, stdout=self._omc_log_file, stderr=self._omc_log_file, env=my_env, preexec_fn=os.setsid)
177-
if self._docker:
178-
for i in range(0, 40):
179-
try:
180-
with open(self._dockerCidFile, "r") as fin:
181-
self._dockerCid = fin.read().strip()
182-
except Exception:
183-
pass
184-
if self._dockerCid:
185-
break
186-
time.sleep(timeout / 40.0)
187-
try:
188-
os.remove(self._dockerCidFile)
189-
except Exception:
190-
pass
191-
if self._dockerCid is None:
192-
logger.error("Docker did not start. Log-file says:\n%s" % (open(self._omc_log_file.name).read()))
193-
raise Exception("Docker did not start (timeout=%f might be too short especially if you did not docker pull the image before this command)." % timeout)
194-
if self._docker or self._dockerContainer:
195-
if self._dockerNetwork == "separate":
196-
self._serverIPAddress = json.loads(subprocess.check_output(["docker", "inspect", self._dockerCid]).decode().strip())[0]["NetworkSettings"]["IPAddress"]
197-
for i in range(0, 40):
198-
if sys.platform == 'win32':
199-
break
200-
dockerTop = subprocess.check_output(["docker", "top", self._dockerCid]).decode().strip()
201-
self._omc_process = None
202-
for line in dockerTop.split("\n"):
203-
columns = line.split()
204-
if self._random_string in line:
205-
try:
206-
self._omc_process = DummyPopen(int(columns[1]))
207-
except psutil.NoSuchProcess:
208-
raise Exception(f"Could not find PID {dockerTop} - is this a docker instance spawned without --pid=host?\nLog-file says:\n{open(self._omc_log_file.name).read()}")
209-
break
210-
if self._omc_process is not None:
211-
break
212-
time.sleep(timeout / 40.0)
213-
if self._omc_process is None:
214-
raise Exception("Docker top did not contain omc process %s:\n%s\nLog-file says:\n%s" % (self._random_string, dockerTop, open(self._omc_log_file.name).read()))
215-
return self._omc_process
216-
217-
def _getuid(self):
218-
"""
219-
The uid to give to docker.
220-
On Windows, volumes are mapped with all files are chmod ugo+rwx,
221-
so uid does not matter as long as it is not the root user.
222-
"""
223-
return 1000 if sys.platform == 'win32' else os.getuid()
224-
225-
def _set_omc_command(self, omc_path_and_args_list):
226-
"""Define the command that will be called by the subprocess module.
227-
228-
On Windows, use the list input style of the subprocess module to
229-
avoid problems resulting from spaces in the path string.
230-
Linux, however, only works with the string version.
231-
"""
232-
if (self._docker or self._dockerContainer) and sys.platform == "win32":
233-
extraFlags = ["-d=zmqDangerousAcceptConnectionsFromAnywhere"]
234-
if not self._interactivePort:
235-
raise Exception("docker on Windows requires knowing which port to connect to. For dockerContainer=..., the container needs to have already manually exposed this port when it was started (-p 127.0.0.1:n:n) or you get an error later.")
236-
else:
237-
extraFlags = []
238-
if self._docker:
239-
if sys.platform == "win32":
240-
p = int(self._interactivePort)
241-
dockerNetworkStr = ["-p", "127.0.0.1:%d:%d" % (p, p)]
242-
elif self._dockerNetwork == "host" or self._dockerNetwork is None:
243-
dockerNetworkStr = ["--network=host"]
244-
elif self._dockerNetwork == "separate":
245-
dockerNetworkStr = []
246-
extraFlags = ["-d=zmqDangerousAcceptConnectionsFromAnywhere"]
247-
else:
248-
raise Exception('dockerNetwork was set to %s, but only \"host\" or \"separate\" is allowed')
249-
self._dockerCidFile = self._omc_log_file.name + ".docker.cid"
250-
omcCommand = ["docker", "run", "--cidfile", self._dockerCidFile, "--rm", "--env", "USER=%s" % self._currentUser, "--user", str(self._getuid())] + self._dockerExtraArgs + dockerNetworkStr + [self._docker, self._dockerOpenModelicaPath]
251-
elif self._dockerContainer:
252-
omcCommand = ["docker", "exec", "--env", "USER=%s" % self._currentUser, "--user", str(self._getuid())] + self._dockerExtraArgs + [self._dockerContainer, self._dockerOpenModelicaPath]
253-
self._dockerCid = self._dockerContainer
254-
else:
255-
omcCommand = [self._get_omc_path()]
256-
if self._interactivePort:
257-
extraFlags = extraFlags + ["--interactivePort=%d" % int(self._interactivePort)]
258-
259-
omc_path_and_args_list = omcCommand + omc_path_and_args_list + extraFlags
260-
261-
if sys.platform == 'win32':
262-
self._omc_command = omc_path_and_args_list
263-
else:
264-
self._omc_command = ' '.join([shlex.quote(a) if (sys.version_info > (3, 0)) else a for a in omc_path_and_args_list])
265-
266-
return self._omc_command
267-
268-
@abc.abstractmethod
269-
def _connect_to_omc(self, timeout):
270-
pass
271-
272107
def clearOMParserResult(self):
273108
OMParser.result = {}
274109

@@ -503,7 +338,28 @@ def __init__(self, readonly=False, timeout=10.00,
503338

504339
self.omhome = self._get_omhome(omhome=omhome)
505340

506-
OMCSessionBase.__init__(self, readonly)
341+
self.readonly = readonly
342+
self.omc_cache = {}
343+
self._omc_process = None
344+
self._omc_command = None
345+
self._omc = None
346+
self._dockerCid = None
347+
self._serverIPAddress = "127.0.0.1"
348+
self._interactivePort = None
349+
# FIXME: this code is not well written... need to be refactored
350+
self._temp_dir = tempfile.gettempdir()
351+
# generate a random string for this session
352+
self._random_string = uuid.uuid4().hex
353+
# omc log file
354+
self._omc_log_file = None
355+
try:
356+
self._currentUser = getpass.getuser()
357+
if not self._currentUser:
358+
self._currentUser = "nobody"
359+
except KeyError:
360+
# We are running as a uid not existing in the password database... Pretend we are nobody
361+
self._currentUser = "nobody"
362+
507363
# Locating and using the IOR
508364
if sys.platform != 'win32' or docker or dockerContainer:
509365
self._port_file = "openmodelica." + self._currentUser + ".port." + self._random_string
@@ -530,7 +386,149 @@ def __init__(self, readonly=False, timeout=10.00,
530386
self._connect_to_omc(timeout)
531387

532388
def __del__(self):
533-
OMCSessionBase.__del__(self)
389+
try:
390+
self.sendExpression("quit()")
391+
except Exception:
392+
pass
393+
self._omc_log_file.close()
394+
if sys.version_info.major >= 3:
395+
try:
396+
self._omc_process.wait(timeout=2.0)
397+
except Exception:
398+
if self._omc_process:
399+
self._omc_process.kill()
400+
else:
401+
for i in range(0, 100):
402+
time.sleep(0.02)
403+
if self._omc_process and (self._omc_process.poll() is not None):
404+
break
405+
# kill self._omc_process process if it is still running/exists
406+
if self._omc_process is not None and self._omc_process.returncode is None:
407+
logger.warning("OMC did not exit after being sent the quit() command; killing the process with pid=%s" % str(self._omc_process.pid))
408+
if sys.platform == "win32":
409+
self._omc_process.kill()
410+
self._omc_process.wait()
411+
else:
412+
os.killpg(os.getpgid(self._omc_process.pid), signal.SIGTERM)
413+
self._omc_process.kill()
414+
self._omc_process.wait()
415+
416+
def _create_omc_log_file(self, suffix):
417+
if sys.platform == 'win32':
418+
self._omc_log_file = open(os.path.join(self._temp_dir, "openmodelica.{0}.{1}.log".format(suffix, self._random_string)), 'w')
419+
else:
420+
# this file must be closed in the destructor
421+
self._omc_log_file = open(os.path.join(self._temp_dir, "openmodelica.{0}.{1}.{2}.log".format(self._currentUser, suffix, self._random_string)), 'w')
422+
423+
def _start_omc_process(self, timeout):
424+
if sys.platform == 'win32':
425+
omhome_bin = os.path.join(self.omhome, 'bin').replace("\\", "/")
426+
my_env = os.environ.copy()
427+
my_env["PATH"] = omhome_bin + os.pathsep + my_env["PATH"]
428+
self._omc_process = subprocess.Popen(self._omc_command, stdout=self._omc_log_file,
429+
stderr=self._omc_log_file, env=my_env)
430+
else:
431+
# set the user environment variable so omc running from wsgi has the same user as OMPython
432+
my_env = os.environ.copy()
433+
my_env["USER"] = self._currentUser
434+
# Because we spawned a shell, and we need to be able to kill OMC, create a new process group for this
435+
self._omc_process = subprocess.Popen(self._omc_command, shell=True, stdout=self._omc_log_file,
436+
stderr=self._omc_log_file, env=my_env, preexec_fn=os.setsid)
437+
if self._docker:
438+
for i in range(0, 40):
439+
try:
440+
with open(self._dockerCidFile, "r") as fin:
441+
self._dockerCid = fin.read().strip()
442+
except Exception:
443+
pass
444+
if self._dockerCid:
445+
break
446+
time.sleep(timeout / 40.0)
447+
try:
448+
os.remove(self._dockerCidFile)
449+
except Exception:
450+
pass
451+
if self._dockerCid is None:
452+
logger.error("Docker did not start. Log-file says:\n%s" % (open(self._omc_log_file.name).read()))
453+
raise Exception("Docker did not start (timeout=%f might be too short especially if you did not docker pull the image before this command)." % timeout)
454+
455+
dockerTop = None
456+
if self._docker or self._dockerContainer:
457+
if self._dockerNetwork == "separate":
458+
self._serverIPAddress = json.loads(subprocess.check_output(["docker", "inspect", self._dockerCid]).decode().strip())[0]["NetworkSettings"]["IPAddress"]
459+
for i in range(0, 40):
460+
if sys.platform == 'win32':
461+
break
462+
dockerTop = subprocess.check_output(["docker", "top", self._dockerCid]).decode().strip()
463+
self._omc_process = None
464+
for line in dockerTop.split("\n"):
465+
columns = line.split()
466+
if self._random_string in line:
467+
try:
468+
self._omc_process = DummyPopen(int(columns[1]))
469+
except psutil.NoSuchProcess:
470+
raise Exception(
471+
"Could not find PID %s - is this a docker instance spawned without --pid=host?\n"
472+
"Log-file says:\n%s" % (self._random_string, open(self._omc_log_file.name).read()))
473+
break
474+
if self._omc_process is not None:
475+
break
476+
time.sleep(timeout / 40.0)
477+
if self._omc_process is None:
478+
raise Exception("Docker top did not contain omc process %s:\n%s\nLog-file says:\n%s"
479+
% (self._random_string, dockerTop, open(self._omc_log_file.name).read()))
480+
return self._omc_process
481+
482+
def _getuid(self):
483+
"""
484+
The uid to give to docker.
485+
On Windows, volumes are mapped with all files are chmod ugo+rwx,
486+
so uid does not matter as long as it is not the root user.
487+
"""
488+
return 1000 if sys.platform == 'win32' else os.getuid()
489+
490+
def _set_omc_command(self, omc_path_and_args_list):
491+
"""Define the command that will be called by the subprocess module.
492+
493+
On Windows, use the list input style of the subprocess module to
494+
avoid problems resulting from spaces in the path string.
495+
Linux, however, only works with the string version.
496+
"""
497+
if (self._docker or self._dockerContainer) and sys.platform == "win32":
498+
extraFlags = ["-d=zmqDangerousAcceptConnectionsFromAnywhere"]
499+
if not self._interactivePort:
500+
raise Exception("docker on Windows requires knowing which port to connect to. For dockerContainer=..., the container needs to have already manually exposed this port when it was started (-p 127.0.0.1:n:n) or you get an error later.")
501+
else:
502+
extraFlags = []
503+
if self._docker:
504+
if sys.platform == "win32":
505+
p = int(self._interactivePort)
506+
dockerNetworkStr = ["-p", "127.0.0.1:%d:%d" % (p, p)]
507+
elif self._dockerNetwork == "host" or self._dockerNetwork is None:
508+
dockerNetworkStr = ["--network=host"]
509+
elif self._dockerNetwork == "separate":
510+
dockerNetworkStr = []
511+
extraFlags = ["-d=zmqDangerousAcceptConnectionsFromAnywhere"]
512+
else:
513+
raise Exception('dockerNetwork was set to %s, but only \"host\" or \"separate\" is allowed')
514+
self._dockerCidFile = self._omc_log_file.name + ".docker.cid"
515+
omcCommand = ["docker", "run", "--cidfile", self._dockerCidFile, "--rm", "--env", "USER=%s" % self._currentUser, "--user", str(self._getuid())] + self._dockerExtraArgs + dockerNetworkStr + [self._docker, self._dockerOpenModelicaPath]
516+
elif self._dockerContainer:
517+
omcCommand = ["docker", "exec", "--env", "USER=%s" % self._currentUser, "--user", str(self._getuid())] + self._dockerExtraArgs + [self._dockerContainer, self._dockerOpenModelicaPath]
518+
self._dockerCid = self._dockerContainer
519+
else:
520+
omcCommand = [self._get_omc_path()]
521+
if self._interactivePort:
522+
extraFlags = extraFlags + ["--interactivePort=%d" % int(self._interactivePort)]
523+
524+
omc_path_and_args_list = omcCommand + omc_path_and_args_list + extraFlags
525+
526+
if sys.platform == 'win32':
527+
self._omc_command = omc_path_and_args_list
528+
else:
529+
self._omc_command = ' '.join([shlex.quote(a) if (sys.version_info > (3, 0)) else a for a in omc_path_and_args_list])
530+
531+
return self._omc_command
534532

535533
def _get_omhome(self, omhome: str = None):
536534
# use the provided path

0 commit comments

Comments
 (0)