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

Last change on this file since 1153 was 1153, checked in by joergs, 8 years ago

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.