From e34ef92435d71970c2a95ff927ae8d42fca451e3 Mon Sep 17 00:00:00 2001 From: aldbr Date: Fri, 19 Jun 2026 17:24:28 +0200 Subject: [PATCH] fix: add skip_local_config_file variable to avoid auth errors at CERN site --- .../BatchSystems/TimeLeft/HTCondorResourceUsage.py | 11 ++++++++--- .../Computing/BatchSystems/TimeLeft/TimeLeft.py | 4 ++-- .../TimeLeft/test/Test_HTCondorResourceUsage.py | 10 ++++++++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/DIRAC/Resources/Computing/BatchSystems/TimeLeft/HTCondorResourceUsage.py b/src/DIRAC/Resources/Computing/BatchSystems/TimeLeft/HTCondorResourceUsage.py index fc83c1f4b8f..fc9cfd7107b 100644 --- a/src/DIRAC/Resources/Computing/BatchSystems/TimeLeft/HTCondorResourceUsage.py +++ b/src/DIRAC/Resources/Computing/BatchSystems/TimeLeft/HTCondorResourceUsage.py @@ -13,7 +13,7 @@ class HTCondorResourceUsage(ResourceUsage): This is the HTCondor plugin of the TimeLeft Utility. HTCondor does not provide any way to get the wallclock/cpu limit, the batch system just provides fair-sharing to users and groups: the limit depends on many parameters. - However, some Sites have introduced a MaxRuntime variable that sets a wallclock time limit to the allocations and + However, CERN has introduced a MaxRuntime variable that sets a wallclock time limit to the allocations and allow us to get an estimation of the resources usage. """ @@ -26,11 +26,16 @@ def getResourceUsage(self): # $_CONDOR_JOB_AD corresponds to the path to the .job.ad file # It contains info about the job: # - MaxRuntime: wallclock time allocated to the job - not officially supported by HTCondor, - # only present on some Sites + # only present at CERN # - CurrentTime: current time # - JobCurrentStartDate: start of the job execution cmd = f"condor_status -ads {self.info_path} -af MaxRuntime CurrentTime-JobCurrentStartDate" - result = runCommand(cmd) + # SKIP_LOCAL_CONFIG_FILE prevents condor_status from loading the local config file, which + # would otherwise trigger authentication errors at CERN. runCommand() executes without a + # shell (systemCall with shell=False), so the variable has to be passed via the environment + # rather than as a "VAR=value cmd" prefix. Merge with os.environ so PATH/CONDOR_CONFIG/etc. + # are preserved (subprocess replaces, not augments, the environment when env is given). + result = runCommand(cmd, env={**os.environ, "SKIP_LOCAL_CONFIG_FILE": "true"}) if not result["OK"]: return S_ERROR("Current batch system is not supported") diff --git a/src/DIRAC/Resources/Computing/BatchSystems/TimeLeft/TimeLeft.py b/src/DIRAC/Resources/Computing/BatchSystems/TimeLeft/TimeLeft.py index e5b5c681e00..b250cb10227 100644 --- a/src/DIRAC/Resources/Computing/BatchSystems/TimeLeft/TimeLeft.py +++ b/src/DIRAC/Resources/Computing/BatchSystems/TimeLeft/TimeLeft.py @@ -160,9 +160,9 @@ def _getBatchSystemPlugin(self): ############################################################################# -def runCommand(cmd, timeout=120): +def runCommand(cmd, timeout=120, env=None): """Wrapper around systemCall to return S_OK(stdout) or S_ERROR(message)""" - result = systemCall(timeout=timeout, cmdSeq=shlex.split(cmd)) + result = systemCall(timeout=timeout, cmdSeq=shlex.split(cmd), env=env) if not result["OK"]: return result status, stdout, stderr = result["Value"][0:3] diff --git a/src/DIRAC/Resources/Computing/BatchSystems/TimeLeft/test/Test_HTCondorResourceUsage.py b/src/DIRAC/Resources/Computing/BatchSystems/TimeLeft/test/Test_HTCondorResourceUsage.py index f481b487857..40572f50c97 100644 --- a/src/DIRAC/Resources/Computing/BatchSystems/TimeLeft/test/Test_HTCondorResourceUsage.py +++ b/src/DIRAC/Resources/Computing/BatchSystems/TimeLeft/test/Test_HTCondorResourceUsage.py @@ -1,4 +1,4 @@ -""" Test class for SGEResourceUsage utility +""" Test class for HTCondorResourceUsage utility """ import pytest @@ -13,7 +13,7 @@ def test_getResourceUsage(mocker): - mocker.patch( + runCommandMock = mocker.patch( "DIRAC.Resources.Computing.BatchSystems.TimeLeft.HTCondorResourceUsage.runCommand", side_effect=[S_OK(HTCONDOR_OUT_0), S_OK(HTCONDOR_OUT_1), S_OK(HTCONDOR_OUT_2)], ) @@ -25,6 +25,12 @@ def test_getResourceUsage(mocker): assert res["Value"]["WallClock"] == 3600 assert res["Value"]["WallClockLimit"] == 86400 + # SKIP_LOCAL_CONFIG_FILE must be passed through the environment (runCommand runs without a shell, + # so a "VAR=value cmd" prefix would not work), and it must not wipe the rest of the environment. + _, kwargs = runCommandMock.call_args + assert kwargs["env"]["SKIP_LOCAL_CONFIG_FILE"] == "true" + assert "PATH" in kwargs["env"] + # Second test: MaxRuntime is undefined htcondorResourceUsage = HTCondorResourceUsage("1234", {"Queue": "Test", "InfoPath": "/path/to/condor_ad"}) res = htcondorResourceUsage.getResourceUsage()