1 |
#!/usr/bin/env python
|
2 |
import sys, os, time, string, shutil
|
3 |
from crab_util import *
|
4 |
from crab import *
|
5 |
import common
|
6 |
|
7 |
###########################################################################
|
8 |
class MultiCrab:
|
9 |
def __init__(self, opts):
|
10 |
self.prog_name='multicrab'
|
11 |
# Configuration file
|
12 |
self.cfg_fname = None
|
13 |
# Continuation flag
|
14 |
self.flag_continue = 0
|
15 |
self.continue_dir = None
|
16 |
self.processContinueOption_(opts)
|
17 |
|
18 |
self.processIniFile_(opts)
|
19 |
# configuration
|
20 |
self.opts=opts
|
21 |
|
22 |
if not self.flag_continue:
|
23 |
self.createWorkSpace()
|
24 |
|
25 |
print self.prog_name + ' running on ' + time.ctime(time.time())
|
26 |
print ' working directory ' + self.continue_dir
|
27 |
|
28 |
crabs=[]
|
29 |
|
30 |
def processContinueOption_(self,opts):
|
31 |
|
32 |
# Look for the '-continue' option.
|
33 |
|
34 |
for opt in opts.keys():
|
35 |
if ( opt in ('-continue','-c') ):
|
36 |
self.flag_continue = 1
|
37 |
val = opts[opt]
|
38 |
if val:
|
39 |
if val[0] == '/': self.continue_dir = val # abs path
|
40 |
else: self.continue_dir = os.getcwd() + '/' + val # rel path
|
41 |
pass
|
42 |
break
|
43 |
pass
|
44 |
|
45 |
# Look for actions which has sense only with '-continue'
|
46 |
|
47 |
if "-create" not in opts.keys() :
|
48 |
self.flag_continue = 1
|
49 |
|
50 |
if not self.flag_continue: return
|
51 |
|
52 |
if not self.continue_dir:
|
53 |
prefix = self.prog_name + '_'
|
54 |
self.continue_dir = findLastWorkDir(prefix)
|
55 |
pass
|
56 |
|
57 |
if not self.continue_dir:
|
58 |
raise CrabException('Cannot find last working directory.')
|
59 |
|
60 |
if not os.path.exists(self.continue_dir):
|
61 |
msg = 'Cannot continue because the working directory <'
|
62 |
msg += self.continue_dir
|
63 |
msg += '> does not exist.'
|
64 |
raise CrabException(msg)
|
65 |
|
66 |
return
|
67 |
|
68 |
def createWorkSpace(self):
|
69 |
# create WorkingDir for Multicrab
|
70 |
if 'MULTICRAB.working_dir' in self.opts.keys():
|
71 |
self.continue_dir = os.path.abspath(self.opts['MULTICRAB.working_dir'])
|
72 |
else:
|
73 |
current_time = time.strftime('%y%m%d_%H%M%S', time.localtime(time.time()))
|
74 |
self.continue_dir = os.getcwd() + '/' + self.prog_name + '_' + current_time
|
75 |
|
76 |
if self.continue_dir and not os.path.exists(self.continue_dir):
|
77 |
try:
|
78 |
os.mkdir(self.continue_dir)
|
79 |
except OSError:
|
80 |
msg = 'Cannot create '+str(self.continue_dir) +' directory.\n'
|
81 |
raise CrabException(msg)
|
82 |
pass
|
83 |
else:
|
84 |
msg = 'Directory '+str(self.continue_dir) +' already exist.\n'
|
85 |
raise CrabException(msg)
|
86 |
|
87 |
shutil.copyfile('multicrab.cfg',self.continue_dir+'/multicrab.cfg')
|
88 |
|
89 |
return
|
90 |
|
91 |
def processIniFile_(self, opts):
|
92 |
"""
|
93 |
Processes a configuration INI-file.
|
94 |
"""
|
95 |
|
96 |
# Extract cfg-file name from the cmd-line options.
|
97 |
|
98 |
for opt in opts.keys():
|
99 |
if ( opt == '-cfg' ):
|
100 |
if self.flag_continue:
|
101 |
raise CrabException('-continue and -cfg cannot coexist.')
|
102 |
if opts[opt] : self.cfg_fname = opts[opt]
|
103 |
else : processHelpOptions()
|
104 |
pass
|
105 |
pass
|
106 |
|
107 |
# Set default cfg-fname
|
108 |
|
109 |
if self.cfg_fname == None:
|
110 |
if self.flag_continue:
|
111 |
self.cfg_fname = self.continue_dir + '/multicrab.cfg'
|
112 |
else:
|
113 |
self.cfg_fname = 'multicrab.cfg'
|
114 |
pass
|
115 |
pass
|
116 |
|
117 |
# Load cfg-file
|
118 |
|
119 |
if self.cfg_fname != None:
|
120 |
if os.path.exists(self.cfg_fname):
|
121 |
self.cfg_params = self.loadMultiConfig(self.cfg_fname)
|
122 |
pass
|
123 |
else:
|
124 |
msg = 'cfg-file '+self.cfg_fname+' not found.'
|
125 |
raise CrabException(msg)
|
126 |
pass
|
127 |
pass
|
128 |
|
129 |
# process the [CRAB] section
|
130 |
|
131 |
lhp = len('MULTICRAB.')
|
132 |
for k in self.cfg_params.keys():
|
133 |
if len(k) >= lhp and k[:lhp] == 'MULTICRAB.':
|
134 |
opt = '-'+k[lhp:]
|
135 |
if len(opt) >= 3 and opt[:3] == '-__': continue
|
136 |
if opt not in opts.keys():
|
137 |
opts[opt] = self.cfg_params[k]
|
138 |
pass
|
139 |
pass
|
140 |
pass
|
141 |
|
142 |
self.cfg_params_dataset = {}
|
143 |
common_opts = {}
|
144 |
# first get common sections
|
145 |
for sec in self.cfg_params:
|
146 |
if sec in ['MULTICRAB']:
|
147 |
cfg_common=self.cfg_params[sec]
|
148 |
continue
|
149 |
if sec in ['COMMON']:
|
150 |
common_opts=self.cfg_params[sec]
|
151 |
continue
|
152 |
pass
|
153 |
|
154 |
# then Dataset's specific
|
155 |
for sec in self.cfg_params:
|
156 |
if sec in ['MULTICRAB', 'COMMON']: continue
|
157 |
self.cfg_params_dataset[sec]=self.cfg_params[sec]
|
158 |
# add common to all dataset
|
159 |
for key in common_opts:
|
160 |
self.cfg_params_dataset[sec][key]=common_opts[key]
|
161 |
pass
|
162 |
|
163 |
self.cfg=cfg_common['cfg']
|
164 |
|
165 |
# read crab.cfg file and search for storage_path
|
166 |
cfg_params = loadConfig(self.cfg,{})
|
167 |
if self.cfg_params.has_key("COMMON"):
|
168 |
self.user_remote_dir = self.cfg_params["COMMON"].get("user.user_remote_dir", cfg_params.get("USER.user_remote_dir",None))
|
169 |
else:
|
170 |
self.user_remote_dir = cfg_params.get("USER.user_remote_dir",None)
|
171 |
return
|
172 |
|
173 |
def loadMultiConfig(self, file):
|
174 |
"""
|
175 |
returns a dictionary with keys of the form
|
176 |
<section>.<option> and the corresponding values
|
177 |
"""
|
178 |
config={}
|
179 |
cp = ConfigParser.ConfigParser()
|
180 |
cp.read(file)
|
181 |
for sec in cp.sections():
|
182 |
# print 'Section',sec
|
183 |
config[sec]={}
|
184 |
for opt in cp.options(sec):
|
185 |
#print 'config['+sec+'.'+opt+'] = '+string.strip(cp.get(sec,opt))
|
186 |
config[sec][opt] = string.strip(cp.get(sec,opt))
|
187 |
return config
|
188 |
|
189 |
def run(self):
|
190 |
#run crabs
|
191 |
for sec in self.cfg_params_dataset:
|
192 |
options={}
|
193 |
if self.flag_continue:
|
194 |
options['-c']=sec
|
195 |
# DatasetName to be used
|
196 |
options['-USER.ui_working_dir']=sec
|
197 |
# options from multicrab.cfg
|
198 |
for opt in self.cfg_params_dataset[sec]:
|
199 |
tmp="-"+string.upper(opt.split(".")[0])+"."+opt.split(".")[1]
|
200 |
options[tmp]=self.cfg_params_dataset[sec][opt]
|
201 |
# add section to storage_path if exist in crab.cfg
|
202 |
if not self.cfg_params_dataset.has_key("USER.user_remote_dir") and self.user_remote_dir:
|
203 |
options["-USER.user_remote_dir"]=self.user_remote_dir+"/"+sec
|
204 |
# Input options (command)
|
205 |
for opt in self.opts:
|
206 |
options[opt]=self.opts[opt]
|
207 |
try:
|
208 |
#print options
|
209 |
crab = Crab(options)
|
210 |
crab.run()
|
211 |
common.apmon.free()
|
212 |
del crab
|
213 |
except CrabException, e:
|
214 |
print '\n' + common.prog_name + ': ' + str(e) + '\n'
|
215 |
if common.logger:
|
216 |
common.logger.write('ERROR: '+str(e)+'\n')
|
217 |
pass
|
218 |
pass
|
219 |
pass
|
220 |
pass
|
221 |
|
222 |
#common.apmon.free()
|
223 |
|
224 |
###########################################################################
|
225 |
if __name__ == '__main__':
|
226 |
## Get rid of some useless warning
|
227 |
try:
|
228 |
import warnings
|
229 |
warnings.simplefilter("ignore", RuntimeWarning)
|
230 |
except ImportError:
|
231 |
pass # too bad, you'll get the warning
|
232 |
|
233 |
# Parse command-line options and create a dictionary with
|
234 |
# key-value pairs.
|
235 |
options = parseOptions(sys.argv[1:])
|
236 |
|
237 |
# Process "help" options, such as '-help', '-version'
|
238 |
if processHelpOptions(options) : sys.exit(0)
|
239 |
|
240 |
# Create, initialize, and run a Crab object
|
241 |
try:
|
242 |
multicrab = MultiCrab(options)
|
243 |
multicrab.run()
|
244 |
except CrabException, e:
|
245 |
print '\n' + common.prog_name + ': ' + str(e) + '\n'
|
246 |
|
247 |
pass
|