Skip to content

Commit 54371e8

Browse files
author
Thierry RAMORASOAVINA
committed
Ensure HOME is always set when running khiops core with OpenMPI 5+
- A specific environment is created when running khiops core. In this environment HOME is set using KHIOPS_MPI_HOME if it exists
1 parent 6aea158 commit 54371e8

2 files changed

Lines changed: 89 additions & 1 deletion

File tree

khiops/core/internals/runner.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -994,8 +994,14 @@ def _initialize_khiops_environment(self):
994994
var_value = ""
995995
else:
996996
continue
997+
998+
# Special var to export in order
999+
# to prepend to or to set to HOME for OpenMPI 5+
1000+
# when running khiops core
1001+
if var_name == "KHIOPS_MPI_HOME":
1002+
os.environ["KHIOPS_MPI_HOME"] = var_value
9971003
# Set paths to Khiops binaries
998-
if var_name == "KHIOPS_PATH":
1004+
elif var_name == "KHIOPS_PATH":
9991005
self.khiops_path = var_value
10001006
os.environ["KHIOPS_PATH"] = var_value
10011007
elif var_name == "KHIOPS_COCLUSTERING_PATH":
@@ -1443,6 +1449,14 @@ def raw_run(self, tool_name, command_line_args=None, use_mpi=True, trace=False):
14431449
khiops_call += f" {quote}{arg}{quote}"
14441450
print(f"Khiops execution call: {khiops_call}")
14451451

1452+
# Build custom Khiops process environment
1453+
# which makes sure HOME is defined and set
1454+
# according to khiops_env's KHIOPS_MPI_HOME
1455+
khiops_env = os.environ.copy()
1456+
khiops_env["HOME"] = os.path.pathsep.join(
1457+
[khiops_env.get("KHIOPS_MPI_HOME", ""), khiops_env.get("HOME", "")]
1458+
)
1459+
14461460
# Execute the process
14471461
with subprocess.Popen(
14481462
khiops_process_args,
@@ -1452,6 +1466,7 @@ def raw_run(self, tool_name, command_line_args=None, use_mpi=True, trace=False):
14521466
encoding="utf8",
14531467
errors="replace",
14541468
universal_newlines=True,
1469+
env=khiops_env,
14551470
) as khiops_process:
14561471
stdout, stderr = khiops_process.communicate()
14571472

tests/test_khiops_integrations.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,12 +282,85 @@ def test_environment_error_on_bogus_khiops_env_script(self):
282282
output_msg = str(context.exception)
283283
self.assertEqual(output_msg, expected_msg)
284284

285+
def test_runner_environment_for_openmpi5(self):
286+
"""Test if HOME is actually corrected for OpenMPI 5+"""
287+
288+
with tempfile.TemporaryDirectory() as temp_dir:
289+
290+
# Create temporary khiops_env binary dir
291+
# Note: The "bin" subdir is needed for Windows.
292+
temp_khiops_env_dir = os.path.join(temp_dir, "bin")
293+
os.makedirs(temp_khiops_env_dir)
294+
295+
# Create temporary khiops_env path
296+
temp_khiops_env_file_path = os.path.join(temp_khiops_env_dir, "khiops_env")
297+
298+
# On Windows, set KHIOPS_HOME to the temp dir
299+
original_khiops_home_env_var = os.environ.get("KHIOPS_HOME")
300+
if platform.system() == "Windows":
301+
os.environ["KHIOPS_HOME"] = temp_dir
302+
temp_khiops_env_file_path += ".cmd"
303+
304+
# Replace the khiops_env with a crafted one
305+
with open(
306+
temp_khiops_env_file_path, "w", encoding="utf-8"
307+
) as temp_khiops_env_file:
308+
if platform.system() == "Windows":
309+
temp_khiops_env_file.write(
310+
"echo KHIOPS_PATH /usr/bin/MODL_openmpi\r\n"
311+
)
312+
temp_khiops_env_file.write(
313+
"echo KHIOPS_COCLUSTERING_PATH "
314+
"/usr/bin/MODL_Coclustering_openmpi\r\n"
315+
)
316+
temp_khiops_env_file.write("echo KHIOPS_MPI_HOME \tmp" + "\r\n")
317+
else:
318+
temp_khiops_env_file.write("#!/bin/bash\n")
319+
temp_khiops_env_file.write(
320+
"echo KHIOPS_PATH /usr/bin/MODL_openmpi\n"
321+
)
322+
temp_khiops_env_file.write(
323+
"echo KHIOPS_COCLUSTERING_PATH "
324+
"/usr/bin/MODL_Coclustering_openmpi\n"
325+
)
326+
temp_khiops_env_file.write("echo KHIOPS_MPI_HOME /tmp\n")
327+
328+
# Make the temporary khiops_env file executable
329+
os.chmod(
330+
temp_khiops_env_file_path,
331+
os.stat(temp_khiops_env_file_path).st_mode | stat.S_IEXEC,
332+
)
333+
334+
# Store initial PATH
335+
original_path_env_var = os.environ["PATH"]
336+
337+
# Prepend path to temporary khiops_env to PATH
338+
os.environ["PATH"] = (
339+
temp_khiops_env_dir + os.pathsep + original_path_env_var
340+
)
341+
342+
_ = KhiopsLocalRunner()
343+
344+
# Check `KHIOPS_MPI_HOME` is correctly exported for OpenMPI 5+
345+
self.assertIsNotNone(os.environ.get("KHIOPS_MPI_HOME"))
346+
347+
# Restore initial PATH
348+
os.environ["PATH"] = original_path_env_var
349+
350+
# On Windows, restore initial KHIOPS_HOME
351+
if (
352+
platform.system() == "Windows"
353+
and original_khiops_home_env_var is not None
354+
):
355+
os.environ["KHIOPS_HOME"] = original_khiops_home_env_var
356+
285357
def test_runner_environment_initialization(self):
286358
"""Test that local runner initializes/ed its environment properly
287359
288360
.. note::
289361
To test a real initialization this test should be executed alone.
290362
"""
363+
291364
# Obtain the current runner
292365
runner = kh.get_runner()
293366

0 commit comments

Comments
 (0)