11""" Utilities for WMS
22"""
33import os
4+ from pathlib import Path
5+ from glob import glob
6+ import subprocess
47import sys
58import json
69
@@ -63,8 +66,6 @@ def createJobWrapper(
6366 if os .path .exists (jobWrapperFile ):
6467 log .verbose ("Removing existing Job Wrapper for" , jobID )
6568 os .remove (jobWrapperFile )
66- with open (os .path .join (diracRoot , defaultWrapperLocation )) as fd :
67- wrapperTemplate = fd .read ()
6869
6970 if "LogLevel" in jobParams :
7071 logLevel = jobParams ["LogLevel" ]
@@ -76,34 +77,43 @@ def createJobWrapper(
7677 pythonPath = os .path .realpath (sys .executable )
7778 log .debug ("Real python path after resolving links is: " , pythonPath )
7879
79- # Making real substitutions
80- sitePython = os .getcwd ()
81- if rootLocation :
82- sitePython = rootLocation
83- wrapperTemplate = wrapperTemplate .replace ("@SITEPYTHON@" , sitePython )
84-
85- jobWrapperJsonFile = jobWrapperFile + ".json"
86- with open (jobWrapperJsonFile , "w" , encoding = "utf8" ) as jsonFile :
87- json .dump (arguments , jsonFile , ensure_ascii = False )
88-
89- with open (jobWrapperFile , "w" ) as wrapper :
90- wrapper .write (wrapperTemplate )
91-
92- if not rootLocation :
93- rootLocation = wrapperPath
94-
95- # The "real" location of the jobwrapper after it is started
96- jobWrapperDirect = os .path .join (rootLocation , f"Wrapper_{ jobID } " )
97- jobExeFile = os .path .join (wrapperPath , f"Job{ jobID } " )
98- jobFileContents = """#!/bin/sh
99- {} {} {} -o LogLevel={} -o /DIRAC/Security/UseServerCertificate=no {}
100- """ .format (
101- pythonPath ,
102- jobWrapperDirect ,
103- extraOptions if extraOptions else "" ,
104- logLevel ,
105- cfgPath if cfgPath else "" ,
106- )
80+ if "Executable" in jobParams and jobParams ["Executable" ] == "dirac-cwl-exec" :
81+ ret = __createCWLJobWrapper (jobID , wrapperPath , log , rootLocation )
82+ if not ret ["OK" ]:
83+ return ret
84+ jobWrapperFile , jobWrapperJsonFile , jobExeFile , jobFileContents = ret ["Value" ]
85+ else :
86+ with open (os .path .join (diracRoot , defaultWrapperLocation )) as fd :
87+ wrapperTemplate = fd .read ()
88+
89+ # Making real substitutions
90+ sitePython = os .getcwd ()
91+ if rootLocation :
92+ sitePython = rootLocation
93+ wrapperTemplate = wrapperTemplate .replace ("@SITEPYTHON@" , sitePython )
94+
95+ jobWrapperJsonFile = jobWrapperFile + ".json"
96+ with open (jobWrapperJsonFile , "w" , encoding = "utf8" ) as jsonFile :
97+ json .dump (arguments , jsonFile , ensure_ascii = False )
98+
99+ with open (jobWrapperFile , "w" ) as wrapper :
100+ wrapper .write (wrapperTemplate )
101+
102+ if not rootLocation :
103+ rootLocation = wrapperPath
104+
105+ # The "real" location of the jobwrapper after it is started
106+ jobWrapperDirect = os .path .join (rootLocation , f"Wrapper_{ jobID } " )
107+ jobExeFile = os .path .join (wrapperPath , f"Job{ jobID } " )
108+ jobFileContents = """#!/bin/sh
109+ {} {} {} -o LogLevel={} -o /DIRAC/Security/UseServerCertificate=no {}
110+ """ .format (
111+ pythonPath ,
112+ jobWrapperDirect ,
113+ extraOptions if extraOptions else "" ,
114+ logLevel ,
115+ cfgPath if cfgPath else "" ,
116+ )
107117
108118 with open (jobExeFile , "w" ) as jobFile :
109119 jobFile .write (jobFileContents )
@@ -113,11 +123,49 @@ def createJobWrapper(
113123 "JobWrapperConfigPath" : jobWrapperJsonFile ,
114124 "JobWrapperPath" : jobWrapperFile ,
115125 }
116- if rootLocation != wrapperPath :
126+ if rootLocation and rootLocation != wrapperPath :
117127 generatedFiles ["JobExecutableRelocatedPath" ] = os .path .join (rootLocation , os .path .basename (jobExeFile ))
118128 return S_OK (generatedFiles )
119129
120130
131+ def __createCWLJobWrapper (jobID , wrapperPath , log , rootLocation ):
132+ # Get the new JobWrapper
133+ if not rootLocation :
134+ rootLocation = wrapperPath
135+ protoPath = Path (wrapperPath ) / f"proto{ jobID } "
136+ protoPath .unlink (missing_ok = True )
137+ log .info ("Cloning JobWrapper from repository https://github.com/DIRACGrid/dirac-cwl.git into" , protoPath )
138+ try :
139+ subprocess .run (["git" , "clone" , "https://github.com/DIRACGrid/dirac-cwl.git" , str (protoPath )], check = True )
140+ except subprocess .CalledProcessError :
141+ return S_ERROR ("Failed to clone the JobWrapper repository" )
142+ wrapperFound = glob (os .path .join (str (protoPath ), "**" , "job_wrapper_template.py" ), recursive = True )
143+ if len (wrapperFound ) < 1 or not Path (wrapperFound [0 ]).is_file ():
144+ return S_ERROR ("Could not find the JobWrapper in the cloned repository" )
145+ jobWrapperFile = wrapperFound [0 ]
146+ directJobWrapperFile = str (Path (rootLocation ) / Path (wrapperFound [0 ]).relative_to (wrapperPath ))
147+
148+ jobWrapperJsonFile = Path (wrapperPath ) / f"InputSandbox{ jobID } " / "job.json"
149+ directJobWrapperJsonFile = Path (rootLocation ) / f"InputSandbox{ jobID } " / "job.json"
150+ # Create the executable file
151+ jobExeFile = os .path .join (wrapperPath , f"Job{ jobID } " )
152+ protoPath = str (Path (rootLocation ) / Path (protoPath ).relative_to (wrapperPath ))
153+ pixiPath = str (Path (rootLocation ) / ".pixi" )
154+ jobFileContents = f"""#!/bin/bash
155+ # Install pixi
156+ export PIXI_NO_PATH_UPDATE=1
157+ export PIXI_HOME={ pixiPath }
158+ curl -fsSL https://pixi.sh/install.sh | bash
159+ export PATH="{ pixiPath } /bin:$PATH"
160+ pixi install --manifest-path { protoPath }
161+ # Get json
162+ dirac-wms-job-get-input { jobID } -D { rootLocation }
163+ # Run JobWrapper
164+ pixi run --manifest-path { protoPath } python { directJobWrapperFile } { directJobWrapperJsonFile }
165+ """
166+ return S_OK ((jobWrapperFile , jobWrapperJsonFile , jobExeFile , jobFileContents ))
167+
168+
121169def rescheduleJobs (
122170 jobIDs : list [int ],
123171 source : str = "" ,
0 commit comments