From 0a4901a15790e34899f101f2fa75958242db0fd1 Mon Sep 17 00:00:00 2001 From: "Marcel R." Date: Sat, 11 Jan 2025 11:02:28 +0100 Subject: [PATCH] [cms] Update to new crab changes. --- law.cfg.example | 2 +- law/contrib/cms/config.py | 2 +- law/contrib/cms/job.py | 4 ++-- law/contrib/cms/sandbox.py | 13 +++++++++---- law/contrib/cms/scripts/delegate_myproxy.py | 7 ++++++- law/contrib/cms/scripts/setup_cmssw.sh | 17 +++++++++++++++++ law/contrib/cms/workflow.py | 17 ++++++++++------- law/contrib/wlcg/util.py | 14 +++++++++++--- 8 files changed, 57 insertions(+), 19 deletions(-) diff --git a/law.cfg.example b/law.cfg.example index 27b0df89..a502e9f3 100644 --- a/law.cfg.example +++ b/law.cfg.example @@ -951,7 +951,7 @@ ; "dir", a custom install directory, "arch", a custom scram architecture, and "cores", the number of ; CPU cores to use for installation. ; Type: string -; Default: CMSSW_10_6_30 +; Default: CMSSW_14_2_1::arch=el9_amd64_gcc12 ; crab_password_file ; Description: A file containing the X509 certificate password for automatic proxy delegations by diff --git a/law/contrib/cms/config.py b/law/contrib/cms/config.py index f360ff58..e2ee5aab 100644 --- a/law/contrib/cms/config.py +++ b/law/contrib/cms/config.py @@ -11,7 +11,7 @@ def config_defaults(default_config): "crab_job_file_dir": None, "crab_job_file_dir_cleanup": False, "crab_job_file_dir_mkdtemp": None, - "crab_sandbox_name": "CMSSW_14_0_0::arch=el9_amd64_gcc12", + "crab_sandbox_name": "CMSSW_14_2_1::arch=el9_amd64_gcc12", "crab_password_file": None, }, "cmssw_sandbox": { diff --git a/law/contrib/cms/job.py b/law/contrib/cms/job.py index b9b41b57..8fbb56d1 100644 --- a/law/contrib/cms/job.py +++ b/law/contrib/cms/job.py @@ -286,7 +286,7 @@ def query(self, proj_dir, job_ids=None, proxy=None, instance=None, myproxy_usern # run it logger.debug("query crab job(s) with command '{}'".format(cmd)) code, out, _ = interruptable_popen(cmd, shell=True, executable="/bin/bash", - stdout=subprocess.PIPE, env=self.cmssw_env) + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=self.cmssw_env) # handle errors if code != 0: @@ -358,6 +358,7 @@ def extra(job_id, job_data=None): "HOLDING on command SUBMIT", "NEW on command SUBMIT", "QUEUED on command SUBMIT", + "WAITING on command SUBMIT", "SUBMITTED", ] if server_status not in accepted_server_states: @@ -585,7 +586,6 @@ def __init__(self, file_name="crab_job.py", executable=None, arguments=None, wor ("scriptExe", no_value), ("maxMemoryMB", 2048), ("allowUndistributedCMSSW", True), - ("sendPythonFolder", False), ("disableAutomaticOutputCollection", True), ("inputFiles", no_value), ("outputFiles", no_value), diff --git a/law/contrib/cms/sandbox.py b/law/contrib/cms/sandbox.py index 0a743fe9..61b191db 100644 --- a/law/contrib/cms/sandbox.py +++ b/law/contrib/cms/sandbox.py @@ -22,8 +22,8 @@ class CMSSWSandboxVariables(SandboxVariables): - fields = ("version", "setup", "args", "dir", "arch", "cores") - eq_fields = ("name", "version", "setup", "args", "dir", "arch") + fields = ("version", "setup", "args", "dir", "arch", "cores", "source") + eq_fields = ("name", "version", "setup", "args", "dir", "arch", "source") @classmethod def parse_name(cls, name): @@ -47,9 +47,13 @@ def parse_name(cls, name): if "cores" in values: values["cores"] = int(values["cores"]) + if "source" in values: + values["source"] = expand(values["source"]) + return values - def __init__(self, name, version, setup=None, args=None, dir=None, arch=None, cores=None): + def __init__(self, name, version, setup=None, args=None, dir=None, arch=None, cores=None, + source=None): super(CMSSWSandboxVariables, self).__init__(name) self.version = version @@ -58,6 +62,7 @@ def __init__(self, name, version, setup=None, args=None, dir=None, arch=None, co self.dir = dir self.arch = arch self.cores = cores + self.source = source class CMSSWSandbox(BashSandbox): @@ -100,7 +105,7 @@ def env_cache_key(self): # use version, setup, args, dir and arch as cache key return tuple( getattr(self.variables, attr) - for attr in ("version", "setup", "args", "dir", "arch") + for attr in CMSSWSandboxVariables.eq_fields[1:] ) @property diff --git a/law/contrib/cms/scripts/delegate_myproxy.py b/law/contrib/cms/scripts/delegate_myproxy.py index 260e595a..dfe3b623 100755 --- a/law/contrib/cms/scripts/delegate_myproxy.py +++ b/law/contrib/cms/scripts/delegate_myproxy.py @@ -97,4 +97,9 @@ def main(): # entry hook if __name__ == "__main__": - main() + import sys + + exit_code = main() + + if isinstance(exit_code, int): + sys.exit(exit_code) diff --git a/law/contrib/cms/scripts/setup_cmssw.sh b/law/contrib/cms/scripts/setup_cmssw.sh index eeaf1127..34549bc1 100644 --- a/law/contrib/cms/scripts/setup_cmssw.sh +++ b/law/contrib/cms/scripts/setup_cmssw.sh @@ -17,6 +17,8 @@ # The directory in which CMSSW is installed. Defaults to $LAW_HOME/cms/cmssw. # - LAW_CMSSW_CORES: # The number of cores to use for compilation. Defaults to 1. +# - LAW_CMSSW_SOURCE: +# A path to a script that is source'd after successful installation. Optional. setup_cmssw() { local shell_is_zsh="$( [ -z "${ZSH_VERSION}" ] && echo "false" || echo "true" )" @@ -82,6 +84,7 @@ setup_cmssw() { local custom_setup_args="${LAW_CMSSW_ARGS}" local custom_install_dir="${LAW_CMSSW_DIR}" local custom_install_cores="${LAW_CMSSW_CORES:-1}" + local custom_source_script="${LAW_CMSSW_SOURCE}" # checks if [ -z "${custom_cmssw_version}" ]; then @@ -190,6 +193,20 @@ setup_cmssw() { return "9" fi + # additional source script + if [ ! -z "${custom_source_script}" ] && [ -f "${custom_source_script}" ]; then + source "${custom_source_script}" "" + local source_ret="$?" + if [ "${source_ret}" != "0" ]; then + >&2 echo "custom source script '${custom_source_script}' failed" + return "10" + fi + fi + + # patch for crab: pythonpath is incomplete so add missing fragments + local cmssw_py_past_path="$( python3 -c "import os, past; print(os.path.normpath(os.path.join(past.__file__, '../..')))" )" + [ "$?" = "0" ] && export PYTHONPATH="${PYTHONPATH}:${cmssw_py_past_path}" + # setup done return "0" } diff --git a/law/contrib/cms/workflow.py b/law/contrib/cms/workflow.py index 65fe23aa..6ab0dca8 100644 --- a/law/contrib/cms/workflow.py +++ b/law/contrib/cms/workflow.py @@ -28,6 +28,8 @@ from law.contrib.cms.job import CrabJobManager, CrabJobFileFactory from law.contrib.cms.util import renew_vomsproxy, delegate_myproxy +law.contrib.load("wlcg") + logger = get_logger(__name__) @@ -46,13 +48,15 @@ def setup_job_manager(self): cfg = Config.instance() password_file = cfg.get_expanded("job", "crab_password_file") + # determine the proxy file first + proxy_file = law.wlcg.get_vomsproxy_file() + # ensure a VOMS proxy exists if not law.wlcg.check_vomsproxy_validity(): - print("renew voms-proxy") - renew_vomsproxy(password_file=password_file) + renew_vomsproxy(proxy_file=proxy_file, password_file=password_file) # ensure that it has been delegated to the myproxy server - info = law.wlcg.get_myproxy_info(silent=True) + info = law.wlcg.get_myproxy_info(proxy_file=proxy_file, silent=True) delegate = False if not info: delegate = True @@ -70,12 +74,11 @@ def setup_job_manager(self): # actual delegation if delegate: - print("delegate to myproxy server") - myproxy_username = delegate_myproxy(password_file=password_file) + myproxy_username = delegate_myproxy(proxy_file=proxy_file, password_file=password_file) else: myproxy_username = info["username"] - return {"myproxy_username": myproxy_username} + return {"proxy": proxy_file, "myproxy_username": myproxy_username} def create_job_file_factory(self, **kwargs): return self.task.crab_create_job_file_factory(**kwargs) @@ -357,7 +360,7 @@ def crab_create_job_file_factory(self, **kwargs): return factory_cls(**kwargs) - def crab_job_config(self, config, submit_jobs): + def crab_job_config(self, config, job_num, branches): """ Hook to inject custom settings into the job *config*, which is an instance of the :py:attr:`Config` class defined inside the job manager. diff --git a/law/contrib/wlcg/util.py b/law/contrib/wlcg/util.py index ecb0d6c5..c65564f7 100644 --- a/law/contrib/wlcg/util.py +++ b/law/contrib/wlcg/util.py @@ -313,6 +313,7 @@ def delegate_myproxy( userkey=None, usercert=None, username=None, + proxy_file=None, encode_username=True, cred_lifetime=720, proxy_lifetime=168, @@ -354,7 +355,10 @@ def delegate_myproxy( usercert = get_usercert() usercert = str(usercert) if not username: - username = get_vomsproxy_identity(silent=True) or get_usercert_subject() + username = ( + get_vomsproxy_identity(proxy_file=proxy_file, silent=True) or + get_usercert_subject() + ) if encode_username: username = hashlib.sha1(username.encode("utf-8")).hexdigest() @@ -402,7 +406,8 @@ def delegate_myproxy( raise Exception("myproxy-init failed with code {}".format(code)) -def get_myproxy_info(endpoint="myproxy.cern.ch", username=None, encode_username=True, silent=False): +def get_myproxy_info(endpoint="myproxy.cern.ch", username=None, encode_username=True, + proxy_file=None, silent=False): """ Returns information about a previous myproxy delegation to a server *endpoint*. When *username* is *None*, the subject string of the certificate is used instead, and sha1 encoded if @@ -415,7 +420,10 @@ def get_myproxy_info(endpoint="myproxy.cern.ch", username=None, encode_username= """ # prepare arguments if not username: - username = get_vomsproxy_identity(silent=True) or get_usercert_subject() + username = ( + get_vomsproxy_identity(proxy_file=proxy_file, silent=True) or + get_usercert_subject() + ) if encode_username: username = hashlib.sha1(username.encode("utf-8")).hexdigest()