source: dassmodus/trunk/dassmodus/nosferatu/nosferatu/tools/bacsource2configrules.py@ 1153

Last change on this file since 1153 was 1153, checked in by joergs, on Jun 8, 2013 at 7:43:56 PM

dot commands

File size: 13.4 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# $Id: bacsource2configrules.py 11326 2010-10-25 07:56:12Z pstorz $
5
6"""Helper script to generate resource classes from
7bacula c definitions.
8
9Usage:
10c2py_resource.py BACULA_SRC_PATH
11"""
12
13####
14# RESOURCE_TYPE has to be either 'dird', 'console', 'filed' or 'stored'
15# CONF_C_FILE is the corresponding c source e.g. 'dird/dird_conf.c'
16#"""
17
18
19
20
21C_CONFS = (
22 ("dird", "dird_conf.c"),
23 ("console", "console_conf.c"),
24 ("filed", "filed_conf.c"),
25 ("stored", "stored_conf.c"),
26 ("lib", "parse_conf.c"),
27 ("inc" , "inc_conf.c"),
28 )
29
30
31
32import os
33import re
34from nosferatu.config_classes import *
35from resource import Resource
36from nosferatu import prettynames
37import pprint
38
39RXP_RESOURCE = re.compile(r'''
40 ^(?:static\s+)?RES_ITEM(2)?\s+
41 (?P<name>[^[]+)\[\]\s+=\s+\{\s*\n # First line with starting brace
42 (?P<items>.*?) # Non greedy search
43 \n}\s*;
44''', re.M|re.X|re.S)
45
46
47RXP_ITEM = re.compile(r'''
48 ^\s+{"(?P<name>[^"]+)"\s*,
49 \s*(?P<handler>[^,]+)\s*,
50 \s*(?P<value>[^,]+)\s*,
51 \s*(?P<code>[^,]+)\s*,
52 \s*(?P<flags>[^,]+)\s*,
53 \s*(?P<default_value>[^}]+)},?\s*
54''', re.X)
55
56
57RXP_RESTABLE = re.compile(r'''
58 ^(?:static\s+)?RES_TABLE\s+
59 (?P<name>[^[]+)\[\]\s+=\s+\{\s*\n # First line with starting brace
60 (?P<items>.*?) # Non greedy search
61 \n}\s*;
62''', re.M|re.X|re.S)
63
64
65RXP_RESTABLE_ITEM = re.compile(r'''
66 ^\s+{"(?P<name>[^"]+)"\s*,
67 \s*(?P<resitem>[^,]+)\s*,
68 \s*(?P<rcode>[^}]+)},?\s*
69''', re.X)
70
71
72
73RXP_STRUCT_TABLE = re.compile(r'''
74 ^(?:static\s+?)?struct
75 \ss_[a-zA-Z_]+\s(?P<name>[^[^{]+)\[\]\s+=\s+\{\s*\n # First line with starting brace
76 (?P<items>.*?) # Non greedy search
77 \n}\s*;
78''', re.M|re.X|re.S)
79
80RXP_STRUCT_ITEM = re.compile(r'''
81 ^\s+{\s*"(?P<name>[^"]+)"\s*,
82 \s*(?P<resitem>[^,]+)\s*(,
83 \s*(?P<rcode>[^}]+))?},?\s*(/\*.*\*/)?
84''', re.X)
85
86
87
88
89# handler to python type wrapping
90CONF2TYPE = {
91 'store_bool' : bool,
92 'store_pint32' : int,
93 'store_str' : str,
94 'store_name' : str,
95 #'store_dir' : Path,
96 }
97
98CONF2VALUE = {
99 'INT32_MAX' : 0x7fffffffL,
100 'true' : True,
101 'false' : False,
102 'REPLACE_ALWAYS': 0 ,
103 #0 : '0' ,
104 #'0' : '0',
105 0 : None ,
106 '0' : None ,
107
108 '60*60*24*31*12*5' : '160704000',
109 '60*60*24*60' : '5184000',
110 '60*60*24*180': '15552000',
111 '60*60*24*365': '31536000',
112 '3 * 60' : '180',
113 '30 * 60' : '1800',
114 '60 * 30' : '1800',
115 '5 * 60' : '300',
116 }
117
118
119
120
121# Read in Commands Info
122
123RXP_COMMAND_ENTRY = re.compile(r'''
124^\s*{\s*NT_\("(?P<cmdtext>[^"]+)"\),
125\s*(?P<cmd>[^,]+),
126\s*_\("(?P<usage>[^"]*)"\),\s*\n*
127\s*NT_\("(?P<help>[^"]*)"\),
128\s*(?P<inrunscript>\w+)\s*}
129''', re.X|re.M|re.S)
130
131
132RXP_DOT_COMMAND_ENTRY = re.compile(r'''
133^\s+{\s*NT_\("(?P<cmdtext>[^"]+)"\),
134\s*(?P<cmd>[^,]+),
135\s*(?P<help>\w*),
136\s*(?P<inrunscript>\w+)\s*}
137''', re.X|re.M|re.S)
138
139
140
141
142
143
144BOOL_FILESET_OPTIONS = set([
145'portable' ,
146'ignorecase' ,
147'honornodumpflag',
148'exclude' ,
149'enhancedwild' ,
150'hardlinks' ,
151'onefs' ,
152'xattrsupport' ,
153'hfsplussupport' ,
154'aclsupport' ,
155'checkfilechanges' ,
156'keepatime' ,
157'readfifo' ,
158'recurse' ,
159'sparse' ,
160'mtimeonly' ,
161'noatime' ,
162])
163
164def defvalue(type, name, value):
165 if type == 'store_opts':
166 if name in BOOL_FILESET_OPTIONS:
167 if value == 0:
168 defval = False
169 else:
170 defval = True
171 else:
172 defval = value
173
174 elif type == 'store_bool' or type == 'store_bit':
175 if value == 0 or value == '0' or value == 'false' or value == None:
176 defval = False
177 else:
178 defval = True
179 else:
180 defval = CONF2VALUE.get(value,value)
181 return defval
182
183
184
185store_classes = []
186
187def parse_conf_c(filename):
188 """parse a bacula c file for resoure item definitions"""
189 cfg = {}
190 cf = open(filename).read()
191 for block in RXP_RESOURCE.finditer(cf):
192 bl = cfg[block.group("name")] = {}
193 for line in block.group("items").split('\n'):
194 m = RXP_ITEM.search(line)
195 if not m: continue
196 item = m.groupdict()
197 bl[item.pop("name")] = item
198 return cfg
199
200
201def parse_conf_c_for_res_table(filename):
202 """parse a bacula c file for resoure table definitions"""
203 cfg = {}
204 cf = open(filename).read()
205 for block in RXP_RESTABLE.finditer(cf):
206 bl = cfg[block.group("name")] = {}
207 for line in block.group("items").split('\n'):
208 m = RXP_RESTABLE_ITEM.search(line)
209 if not m: continue
210 item = m.groupdict()
211 bl[item.pop("name")] = item
212 return cfg
213
214
215
216def directives(daemon, conf):
217 res = conf.keys()
218 res.sort()
219 for r in res:
220 s = "%s_%s = [\n" % (daemon, r)
221 #s = ' '
222 keys = sorted(conf[r].iterkeys())
223 try: # put name first
224 keys.remove('name')
225 keys.insert(0,'name')
226 except:
227 pass
228 for i in keys:
229 #for i, v in conf[r].iteritems():
230 name = i
231 v = conf[r][i]
232 type = v["handler"]
233 required = v["flags"] == "ITEM_REQUIRED"
234 default = v["flags"] == "ITEM_DEFAULT"
235 defaultvalue = defvalue(type, name, v["default_value"])
236 #defaultvalue = CONF2VALUE.get(v["default_value"],v["default_value"])
237 if default:
238 value = defaultvalue
239 else:
240 value = defvalue(type, name, None)
241 #if type=='store_bool':
242 # print "Bool"
243 s += " %s,\n" % repr(Item(name, value, defaultvalue, default, type, required))
244 #if defaultvalue == None:
245 # defaultvalue = ''
246 #if required == True:
247 # required = 'Ja'
248 #else:
249 # required = 'Nein'
250 #type = type.replace('store_','').replace('_','\_')
251 #s += "%s & %s & %s & %s \\\\ \n" % (PrettyNames[name], defaultvalue ,type, required)
252 s += "]\n"
253 print s
254
255
256def ressources(daemon, conf):
257 res = conf.keys()
258 res.sort()
259 for r in res:
260 s = "# This is the master resource definition. \n# It must have one item for each of the resources.\n"
261 s += "%s_%s = [\n" % (daemon, r)
262 for i, v in conf[r].iteritems():
263 name = i
264 rcode = v["rcode"]
265 resitem = v["resitem"]
266 #print resitem
267 if resitem == 'NULL': continue
268 if resitem == 'msgs_items': # Message ressource is defined in lib file
269 s += " [ \'%s\' , \'%s\', %s_%s ], \n" % (name, rcode, 'lib', resitem)
270 else:
271 s += " [ \'%s\' , \'%s\', %s_%s ], \n" % (name, rcode, daemon, resitem)
272 s += "]\n"
273 print s
274
275
276
277
278def parse_conf_c_for_structs(filename):
279 """parse a bacula c file for resoure table definitions"""
280 cfg = {}
281 cf = open(filename).read()
282 for block in RXP_STRUCT_TABLE.finditer(cf):
283 if block.group("name") != "FS_options" and block.group("name") != "FS_option_kw":
284 bl = cfg[block.group("name")] = {}
285 for line in block.group("items").split('\n'):
286 m = RXP_STRUCT_ITEM.search(line)
287 if not m: continue
288 item = m.groupdict()
289 bl[item.pop("name")] = item
290
291 elif block.group("name") == "FS_options":
292 bl = cfg[block.group("name")] = {} # keywords
293 for line in block.group("items").split('\n'):
294 m = RXP_STRUCT_ITEM.search(line)
295 if not m: continue
296 item = m.groupdict()
297 if not item["resitem"] in bl:
298 #print "creating", item["resitem"], item
299 bl[item["resitem"]] = []
300 #else:
301 # print "not creating" , item["resitem"]
302 #bl[item["resitem"]].append(item["name"])
303 #item.pop('rcode')
304 bl[item["resitem"]].append(prettyName(item.pop('name')))
305
306 #print " appended to bl[" , item["resitem"] , "]" , item
307
308 elif block.group("name") == "FS_option_kw":
309 bl = cfg[block.group("name")] = {} # keywords
310 for line in block.group("items").split('\n'):
311 m = RXP_STRUCT_ITEM.search(line)
312 if not m: continue
313 item = m.groupdict()
314 if not item["name"] in bl:
315 #print "adding", item["resitem"], item["name"]
316 bl[item["name"]] = []
317 #else:
318 # print "not adding" , item["resitem"]
319 #bl[item["resitem"]].append(item["name"])
320 bl[item["name"]] = item.pop('resitem')
321 #print " appending to bl[" , item["resitem"] , "]"
322 #print cfg
323 return cfg
324
325#def structs(daemon, conf):
326
327
328
329
330if __name__ == "__main__":
331 try:
332 bacula_src = sys.argv[1]
333 #bacula_src = '/home/pstorz/bacula_git/trunk/bacula/src/'
334 except:
335 raise(__doc__)
336
337 rsc = []
338
339 print '''#!/usr/bin/env python
340# -*- coding: utf-8 -*-
341#
342# auto_types.py
343#
344# This file is autogenerated from the bacula sources.
345#
346from auto_types import *
347from command import *
348
349 '''
350
351
352 # for parse_conf_c_for_structs(bacula_src + 'dird/dird_conf.c')
353 conf = parse_conf_c_for_structs(bacula_src + 'lib/parse_conf.c')
354 for r in conf.keys():
355 print r + ' = [' ,
356 #print r, conf[r]
357 for i, v in conf[r].iteritems():
358 if str(i) != ' ':
359 print "'" + i.lower() + "'" +', ',
360
361 print ']'
362
363 # for parse_conf_c_for_structs(bacula_src + 'dird/dird_conf.c')
364 conf = parse_conf_c_for_structs(bacula_src + 'dird/dird_conf.c')
365 for r in conf.keys():
366 print r + ' = [' ,
367 #print r, conf[r]
368 for i, v in conf[r].iteritems():
369 if str(i) != ' ':
370 print "'" + prettynames.prettyName(i.lower()) + "'" +', ',
371 #print "'" + i.lower() + "'" +', ',
372 print ']'
373 #print 'READY1'
374
375
376
377
378 conf = parse_conf_c_for_structs(bacula_src + 'dird/inc_conf.c')
379 #print conf
380
381 for r in conf.keys():
382 if r != 'FS_options' and r != 'FS_option_kw':
383 #print 'R:' + r + ':R'
384 print r + ' = [' ,
385 #print r,type( conf[r] )
386 #if type(conf[r]) == 'type <dict>':
387 for i, v in conf[r].iteritems():
388 if type(v) == 'type <str>':
389 print "'" + i.lower() + "'" +', ',
390 else:
391 print '[' , i,'=',v, ']'
392 #print "i,v:",i,v
393 print ']\n'
394
395 elif r == "FS_option_kw":
396 print r + ' = {' ,
397 for i, v in conf[r].iteritems():
398 #if type(v) == 'type <str>':
399 # print "'" + i.lower() + "'" +', ',
400 #else:
401 #print '[' , i,'=',v, ']'
402
403 #print conf['FS_options']
404 try:
405 options = conf['FS_options'][v]
406 #print conf['FS_options'][v]
407 except:
408 options = ['Yes', 'No']
409 #print "excepting on "
410 print "'" + i + "'" , ':', options, ','
411 #print "i,v:",i,v
412 print '}\n'
413
414
415 #else:
416 # for i in conf[r]:
417 # print i
418 # print ']\n'
419
420 #print 'READY2'
421
422
423 commands = {}
424
425 filename = bacula_src+"/dird/ua_cmds.c"
426
427 cf = open(filename).read()
428 for entry in RXP_COMMAND_ENTRY.finditer(cf):
429 #print entry.groups()
430 commands[entry.group("cmdtext")]= command(
431 entry.group("cmdtext"),
432 entry.group("cmd"),
433 entry.group("usage"),
434 entry.group("help").replace('"','').replace('\n',''),
435 entry.group("inrunscript"),
436 )
437
438 filename = bacula_src+"/dird/ua_dotcmds.c"
439
440 cf = open(filename).read()
441 for entry in RXP_DOT_COMMAND_ENTRY.finditer(cf):
442 #print entry.groups()
443 commands[entry.group("cmdtext")]= command(entry.group("cmdtext"),
444 entry.group("cmd"),
445 '',
446 entry.group("help").replace('"','').replace('\n',''),
447 entry.group("inrunscript"),
448 )
449 print "commands = ",
450 pprint.pprint(commands)
451
452
453
454
455 print '''
456#!/usr/bin/env python
457# -*- coding: utf-8 -*-
458# auto_configrules.py
459#
460# This file is autogenerated from the bacula sources.
461#
462from auto_types import *
463from config_classes import *
464
465
466 '''
467
468
469 inc = False
470
471 for daemon, conf in C_CONFS:
472 if daemon == 'inc':
473 inc = True
474 daemon = 'dird'
475 filename = os.path.join(bacula_src, daemon, conf)
476 if inc:
477 daemon = 'inc'
478 directives(daemon, parse_conf_c(filename))
479
480
481 inc = False
482 for daemon, conf in C_CONFS:
483 if daemon == 'inc':
484 inc = True
485 daemon = 'dird'
486 filename = os.path.join(bacula_src, daemon, conf)
487 if inc:
488 daemon = 'inc'
489 ressources(daemon, parse_conf_c_for_res_table(filename))
490
491 print '''
492# manual configurations
493
494dir_addresses_items = [
495 # no items, just a container
496]
497
498cli_addresses_items = [
499 # no items, just a container
500]
501
502store_addresses_items = [
503 # no items, just a container
504]
505
506
507addresses_ip_items = [
508 Item('port', 9102, 9102, True, 'store_str', False),
509 Item('addr', 0, 0, False, 'store_str', False),
510]
511
512#fs_include_items = [
513# Item('file', 0, 0, False, 'store_dir', False),
514#]
515
516fs_include_items = inc_newinc_items
517 '''
518
519
Note: See TracBrowser for help on using the repository browser.