ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/CRAB/python/crab_util.py
Revision: 1.50
Committed: Tue Jul 8 09:20:08 2008 UTC (16 years, 9 months ago) by spiga
Content type: text/x-python
Branch: MAIN
CVS Tags: CRAB_2_4_0_test
Changes since 1.49: +0 -1 lines
Log Message:
removed wrong print in the log file

File Contents

# User Rev Content
1 nsmirnov 1.1 ###########################################################################
2     #
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     # print 'Section',sec
60     for opt in cp.options(sec):
61     #print 'config['+sec+'.'+opt+'] = '+string.strip(cp.get(sec,opt))
62     config[sec+'.'+opt] = string.strip(cp.get(sec,opt))
63     return config
64    
65     ###########################################################################
66     def isInt(str):
67     """ Is the given string an integer ?"""
68     try: int(str)
69     except ValueError: return 0
70     return 1
71    
72     ###########################################################################
73     def isBool(str):
74     """ Is the given string 0 or 1 ?"""
75     if (str in ('0','1')): return 1
76     return 0
77    
78     ###########################################################################
79 nsmirnov 1.3 def parseRange(range):
80     """
81     Takes as the input a string with two integers separated by
82     the minus sign and returns the tuple with these numbers:
83     'n1-n2' -> (n1, n2)
84     'n1' -> (n1, n1)
85     """
86     start = None
87     end = None
88     minus = string.find(range, '-')
89     if ( minus < 0 ):
90     if isInt(range):
91     start = int(range)
92     end = start
93     pass
94     pass
95     else:
96     if isInt(range[:minus]) and isInt(range[minus+1:]):
97     start = int(range[:minus])
98     end = int(range[minus+1:])
99     pass
100     pass
101     return (start, end)
102    
103     ###########################################################################
104 nsmirnov 1.4 def parseRange2(range):
105     """
106     Takes as the input a string in the form of a comma-separated
107     numbers and ranges
108     and returns a list with all specified numbers:
109     'n1' -> [n1]
110     'n1-n2' -> [n1, n1+1, ..., n2]
111     'n1,n2-n3,n4' -> [n1, n2, n2+1, ..., n3, n4]
112     """
113 slacapra 1.30 result = []
114     if not range: return result
115 nsmirnov 1.4
116     comma = string.find(range, ',')
117     if comma == -1: left = range
118     else: left = range[:comma]
119    
120     (n1, n2) = parseRange(left)
121     while ( n1 <= n2 ):
122 slacapra 1.11 try:
123 slacapra 1.30 result.append(n1)
124 slacapra 1.11 n1 += 1
125     pass
126     except:
127     msg = 'Syntax error in range <'+range+'>'
128     raise CrabException(msg)
129 nsmirnov 1.4
130     if comma != -1:
131 slacapra 1.11 try:
132 slacapra 1.30 result.extend(parseRange2(range[comma+1:]))
133 slacapra 1.11 pass
134     except:
135     msg = 'Syntax error in range <'+range+'>'
136     raise CrabException(msg)
137 nsmirnov 1.4
138 slacapra 1.30 return result
139 nsmirnov 1.4
140     ###########################################################################
141 nsmirnov 1.3 def crabJobStatusToString(crab_status):
142     """
143     Convert one-letter crab job status into more readable string.
144     """
145 corvo 1.27 status={
146 slacapra 1.38 'C':'Created',
147     'D':'Done',
148 corvo 1.27 'H':'Hold',
149     'U':'Ready',
150     'I':'Scheduled',
151     'X':'Canceled',
152     'W':'Created',
153     'R':'Running',
154     'SC':'Checkpointed',
155     'SS':'Scheduled',
156     'SR':'Ready',
157     'RE':'Ready',
158     'SW':'Waiting',
159     'SU':'Submitted',
160     'S' :'Submitted (Boss)',
161     'UN':'Undefined',
162     'SK':'Cancelled',
163     'SD':'Done (Success)',
164     'SA':'Aborted',
165     'DA':'Done (Aborted)',
166     'SE':'Cleared',
167     'OR':'Done (Success)',
168     'A?':'Aborted',
169     'K':'Killed',
170     'E':'Cleared',
171     'Z':'Cleared (Corrupt)',
172     'NA':'Unknown',
173     'I?':'Idle',
174     'O?':'Done',
175     'R?':'Running'
176     }
177     return status[crab_status]
178 nsmirnov 1.3
179     ###########################################################################
180 nsmirnov 1.1 def findLastWorkDir(dir_prefix, where = None):
181    
182     if not where: where = os.getcwd() + '/'
183     # dir_prefix usually has the form 'crab_0_'
184     pattern = re.compile(dir_prefix)
185    
186     file_list = []
187     for fl in os.listdir(where):
188     if pattern.match(fl):
189     file_list.append(fl)
190     pass
191     pass
192    
193     if len(file_list) == 0: return None
194    
195     file_list.sort()
196    
197     wdir = where + file_list[len(file_list)-1]
198     return wdir
199    
200     ###########################################################################
201     def importName(module_name, name):
202     """
203     Import a named object from a Python module,
204     i.e., it is an equivalent of 'from module_name import name'.
205     """
206     module = __import__(module_name, globals(), locals(), [name])
207     return vars(module)[name]
208    
209 spiga 1.9
210 slacapra 1.11 ###########################################################################
211 spiga 1.28
212 slacapra 1.29 ### WARNING This Function become USELESS after Boss API implementation
213 gutsche 1.24 def runBossCommand(cmd, printout=0, timeout=3600):
214 slacapra 1.11 """
215     Cd to correct directory before running a boss command
216     """
217     cwd = os.getcwd()
218     os.chdir(common.work_space.shareDir())
219     out = runCommand(cmd, printout, timeout)
220     os.chdir(cwd)
221     return out
222 spiga 1.9
223 nsmirnov 1.1 ###########################################################################
224 slacapra 1.16 def readable(fd):
225 ewv 1.44 return bool(select.select([fd], [], [], 0))
226 slacapra 1.16
227     ###########################################################################
228     def makeNonBlocking(fd):
229     fl = fcntl.fcntl(fd, fcntl.F_GETFL)
230     try:
231     fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NDELAY)
232     except AttributeError:
233     fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.FNDELAY)
234    
235     ###########################################################################
236 slacapra 1.11 def runCommand(cmd, printout=0, timeout=-1):
237 nsmirnov 1.1 """
238     Run command 'cmd'.
239     Returns command stdoutput+stderror string on success,
240     or None if an error occurred.
241 slacapra 1.16 Following recipe on http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52296
242 nsmirnov 1.1 """
243 fanzago 1.15
244 slacapra 1.11 if printout:
245     common.logger.message(cmd)
246     else:
247 slacapra 1.13 common.logger.debug(10,cmd)
248 slacapra 1.11 common.logger.write(cmd)
249 slacapra 1.29 pass
250 slacapra 1.11
251 slacapra 1.16 child = popen2.Popen3(cmd, 1) # capture stdout and stderr from command
252     child.tochild.close() # don't need to talk to child
253 ewv 1.44 outfile = child.fromchild
254 slacapra 1.16 outfd = outfile.fileno()
255     errfile = child.childerr
256     errfd = errfile.fileno()
257     makeNonBlocking(outfd) # don't deadlock!
258     makeNonBlocking(errfd)
259     outdata = []
260     errdata = []
261     outeof = erreof = 0
262    
263     if timeout > 0 :
264     maxwaittime = time.time() + timeout
265    
266     err = -1
267     while (timeout == -1 or time.time() < maxwaittime):
268     ready = select.select([outfd,errfd],[],[]) # wait for input
269     if outfd in ready[0]:
270     outchunk = outfile.read()
271     if outchunk == '': outeof = 1
272     outdata.append(outchunk)
273     if errfd in ready[0]:
274     errchunk = errfile.read()
275     if errchunk == '': erreof = 1
276     errdata.append(errchunk)
277     if outeof and erreof:
278     err = child.wait()
279     break
280 slacapra 1.21 select.select([],[],[],.01) # give a little time for buffers to fill
281 slacapra 1.16 if err == -1:
282     # kill the pid
283 slacapra 1.18 common.logger.message('killing process '+(cmd)+' with timeout '+str(timeout))
284 slacapra 1.16 os.kill (child.pid, 9)
285 slacapra 1.11 err = child.wait()
286 slacapra 1.16
287 fanzago 1.17 cmd_out = string.join(outdata,"")
288     cmd_err = string.join(errdata,"")
289    
290 slacapra 1.11 if err:
291     common.logger.message('`'+cmd+'`\n failed with exit code '
292     +`err`+'='+`(err&0xff)`+'(signal)+'
293     +`(err>>8)`+'(status)')
294     common.logger.message(cmd_out)
295     common.logger.message(cmd_err)
296 nsmirnov 1.1 return None
297    
298 fanzago 1.17 # cmd_out = string.join(outdata,"")
299     # cmd_err = string.join(errdata,"")
300 nsmirnov 1.1 cmd_out = cmd_out + cmd_err
301 slacapra 1.11 if printout:
302     common.logger.message(cmd_out)
303     else:
304 slacapra 1.13 common.logger.debug(10,cmd_out)
305 slacapra 1.11 common.logger.write(cmd_out)
306 slacapra 1.29 pass
307 slacapra 1.16 #print "<"+cmd_out+">"
308 nsmirnov 1.1 return cmd_out
309 nsmirnov 1.4
310 slacapra 1.11 ####################################
311 gutsche 1.20 def makeCksum(filename) :
312     """
313 ewv 1.44 make check sum using filename and content of file
314 gutsche 1.20 """
315    
316 ewv 1.44 from zlib import crc32
317     hashString = filename
318 gutsche 1.20
319 ewv 1.44 inFile = open(filename, 'r')
320     hashString += inFile.read()
321     inFile.close()
322 gutsche 1.20
323 ewv 1.44 cksum = str(crc32(hashString))
324 gutsche 1.20 return cksum
325    
326 gutsche 1.32 def spanRanges(jobArray):
327     """
328     take array of job numbers and concatenate 1,2,3 to 1-3
329     return string
330     """
331    
332     output = ""
333 mcinquil 1.35 jobArray.sort()
334 ewv 1.44
335 gutsche 1.32 previous = jobArray[0]-1
336     for job in jobArray:
337     if previous+1 == job:
338     previous = job
339     if len(output) > 0 :
340     if output[-1] != "-":
341     output += "-"
342     else :
343     output += str(previous)
344     else:
345     output += str(previous) + "," + str(job)
346 mcinquil 1.35 #output += "," + str(job)
347 gutsche 1.32 previous = job
348     if len(jobArray) > 1 :
349     output += str(previous)
350    
351     return output
352    
353 spiga 1.40 def displayReport(self, header, lines, xml=''):
354 ewv 1.44
355 spiga 1.49 counter = 0
356     printline = ''
357     printline+= header
358     print printline
359     print '---------------------------------------------------------------------------------------------------'
360    
361     for i in range(len(lines)):
362     if counter != 0 and counter%10 == 0 :
363     print '---------------------------------------------------------------------------------------------------'
364     print lines[i]
365     counter += 1
366     if xml != '' :
367 spiga 1.40 fileName = common.work_space.shareDir() + xml
368     task = common._db.getTask()
369     taskXML = common._db.serializeTask(task)
370     common.logger.debug(5, taskXML)
371     f = open(fileName, 'w')
372     f.write(taskXML)
373     f.close()
374     pass
375 spiga 1.39
376 spiga 1.42 def CliServerParams(self):
377 slacapra 1.45 """
378     Init client-server interactions
379     """
380     self.srvCfg = {}
381     try:
382     self.srvCfg = ServerConfig(self.cfg_params['CRAB.server_name']).config()
383    
384     self.server_name = str(self.srvCfg['serverName'])
385     self.server_port = int(self.srvCfg['serverPort'])
386    
387     self.storage_name = str(self.srvCfg['storageName'])
388     self.storage_path = str(self.srvCfg['storagePath'])
389     self.storage_proto = str(self.srvCfg['storageProtocol'])
390     self.storage_port = str(self.srvCfg['storagePort'])
391     except KeyError:
392     msg = 'No server selected or port specified.'
393     msg = msg + 'Please specify a server in the crab cfg file'
394     raise CrabException(msg)
395 spiga 1.42 return
396 spiga 1.39
397 ewv 1.44 def bulkControl(self,list):
398 slacapra 1.45 """
399     Check the BULK size and reduce collection ...if needed
400     """
401     max_size = 400
402     sub_bulk = []
403     if len(list) > int(max_size):
404     n_sub_bulk = int( int(len(list) ) / int(max_size) )
405     for n in range(n_sub_bulk):
406     first =n*int(max_size)
407     last = (n+1)*int(max_size)
408     sub_bulk.append(list[first:last])
409     if len(list[last:-1]) < 50:
410     for pp in list[last:-1]:
411     sub_bulk[n_sub_bulk-1].append(pp)
412 spiga 1.43 else:
413 slacapra 1.45 sub_bulk.append(list[last:-1])
414     else:
415     sub_bulk.append(list)
416    
417     return sub_bulk
418    
419     def numberFile(file, txt):
420     """
421     append _'txt' before last extension of a file
422     """
423     txt=str(txt)
424     p = string.split(file,".")
425     # take away last extension
426     name = p[0]
427     for x in p[1:-1]:
428     name=name+"."+x
429     # add "_txt"
430     if len(p)>1:
431     ext = p[len(p)-1]
432     result = name + '_' + txt + "." + ext
433     else:
434     result = name + '_' + txt
435 spiga 1.43
436 slacapra 1.45 return result
437 spiga 1.46
438     def readTXTfile(self,inFileName):
439     """
440     read file and return a list with the content
441     """
442     out_list=[]
443     if os.path.exists(inFileName):
444     f = open(inFileName, 'r')
445     for line in f.readlines():
446     out_list.append(string.strip(line))
447     f.close()
448     else:
449     msg = ' file '+str(inFileName)+' not found.'
450     raise CrabException(msg)
451     return out_list
452    
453     def writeTXTfile(self, outFileName, args):
454     """
455     write a file with the given content ( args )
456     """
457     outFile = open(outFileName,"a")
458     outFile.write(str(args))
459     outFile.close()
460     return
461    
462 gutsche 1.20 ####################################
463 nsmirnov 1.4 if __name__ == '__main__':
464     print 'sys.argv[1] =',sys.argv[1]
465     list = parseRange2(sys.argv[1])
466     print list
467 slacapra 1.29 cksum = makeCksum("crab_util.py")
468     print cksum
469 ewv 1.44