12 import validationfunctions
13 from validationscript
import Script
18 A class that provides the controls for running jobs on a (remote)
19 Sun Grid Engine cluster. It provides two methods:
20 - is_job_finished(job): Returns True or False, depending on whether the job
21 has finished execution
22 - execute(job): Takes a job and executes it by sending it to the cluster
28 Check if qsub is available
30 return shutil.which(
"qsub")
is not None
35 Returns name of this job contol
42 Returns description of this job control
44 return "Batch submission via command line to Grid Engine"
48 The default constructor.
49 - Holds the current working directory, which is also the location of
50 the shellscripts that are being sent to the cluster.
51 - Initializes a logger which writes to validate_basf2.py's log.
52 - Finds the revision of basf2 that will be set up on the cluster.
58 'h_fsize={requirement_storage}G '
59 '-oo {logfile} -q {queuename} -V')
81 self.
logger = logging.getLogger(
'validate_basf2')
89 belle2_release_dir = os.environ.get(
'BELLE2_RELEASE_DIR',
None)
90 belle2_local_dir = os.environ.get(
'BELLE2_LOCAL_DIR',
None)
94 if belle2_release_dir
is not None:
95 self.
b2setup +=
' ' + belle2_release_dir.split(
'/')[-1]
96 if belle2_local_dir
is not None:
97 self.
b2setup =
'MY_BELLE2_DIR=' + \
99 if os.environ.get(
'BELLE2_OPTION') !=
'debug':
100 self.
b2setup +=
'; b2code-option ' + \
101 os.environ.get(
'BELLE2_OPTION')
104 self.
logger.debug(f
'Setting up the following release: {self.b2setup}')
108 clusterlog_dir =
'./html/logs/__general__/'
109 if not os.path.exists(clusterlog_dir):
110 os.makedirs(clusterlog_dir)
113 self.
clusterlog = open(clusterlog_dir +
'clusterlog.log',
'w+')
118 This method can be used if path names are different on submission
120 @param path: The past that needs to be adjusted
121 @return: The adjusted path
129 The cluster should always be available to accept new jobs.
130 @return: Will always return True if the function can be called
135 def execute(self, job: Script, options=
'', dry=
False, tag=
'current'):
137 Takes a Script object and a string with options and runs it on the
138 cluster, either with ROOT or with basf2, depending on the file type.
140 @param job: The steering file object that should be executed
141 @param options: Options that will be given to the basf2 command
142 @param dry: Whether to perform a dry run or not
143 @param tag: The folder within the results directory
152 output_dir = os.path.abspath(f
'./results/{tag}/{job.package}')
153 if not os.path.exists(output_dir):
154 os.makedirs(output_dir)
157 log_file = output_dir +
'/' + os.path.basename(job.path) +
'.log'
160 donefile_path = f
"{self.path}/script_{job.name}.done"
161 if os.path.isfile(donefile_path):
162 os.remove(donefile_path)
165 extension = os.path.splitext(job.path)[1]
166 if extension ==
'.C':
168 command =
'root -b -q ' + job.path
173 job.path, options.split()
175 command = subprocess.list2cmdline(params)
183 tmp_name = self.
path +
'/' +
'script_' + job.name +
'.sh'
184 with open(tmp_name,
'w+')
as tmp_file:
185 tmp_file.write(
'#!/bin/bash \n\n' +
186 'BELLE2_NO_TOOLS_CHECK=1 \n' +
187 'source {0}/b2setup \n'.format(self.
tools) +
189 '{0} \n'.format(command) +
190 'echo $? > {0}/script_{1}.done \n'
191 .format(self.
path, job.name) +
192 'rm {0} \n'.format(tmp_name))
195 st = os.stat(tmp_name)
196 os.chmod(tmp_name, st.st_mode | stat.S_IEXEC)
204 ).split() + [tmp_name]
207 self.
logger.debug(subprocess.list2cmdline(params))
214 process = subprocess.Popen(params, stdout=self.
clusterlog,
215 stderr=subprocess.STDOUT)
218 if process.wait() != 0:
219 job.status =
'failed'
221 os.system(f
'echo 0 > {self.path}/script_{job.name}.done')
226 Checks whether the '.done'-file has been created for a job. If so, it
227 returns True, else it returns False.
228 Also deletes the .done-File once it has returned True.
230 @param job: The job of which we want to know if it finished
231 @return: True if the job has finished, otherwise False
235 donefile_path = f
"{self.path}/script_{job.name}.done"
239 if os.path.isfile(donefile_path):
242 with open(donefile_path)
as f:
244 returncode = int(f.read().strip())
249 os.remove(donefile_path)
252 return [
True, returncode]
261 Terminate a running job, not support with this backend so ignore the
264 self.
logger.error(
"Script termination not supported.")