1 |
spiga |
1.80 |
##########################################################################
|
2 |
nsmirnov |
1.1 |
#
|
3 |
|
|
# C O N V E N I E N C E F U N C T I O N S
|
4 |
|
|
#
|
5 |
|
|
###########################################################################
|
6 |
|
|
|
7 |
slacapra |
1.12 |
import string, sys, os, time
|
8 |
slacapra |
1.16 |
import ConfigParser, re, popen2, select, fcntl
|
9 |
nsmirnov |
1.1 |
|
10 |
nsmirnov |
1.2 |
import common
|
11 |
slacapra |
1.30 |
from crab_exceptions import CrabException
|
12 |
spiga |
1.42 |
from ServerConfig import *
|
13 |
nsmirnov |
1.1 |
|
14 |
|
|
###########################################################################
|
15 |
|
|
def parseOptions(argv):
|
16 |
|
|
"""
|
17 |
|
|
Parses command-line options.
|
18 |
|
|
Returns a dictionary with specified options as keys:
|
19 |
|
|
-opt1 --> 'opt1' : None
|
20 |
|
|
-opt2 val --> 'opt2' : 'val'
|
21 |
|
|
-opt3=val --> 'opt3' : 'val'
|
22 |
|
|
Usually called as
|
23 |
|
|
options = parseOptions(sys.argv[1:])
|
24 |
|
|
"""
|
25 |
|
|
options = {}
|
26 |
|
|
argc = len(argv)
|
27 |
|
|
i = 0
|
28 |
|
|
while ( i < argc ):
|
29 |
|
|
if argv[i][0] != '-':
|
30 |
|
|
i = i + 1
|
31 |
|
|
continue
|
32 |
|
|
eq = string.find(argv[i], '=')
|
33 |
|
|
if eq > 0 :
|
34 |
|
|
opt = argv[i][:eq]
|
35 |
|
|
val = argv[i][eq+1:]
|
36 |
|
|
pass
|
37 |
|
|
else:
|
38 |
|
|
opt = argv[i]
|
39 |
|
|
val = None
|
40 |
|
|
if ( i+1 < argc and argv[i+1][0] != '-' ):
|
41 |
|
|
i = i + 1
|
42 |
|
|
val = argv[i]
|
43 |
|
|
pass
|
44 |
|
|
pass
|
45 |
|
|
options[opt] = val
|
46 |
|
|
i = i + 1
|
47 |
|
|
pass
|
48 |
|
|
return options
|
49 |
|
|
|
50 |
slacapra |
1.47 |
def loadConfig(file, config):
|
51 |
nsmirnov |
1.1 |
"""
|
52 |
|
|
returns a dictionary with keys of the form
|
53 |
|
|
<section>.<option> and the corresponding values
|
54 |
|
|
"""
|
55 |
slacapra |
1.47 |
#config={}
|
56 |
nsmirnov |
1.1 |
cp = ConfigParser.ConfigParser()
|
57 |
|
|
cp.read(file)
|
58 |
|
|
for sec in cp.sections():
|
59 |
|
|
for opt in cp.options(sec):
|
60 |
spiga |
1.79 |
## temporary check. Allow compatibility
|
61 |
|
|
new_sec = sec
|
62 |
|
|
if sec == 'EDG':
|
63 |
spiga |
1.80 |
print ('\tWARNING: The [EDG] section is now deprecated.\n\tPlease remove it and use [GRID] instead.\n')
|
64 |
spiga |
1.79 |
new_sec = 'GRID'
|
65 |
|
|
config[new_sec+'.'+opt] = string.strip(cp.get(sec,opt))
|
66 |
nsmirnov |
1.1 |
return config
|
67 |
|
|
|
68 |
|
|
###########################################################################
|
69 |
|
|
def isInt(str):
|
70 |
|
|
""" Is the given string an integer ?"""
|
71 |
|
|
try: int(str)
|
72 |
|
|
except ValueError: return 0
|
73 |
|
|
return 1
|
74 |
|
|
|
75 |
|
|
###########################################################################
|
76 |
|
|
def isBool(str):
|
77 |
|
|
""" Is the given string 0 or 1 ?"""
|
78 |
|
|
if (str in ('0','1')): return 1
|
79 |
|
|
return 0
|
80 |
|
|
|
81 |
|
|
###########################################################################
|
82 |
nsmirnov |
1.3 |
def parseRange(range):
|
83 |
|
|
"""
|
84 |
|
|
Takes as the input a string with two integers separated by
|
85 |
|
|
the minus sign and returns the tuple with these numbers:
|
86 |
|
|
'n1-n2' -> (n1, n2)
|
87 |
|
|
'n1' -> (n1, n1)
|
88 |
|
|
"""
|
89 |
|
|
start = None
|
90 |
|
|
end = None
|
91 |
|
|
minus = string.find(range, '-')
|
92 |
|
|
if ( minus < 0 ):
|
93 |
|
|
if isInt(range):
|
94 |
|
|
start = int(range)
|
95 |
|
|
end = start
|
96 |
|
|
pass
|
97 |
|
|
pass
|
98 |
|
|
else:
|
99 |
|
|
if isInt(range[:minus]) and isInt(range[minus+1:]):
|
100 |
|
|
start = int(range[:minus])
|
101 |
|
|
end = int(range[minus+1:])
|
102 |
|
|
pass
|
103 |
|
|
pass
|
104 |
|
|
return (start, end)
|
105 |
|
|
|
106 |
|
|
###########################################################################
|
107 |
nsmirnov |
1.4 |
def parseRange2(range):
|
108 |
|
|
"""
|
109 |
|
|
Takes as the input a string in the form of a comma-separated
|
110 |
|
|
numbers and ranges
|
111 |
|
|
and returns a list with all specified numbers:
|
112 |
|
|
'n1' -> [n1]
|
113 |
|
|
'n1-n2' -> [n1, n1+1, ..., n2]
|
114 |
|
|
'n1,n2-n3,n4' -> [n1, n2, n2+1, ..., n3, n4]
|
115 |
|
|
"""
|
116 |
slacapra |
1.30 |
result = []
|
117 |
|
|
if not range: return result
|
118 |
nsmirnov |
1.4 |
|
119 |
|
|
comma = string.find(range, ',')
|
120 |
|
|
if comma == -1: left = range
|
121 |
|
|
else: left = range[:comma]
|
122 |
|
|
|
123 |
|
|
(n1, n2) = parseRange(left)
|
124 |
|
|
while ( n1 <= n2 ):
|
125 |
slacapra |
1.11 |
try:
|
126 |
slacapra |
1.30 |
result.append(n1)
|
127 |
slacapra |
1.11 |
n1 += 1
|
128 |
|
|
pass
|
129 |
|
|
except:
|
130 |
|
|
msg = 'Syntax error in range <'+range+'>'
|
131 |
|
|
raise CrabException(msg)
|
132 |
nsmirnov |
1.4 |
|
133 |
|
|
if comma != -1:
|
134 |
slacapra |
1.11 |
try:
|
135 |
slacapra |
1.30 |
result.extend(parseRange2(range[comma+1:]))
|
136 |
slacapra |
1.11 |
pass
|
137 |
|
|
except:
|
138 |
|
|
msg = 'Syntax error in range <'+range+'>'
|
139 |
|
|
raise CrabException(msg)
|
140 |
nsmirnov |
1.4 |
|
141 |
slacapra |
1.30 |
return result
|
142 |
nsmirnov |
1.4 |
|
143 |
|
|
###########################################################################
|
144 |
nsmirnov |
1.1 |
def findLastWorkDir(dir_prefix, where = None):
|
145 |
|
|
|
146 |
|
|
if not where: where = os.getcwd() + '/'
|
147 |
|
|
# dir_prefix usually has the form 'crab_0_'
|
148 |
|
|
pattern = re.compile(dir_prefix)
|
149 |
|
|
|
150 |
slacapra |
1.76 |
file_list = [f for f in os.listdir(where) if os.path.isdir(f) and pattern.match(f)]
|
151 |
nsmirnov |
1.1 |
|
152 |
|
|
if len(file_list) == 0: return None
|
153 |
|
|
|
154 |
|
|
file_list.sort()
|
155 |
|
|
|
156 |
slacapra |
1.76 |
wdir = where + file_list[-1]
|
157 |
nsmirnov |
1.1 |
return wdir
|
158 |
|
|
|
159 |
|
|
###########################################################################
|
160 |
|
|
def importName(module_name, name):
|
161 |
|
|
"""
|
162 |
|
|
Import a named object from a Python module,
|
163 |
|
|
i.e., it is an equivalent of 'from module_name import name'.
|
164 |
|
|
"""
|
165 |
|
|
module = __import__(module_name, globals(), locals(), [name])
|
166 |
|
|
return vars(module)[name]
|
167 |
|
|
|
168 |
|
|
###########################################################################
|
169 |
slacapra |
1.16 |
def readable(fd):
|
170 |
ewv |
1.44 |
return bool(select.select([fd], [], [], 0))
|
171 |
slacapra |
1.16 |
|
172 |
|
|
###########################################################################
|
173 |
|
|
def makeNonBlocking(fd):
|
174 |
|
|
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
|
175 |
|
|
try:
|
176 |
|
|
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NDELAY)
|
177 |
|
|
except AttributeError:
|
178 |
|
|
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.FNDELAY)
|
179 |
|
|
|
180 |
|
|
###########################################################################
|
181 |
slacapra |
1.11 |
def runCommand(cmd, printout=0, timeout=-1):
|
182 |
nsmirnov |
1.1 |
"""
|
183 |
|
|
Run command 'cmd'.
|
184 |
|
|
Returns command stdoutput+stderror string on success,
|
185 |
|
|
or None if an error occurred.
|
186 |
slacapra |
1.16 |
Following recipe on http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52296
|
187 |
nsmirnov |
1.1 |
"""
|
188 |
fanzago |
1.15 |
|
189 |
slacapra |
1.11 |
if printout:
|
190 |
spiga |
1.78 |
common.logger.info(cmd)
|
191 |
slacapra |
1.11 |
else:
|
192 |
spiga |
1.78 |
common.logger.log(10-1,cmd)
|
193 |
slacapra |
1.29 |
pass
|
194 |
slacapra |
1.11 |
|
195 |
slacapra |
1.16 |
child = popen2.Popen3(cmd, 1) # capture stdout and stderr from command
|
196 |
|
|
child.tochild.close() # don't need to talk to child
|
197 |
ewv |
1.44 |
outfile = child.fromchild
|
198 |
slacapra |
1.16 |
outfd = outfile.fileno()
|
199 |
|
|
errfile = child.childerr
|
200 |
|
|
errfd = errfile.fileno()
|
201 |
|
|
makeNonBlocking(outfd) # don't deadlock!
|
202 |
|
|
makeNonBlocking(errfd)
|
203 |
|
|
outdata = []
|
204 |
|
|
errdata = []
|
205 |
|
|
outeof = erreof = 0
|
206 |
|
|
|
207 |
|
|
if timeout > 0 :
|
208 |
|
|
maxwaittime = time.time() + timeout
|
209 |
|
|
|
210 |
|
|
err = -1
|
211 |
|
|
while (timeout == -1 or time.time() < maxwaittime):
|
212 |
|
|
ready = select.select([outfd,errfd],[],[]) # wait for input
|
213 |
|
|
if outfd in ready[0]:
|
214 |
|
|
outchunk = outfile.read()
|
215 |
|
|
if outchunk == '': outeof = 1
|
216 |
|
|
outdata.append(outchunk)
|
217 |
|
|
if errfd in ready[0]:
|
218 |
|
|
errchunk = errfile.read()
|
219 |
|
|
if errchunk == '': erreof = 1
|
220 |
|
|
errdata.append(errchunk)
|
221 |
|
|
if outeof and erreof:
|
222 |
|
|
err = child.wait()
|
223 |
|
|
break
|
224 |
slacapra |
1.21 |
select.select([],[],[],.01) # give a little time for buffers to fill
|
225 |
slacapra |
1.16 |
if err == -1:
|
226 |
|
|
# kill the pid
|
227 |
spiga |
1.78 |
common.logger.info('killing process '+(cmd)+' with timeout '+str(timeout))
|
228 |
slacapra |
1.16 |
os.kill (child.pid, 9)
|
229 |
slacapra |
1.11 |
err = child.wait()
|
230 |
slacapra |
1.16 |
|
231 |
fanzago |
1.17 |
cmd_out = string.join(outdata,"")
|
232 |
|
|
cmd_err = string.join(errdata,"")
|
233 |
|
|
|
234 |
slacapra |
1.11 |
if err:
|
235 |
spiga |
1.78 |
common.logger.info('`'+cmd+'`\n failed with exit code '
|
236 |
slacapra |
1.11 |
+`err`+'='+`(err&0xff)`+'(signal)+'
|
237 |
|
|
+`(err>>8)`+'(status)')
|
238 |
spiga |
1.78 |
common.logger.info(cmd_out)
|
239 |
|
|
common.logger.info(cmd_err)
|
240 |
nsmirnov |
1.1 |
return None
|
241 |
|
|
|
242 |
fanzago |
1.17 |
# cmd_out = string.join(outdata,"")
|
243 |
|
|
# cmd_err = string.join(errdata,"")
|
244 |
nsmirnov |
1.1 |
cmd_out = cmd_out + cmd_err
|
245 |
slacapra |
1.11 |
if printout:
|
246 |
spiga |
1.78 |
common.logger.info(cmd_out)
|
247 |
slacapra |
1.11 |
else:
|
248 |
spiga |
1.78 |
common.logger.log(10-1,cmd_out)
|
249 |
slacapra |
1.29 |
pass
|
250 |
slacapra |
1.16 |
#print "<"+cmd_out+">"
|
251 |
nsmirnov |
1.1 |
return cmd_out
|
252 |
nsmirnov |
1.4 |
|
253 |
slacapra |
1.11 |
####################################
|
254 |
gutsche |
1.20 |
def makeCksum(filename) :
|
255 |
|
|
"""
|
256 |
ewv |
1.44 |
make check sum using filename and content of file
|
257 |
gutsche |
1.20 |
"""
|
258 |
|
|
|
259 |
ewv |
1.44 |
from zlib import crc32
|
260 |
|
|
hashString = filename
|
261 |
gutsche |
1.20 |
|
262 |
ewv |
1.44 |
inFile = open(filename, 'r')
|
263 |
|
|
hashString += inFile.read()
|
264 |
|
|
inFile.close()
|
265 |
gutsche |
1.20 |
|
266 |
ewv |
1.44 |
cksum = str(crc32(hashString))
|
267 |
gutsche |
1.20 |
return cksum
|
268 |
|
|
|
269 |
ewv |
1.52 |
|
270 |
gutsche |
1.32 |
def spanRanges(jobArray):
|
271 |
|
|
"""
|
272 |
|
|
take array of job numbers and concatenate 1,2,3 to 1-3
|
273 |
|
|
return string
|
274 |
|
|
"""
|
275 |
|
|
|
276 |
|
|
output = ""
|
277 |
mcinquil |
1.35 |
jobArray.sort()
|
278 |
ewv |
1.44 |
|
279 |
gutsche |
1.32 |
previous = jobArray[0]-1
|
280 |
|
|
for job in jobArray:
|
281 |
|
|
if previous+1 == job:
|
282 |
|
|
previous = job
|
283 |
|
|
if len(output) > 0 :
|
284 |
|
|
if output[-1] != "-":
|
285 |
|
|
output += "-"
|
286 |
|
|
else :
|
287 |
|
|
output += str(previous)
|
288 |
|
|
else:
|
289 |
|
|
output += str(previous) + "," + str(job)
|
290 |
mcinquil |
1.35 |
#output += "," + str(job)
|
291 |
gutsche |
1.32 |
previous = job
|
292 |
|
|
if len(jobArray) > 1 :
|
293 |
|
|
output += str(previous)
|
294 |
|
|
|
295 |
|
|
return output
|
296 |
|
|
|
297 |
spiga |
1.40 |
def displayReport(self, header, lines, xml=''):
|
298 |
ewv |
1.44 |
|
299 |
spiga |
1.49 |
counter = 0
|
300 |
|
|
printline = ''
|
301 |
|
|
printline+= header
|
302 |
spiga |
1.87 |
msg = '\n%s'%printline
|
303 |
spiga |
1.49 |
|
304 |
|
|
for i in range(len(lines)):
|
305 |
|
|
if counter != 0 and counter%10 == 0 :
|
306 |
slacapra |
1.84 |
msg += '-------------------------------------------------------------------------------------------------------\n'
|
307 |
spiga |
1.82 |
msg+= '%s\n'%lines[i]
|
308 |
spiga |
1.49 |
counter += 1
|
309 |
|
|
if xml != '' :
|
310 |
spiga |
1.40 |
fileName = common.work_space.shareDir() + xml
|
311 |
|
|
task = common._db.getTask()
|
312 |
|
|
taskXML = common._db.serializeTask(task)
|
313 |
spiga |
1.87 |
common.logger.log(10-1, taskXML)
|
314 |
spiga |
1.40 |
f = open(fileName, 'w')
|
315 |
|
|
f.write(taskXML)
|
316 |
|
|
f.close()
|
317 |
|
|
pass
|
318 |
spiga |
1.82 |
common.logger.info(msg)
|
319 |
spiga |
1.39 |
|
320 |
spiga |
1.42 |
def CliServerParams(self):
|
321 |
slacapra |
1.45 |
"""
|
322 |
|
|
Init client-server interactions
|
323 |
|
|
"""
|
324 |
|
|
self.srvCfg = {}
|
325 |
slacapra |
1.63 |
## First I have to check if the decision has been already taken...
|
326 |
|
|
task = common._db.getTask()
|
327 |
slacapra |
1.81 |
if task['serverName']!=None and task['serverName']!="":
|
328 |
slacapra |
1.63 |
self.cfg_params['CRAB.server_name']=task['serverName']
|
329 |
slacapra |
1.81 |
|
330 |
|
|
if self.cfg_params.has_key('CRAB.server_name'):
|
331 |
|
|
self.srvCfg = ServerConfig(self.cfg_params['CRAB.server_name']).config()
|
332 |
|
|
elif self.cfg_params.has_key('CRAB.use_server'):
|
333 |
slacapra |
1.77 |
serverName=self.cfg_params.get('CRAB.server_name','default')
|
334 |
slacapra |
1.62 |
if self.cfg_params.has_key('CRAB.server_name'):
|
335 |
|
|
serverName=self.cfg_params['CRAB.server_name']
|
336 |
|
|
else:
|
337 |
|
|
serverName='default'
|
338 |
|
|
self.srvCfg = ServerConfig(serverName).config()
|
339 |
slacapra |
1.61 |
else:
|
340 |
|
|
msg = 'No server selected or port specified.\n'
|
341 |
|
|
msg += 'Please specify a server in the crab cfg file'
|
342 |
|
|
raise CrabException(msg)
|
343 |
|
|
return
|
344 |
slacapra |
1.81 |
# save the serverName for future use
|
345 |
|
|
opsToBeSaved={}
|
346 |
|
|
opsToBeSaved['serverName']=self.srvCfg['serverGenericName']
|
347 |
|
|
common._db.updateTask_(opsToBeSaved)
|
348 |
slacapra |
1.45 |
|
349 |
slacapra |
1.61 |
self.server_admin = str(self.srvCfg['serverAdmin'])
|
350 |
|
|
self.server_dn = str(self.srvCfg['serverDN'])
|
351 |
spiga |
1.58 |
|
352 |
slacapra |
1.61 |
self.server_name = str(self.srvCfg['serverName'])
|
353 |
|
|
self.server_port = int(self.srvCfg['serverPort'])
|
354 |
slacapra |
1.45 |
|
355 |
slacapra |
1.61 |
self.storage_name = str(self.srvCfg['storageName'])
|
356 |
|
|
self.storage_path = str(self.srvCfg['storagePath'])
|
357 |
|
|
self.storage_proto = str(self.srvCfg['storageProtocol'])
|
358 |
|
|
self.storage_port = str(self.srvCfg['storagePort'])
|
359 |
spiga |
1.39 |
|
360 |
ewv |
1.44 |
def bulkControl(self,list):
|
361 |
slacapra |
1.45 |
"""
|
362 |
|
|
Check the BULK size and reduce collection ...if needed
|
363 |
|
|
"""
|
364 |
|
|
max_size = 400
|
365 |
|
|
sub_bulk = []
|
366 |
|
|
if len(list) > int(max_size):
|
367 |
|
|
n_sub_bulk = int( int(len(list) ) / int(max_size) )
|
368 |
mcinquil |
1.53 |
for n in xrange(n_sub_bulk):
|
369 |
slacapra |
1.45 |
first =n*int(max_size)
|
370 |
|
|
last = (n+1)*int(max_size)
|
371 |
|
|
sub_bulk.append(list[first:last])
|
372 |
|
|
if len(list[last:-1]) < 50:
|
373 |
|
|
for pp in list[last:-1]:
|
374 |
|
|
sub_bulk[n_sub_bulk-1].append(pp)
|
375 |
spiga |
1.43 |
else:
|
376 |
mcinquil |
1.53 |
sub_bulk.append(list[last:])
|
377 |
slacapra |
1.45 |
else:
|
378 |
|
|
sub_bulk.append(list)
|
379 |
|
|
|
380 |
|
|
return sub_bulk
|
381 |
spiga |
1.66 |
###########################################################################
|
382 |
slacapra |
1.45 |
|
383 |
spiga |
1.69 |
def getUserName():
|
384 |
spiga |
1.66 |
"""
|
385 |
|
|
extract user name from either SiteDB or Unix
|
386 |
|
|
"""
|
387 |
|
|
if common.scheduler.name().upper() in ['LSF', 'CAF']:
|
388 |
spiga |
1.78 |
common.logger.log(10-1,"Using as username the Unix user name")
|
389 |
spiga |
1.70 |
UserName=UnixUserName()
|
390 |
spiga |
1.66 |
else :
|
391 |
spiga |
1.74 |
UserName=gethnUserNameFromSiteDB()
|
392 |
spiga |
1.66 |
|
393 |
|
|
return UserName
|
394 |
spiga |
1.58 |
|
395 |
spiga |
1.69 |
def UnixUserName():
|
396 |
spiga |
1.58 |
"""
|
397 |
|
|
extract username from whoami
|
398 |
|
|
"""
|
399 |
|
|
try:
|
400 |
|
|
UserName = runCommand("whoami")
|
401 |
|
|
UserName = string.strip(UserName)
|
402 |
|
|
except:
|
403 |
|
|
msg = "Error. Problem with whoami command"
|
404 |
|
|
raise CrabException(msg)
|
405 |
|
|
return UserName
|
406 |
spiga |
1.66 |
|
407 |
spiga |
1.69 |
def getDN():
|
408 |
spiga |
1.66 |
"""
|
409 |
|
|
extract DN from user proxy's identity
|
410 |
|
|
"""
|
411 |
|
|
try:
|
412 |
|
|
userdn = runCommand("voms-proxy-info -identity")
|
413 |
|
|
userdn = string.strip(userdn)
|
414 |
|
|
#search for a / to avoid picking up warning messages
|
415 |
|
|
userdn = userdn[userdn.find('/'):]
|
416 |
|
|
except:
|
417 |
|
|
msg = "Error. Problem with voms-proxy-info -identity command"
|
418 |
|
|
raise CrabException(msg)
|
419 |
|
|
return userdn.split('\n')[0]
|
420 |
|
|
|
421 |
spiga |
1.69 |
def gethnUserNameFromSiteDB():
|
422 |
spiga |
1.66 |
"""
|
423 |
|
|
extract user name from SiteDB
|
424 |
|
|
"""
|
425 |
|
|
from WMCore.Services.SiteDB.SiteDB import SiteDBJSON
|
426 |
|
|
hnUserName = None
|
427 |
spiga |
1.69 |
userdn = getDN()
|
428 |
spiga |
1.78 |
dict={ 'cacheduration' : 24, \
|
429 |
slacapra |
1.83 |
'logger' : common.logger() }
|
430 |
spiga |
1.75 |
mySiteDB = SiteDBJSON(dict)
|
431 |
spiga |
1.73 |
msg_ = "there is no user name associated to DN %s in SiteDB. You need to register in SiteDB with the instructions at https://twiki.cern.ch/twiki/bin/view/CMS/SiteDBForCRAB" % userdn
|
432 |
spiga |
1.66 |
try:
|
433 |
|
|
hnUserName = mySiteDB.dnUserName(dn=userdn)
|
434 |
|
|
except:
|
435 |
|
|
msg = "Error. Problem extracting user name from SiteDB"
|
436 |
spiga |
1.73 |
msg += "\n Check that you are registered in SiteDB, see https://twiki.cern.ch/twiki/bin/view/CMS/SiteDBForCRAB\n"
|
437 |
|
|
msg += 'or %s'%msg_
|
438 |
spiga |
1.66 |
raise CrabException(msg)
|
439 |
|
|
if not hnUserName:
|
440 |
spiga |
1.73 |
msg = "Error. %s"%msg_
|
441 |
spiga |
1.66 |
raise CrabException(msg)
|
442 |
|
|
return hnUserName
|
443 |
|
|
|
444 |
|
|
###################################################################33
|
445 |
|
|
|
446 |
slacapra |
1.45 |
def numberFile(file, txt):
|
447 |
|
|
"""
|
448 |
|
|
append _'txt' before last extension of a file
|
449 |
|
|
"""
|
450 |
|
|
txt=str(txt)
|
451 |
|
|
p = string.split(file,".")
|
452 |
|
|
# take away last extension
|
453 |
|
|
name = p[0]
|
454 |
|
|
for x in p[1:-1]:
|
455 |
|
|
name=name+"."+x
|
456 |
|
|
# add "_txt"
|
457 |
|
|
if len(p)>1:
|
458 |
|
|
ext = p[len(p)-1]
|
459 |
|
|
result = name + '_' + txt + "." + ext
|
460 |
|
|
else:
|
461 |
|
|
result = name + '_' + txt
|
462 |
spiga |
1.43 |
|
463 |
slacapra |
1.45 |
return result
|
464 |
spiga |
1.46 |
|
465 |
|
|
def readTXTfile(self,inFileName):
|
466 |
|
|
"""
|
467 |
|
|
read file and return a list with the content
|
468 |
|
|
"""
|
469 |
|
|
out_list=[]
|
470 |
|
|
if os.path.exists(inFileName):
|
471 |
|
|
f = open(inFileName, 'r')
|
472 |
|
|
for line in f.readlines():
|
473 |
ewv |
1.52 |
out_list.append(string.strip(line))
|
474 |
spiga |
1.46 |
f.close()
|
475 |
|
|
else:
|
476 |
|
|
msg = ' file '+str(inFileName)+' not found.'
|
477 |
ewv |
1.52 |
raise CrabException(msg)
|
478 |
spiga |
1.46 |
return out_list
|
479 |
|
|
|
480 |
|
|
def writeTXTfile(self, outFileName, args):
|
481 |
|
|
"""
|
482 |
|
|
write a file with the given content ( args )
|
483 |
|
|
"""
|
484 |
|
|
outFile = open(outFileName,"a")
|
485 |
|
|
outFile.write(str(args))
|
486 |
|
|
outFile.close()
|
487 |
|
|
return
|
488 |
|
|
|
489 |
spiga |
1.54 |
def readableList(self,rawList):
|
490 |
ewv |
1.64 |
"""
|
491 |
|
|
Turn a list of numbers into a string like 1-5,7,9,12-20
|
492 |
|
|
"""
|
493 |
|
|
if not rawList:
|
494 |
|
|
return ''
|
495 |
|
|
|
496 |
slacapra |
1.56 |
listString = str(rawList[0])
|
497 |
|
|
endRange = ''
|
498 |
|
|
for i in range(1,len(rawList)):
|
499 |
|
|
if rawList[i] == rawList[i-1]+1:
|
500 |
|
|
endRange = str(rawList[i])
|
501 |
|
|
else:
|
502 |
|
|
if endRange:
|
503 |
|
|
listString += '-' + endRange + ',' + str(rawList[i])
|
504 |
|
|
endRange = ''
|
505 |
|
|
else:
|
506 |
|
|
listString += ',' + str(rawList[i])
|
507 |
|
|
if endRange:
|
508 |
|
|
listString += '-' + endRange
|
509 |
|
|
endRange = ''
|
510 |
ewv |
1.64 |
|
511 |
slacapra |
1.56 |
return listString
|
512 |
spiga |
1.54 |
|
513 |
spiga |
1.51 |
def getLocalDomain(self):
|
514 |
ewv |
1.52 |
"""
|
515 |
slacapra |
1.56 |
Get local domain name
|
516 |
ewv |
1.52 |
"""
|
517 |
spiga |
1.51 |
import socket
|
518 |
slacapra |
1.88 |
tmp=socket.getfqdn()
|
519 |
spiga |
1.51 |
dot=string.find(tmp,'.')
|
520 |
|
|
if (dot==-1):
|
521 |
|
|
msg='Unkown domain name. Cannot use local scheduler'
|
522 |
|
|
raise CrabException(msg)
|
523 |
|
|
localDomainName = string.split(tmp,'.',1)[-1]
|
524 |
ewv |
1.52 |
return localDomainName
|
525 |
spiga |
1.51 |
|
526 |
slacapra |
1.56 |
#######################################################
|
527 |
|
|
# Brian Bockelman bbockelm@cse.unl.edu
|
528 |
|
|
# Module to check the avaialble disk space on a specified directory.
|
529 |
|
|
#
|
530 |
|
|
import os
|
531 |
|
|
import statvfs
|
532 |
|
|
|
533 |
|
|
def has_freespace(dir_name, needed_space_kilobytes):
|
534 |
|
|
enough_unix_quota = False
|
535 |
|
|
enough_quota = False
|
536 |
|
|
enough_partition = False
|
537 |
|
|
enough_mount = False
|
538 |
|
|
try:
|
539 |
|
|
enough_mount = check_mount(dir_name, need_space_kilobytes)
|
540 |
|
|
except:
|
541 |
|
|
enough_mount = True
|
542 |
|
|
try:
|
543 |
|
|
enough_quota = check_quota(dir_name, needed_space_kilobytes)
|
544 |
|
|
except:
|
545 |
|
|
raise
|
546 |
|
|
enough_quota = True
|
547 |
|
|
try:
|
548 |
|
|
enough_partition = check_partition(dir_name,
|
549 |
|
|
needed_space_kilobytes)
|
550 |
|
|
except:
|
551 |
|
|
enough_partition = True
|
552 |
|
|
try:
|
553 |
|
|
enough_unix_quota = check_unix_quota(dir_name,
|
554 |
|
|
needed_space_kilobytes)
|
555 |
|
|
except:
|
556 |
|
|
enough_unix_quota = True
|
557 |
|
|
return enough_mount and enough_quota and enough_partition \
|
558 |
|
|
and enough_unix_quota
|
559 |
|
|
|
560 |
|
|
def check_mount(dir_name, needed_space_kilobytes):
|
561 |
|
|
try:
|
562 |
|
|
vfs = os.statvfs(dir_name)
|
563 |
|
|
except:
|
564 |
|
|
raise Exception("Unable to query VFS for %s." % dir_name)
|
565 |
|
|
dev_free = vfs[statvfs.F_FRSIZE] * vfs[statvfs.F_BAVAIL]
|
566 |
|
|
return dev_free/1024 > needed_space_kilobytes
|
567 |
|
|
|
568 |
|
|
def check_quota(dir_name, needed_space_kilobytes):
|
569 |
|
|
_, fd, _ = os.popen3("/usr/bin/fs lq %s" % dir_name)
|
570 |
|
|
results = fd.read()
|
571 |
|
|
if fd.close():
|
572 |
|
|
raise Exception("Unable to query the file system quota!")
|
573 |
|
|
try:
|
574 |
|
|
results = results.split('\n')[1].split()
|
575 |
|
|
quota, used = results[1:3]
|
576 |
|
|
avail = int(quota) - int(used)
|
577 |
|
|
return avail > needed_space_kilobytes
|
578 |
|
|
except:
|
579 |
|
|
return Exception("Unable to parse AFS output.")
|
580 |
|
|
|
581 |
|
|
def check_partition(dir_name, needed_space_kilobytes):
|
582 |
|
|
_, fd, _ = os.popen3("/usr/bin/fs diskfree %s" % dir_name)
|
583 |
|
|
results = fd.read()
|
584 |
|
|
if fd.close():
|
585 |
|
|
raise Exception("Unable to query the file system quota!")
|
586 |
|
|
try:
|
587 |
|
|
results = results.split('\n')[1].split()
|
588 |
|
|
avail = results[3]
|
589 |
|
|
return int(avail) > needed_space_kilobytes
|
590 |
|
|
except:
|
591 |
|
|
raise Exception("Unable to parse AFS output.")
|
592 |
|
|
|
593 |
|
|
def check_unix_quota(dir_name, needed_space_kilobytes):
|
594 |
|
|
_, fd, _ = os.popen3("df %s" % dir_name)
|
595 |
|
|
results = fd.read()
|
596 |
|
|
if fd.close():
|
597 |
|
|
raise Exception("Unable to query the filesystem with df.")
|
598 |
|
|
fs = results.split('\n')[1].split()[0]
|
599 |
|
|
_, fd, _ = os.popen3("quota -Q -u -g")
|
600 |
|
|
results = fd.read()
|
601 |
|
|
if fd.close():
|
602 |
|
|
raise Exception("Unable to query the quotas.")
|
603 |
|
|
has_info = False
|
604 |
|
|
for line in results.splitlines():
|
605 |
|
|
info = line.split()
|
606 |
|
|
if info[0] in ['Filesystem', 'Disk']:
|
607 |
|
|
continue
|
608 |
|
|
if len(info) == 1:
|
609 |
|
|
filesystem = info[0]
|
610 |
|
|
has_info = False
|
611 |
|
|
if len(info) == 6:
|
612 |
|
|
used, limit = info[0], info[2]
|
613 |
|
|
has_info = True
|
614 |
|
|
if len(info) == 7:
|
615 |
|
|
filesystem, used, limit = info[0], info[1], info[3]
|
616 |
|
|
has_info = True
|
617 |
|
|
if has_info:
|
618 |
|
|
if filesystem != fs:
|
619 |
|
|
continue
|
620 |
|
|
avail = int(limit) - int(used)
|
621 |
|
|
if avail < needed_space_kilobytes:
|
622 |
|
|
return False
|
623 |
|
|
return True
|
624 |
spiga |
1.54 |
|
625 |
slacapra |
1.57 |
def getGZSize(gzipfile):
|
626 |
|
|
# return the uncompressed size of a gzipped file
|
627 |
|
|
import struct
|
628 |
|
|
f = open(gzipfile, "rb")
|
629 |
|
|
if f.read(2) != "\x1f\x8b":
|
630 |
|
|
raise IOError("not a gzip file")
|
631 |
|
|
f.seek(-4, 2)
|
632 |
ewv |
1.64 |
return struct.unpack("<i", f.read())[0]
|
633 |
slacapra |
1.57 |
|
634 |
spiga |
1.60 |
def showWebMon(server_name):
|
635 |
spiga |
1.72 |
taskName = common._db.queryTask('name')
|
636 |
spiga |
1.60 |
msg = ''
|
637 |
spiga |
1.71 |
msg +='You can also follow the status of this task on :\n'
|
638 |
spiga |
1.72 |
msg +='\tCMS Dashboard: http://dashb-cms-job-task.cern.ch/taskmon.html#task=%s\n'%(taskName)
|
639 |
ewv |
1.64 |
if server_name != '' :
|
640 |
spiga |
1.71 |
msg += '\tServer page: http://%s:8888/logginfo\n'%server_name
|
641 |
spiga |
1.72 |
msg += '\tYour task name is: %s \n'%taskName
|
642 |
spiga |
1.60 |
return msg
|
643 |
|
|
|
644 |
slacapra |
1.86 |
def SE2CMS(dests):
|
645 |
slacapra |
1.85 |
"""
|
646 |
|
|
Trasnsform a list of SE grid name into a list SE according to CMS naming convention
|
647 |
|
|
input: array of SE grid names
|
648 |
|
|
output: array of SE CMS names
|
649 |
|
|
"""
|
650 |
|
|
from ProdCommon.SiteDB.CmsSiteMapper import SECmsMap
|
651 |
|
|
se_cms = SECmsMap()
|
652 |
|
|
SEDestination = [se_cms[d] for d in dests]
|
653 |
|
|
return SEDestination
|
654 |
spiga |
1.60 |
|
655 |
slacapra |
1.86 |
def CE2CMS(dests):
|
656 |
|
|
"""
|
657 |
|
|
Trasnsform a list of CE grid name into a list SE according to CMS naming convention
|
658 |
|
|
input: array of CE grid names
|
659 |
|
|
output: array of CE CMS names
|
660 |
|
|
"""
|
661 |
|
|
from ProdCommon.SiteDB.CmsSiteMapper import CECmsMap
|
662 |
|
|
ce_cms = CECmsMap()
|
663 |
|
|
CEDestination = [ce_cms[d] for d in dests]
|
664 |
|
|
return CEDestination
|
665 |
|
|
|
666 |
gutsche |
1.20 |
####################################
|
667 |
nsmirnov |
1.4 |
if __name__ == '__main__':
|
668 |
|
|
print 'sys.argv[1] =',sys.argv[1]
|
669 |
|
|
list = parseRange2(sys.argv[1])
|
670 |
|
|
print list
|
671 |
slacapra |
1.29 |
cksum = makeCksum("crab_util.py")
|
672 |
|
|
print cksum
|
673 |
ewv |
1.44 |
|