Removed some debuggin print statements.
[sfa.git] / sfatables / sfatables
1 #!/usr/bin/python 
2
3 # This file parses an sfatables command and generates XML files that parameterize
4 # matches and targets. Each such XML file defines a rule. Rules are dropped in directories
5 # that represent 'chains.' SFA loads rules from various chains and invokes them at certain
6 # 'hook points.' For example, it invokes rules in the 'OUTGOING' chain before returning
7 # the output of 'get_resources.'
8
9 import sys
10 import os
11 import pdb
12 import glob
13 import libxml2
14
15 from optparse import OptionParser
16 from sfatables import commands
17 from sfatables.xmlextension import Xmlextension
18 from sfatables.globals import *
19
20 def load_commands(module, list):
21     command_dict={}
22
23     for command_name in list:
24         command_module = __import__(".".join([module,command_name]),fromlist=[module])
25         command = getattr(command_module, command_name)
26         command_dict[command_name]=command()
27
28     return command_dict
29
30 def load_xml_extensions(module, ext_dir):
31     ext_dict={}
32
33     exts = glob.glob(ext_dir + os.path.sep + "*")
34     for ext in exts:
35         module = Xmlextension(ext)
36         # get the filename and get rid of the ".xml" extension
37         ext_name = os.path.extsep.join(os.path.splitext(os.path.basename(ext))[:-1])
38         ext_dict[ext_name]=module
39
40     return ext_dict
41
42
43 def create_parser(command_dict):
44     parser = OptionParser(usage="sfatables [command] [chain] [match] [target]",
45                              description='See "man sfatables" for more detail.')
46     
47     for k in command_dict.keys():
48         command = command_dict[k]
49         for (short_option,long_option) in command.options:
50             parser.add_option(short_option,long_option,dest=command.type,action=command.action,const=k,help=command.help,metavar="CHAIN")
51
52     return parser
53
54 def create_parser_xml_ext(ext_dict):
55     parser = OptionParser(usage="sfatables [command] [chain] [match] [target]",
56                              description='See "man sfatables" for more detail.')
57     
58     for k in ext_dict.keys():
59         command = ext_dict[k]
60         for arg in command.arguments:
61             parser.add_option('',"--"+arg['name'],dest=arg['name'],help=arg['help'],metavar=arg['target'])
62
63     return parser
64
65
66 def partition(sep, lst):
67     ret = []
68     curpart = []
69     for item in lst:
70         if (item==sep):
71             ret.append(curpart)
72             curpart=[]
73         else:
74             curpart.append(item)
75     ret.append(curpart)
76
77     return ret
78
79
80 def main():
81     # sfatables <command> -- <match> -- <target>
82     pargs = partition('--', sys.argv[1:])
83
84     command_dict = load_commands("sfatables.commands",commands.all)
85     command_parser = create_parser(command_dict)
86     (options, args) = command_parser.parse_args(pargs[0])
87     setattr(options, 'args', args)
88
89     command = command_dict[options.command]
90
91     if (command.matches):
92         if (len(pargs)<2):
93             raise Exception("Must specify match for this command")
94         match_dict = load_xml_extensions("sfatables.matches",match_dir)
95         match_parser = create_parser_xml_ext(match_dict)
96         matches_str = ",".join(match_dict.keys())
97         match_parser.add_option('-m','--match',dest='name',help='Match name (one of %s)'%matches_str, metavar = 'MATCH')
98         match_parser.add_option('-n','--negate',dest='negate',help='Negate result',action='store_true')
99         (match_options, args) = match_parser.parse_args(pargs[1])
100         try:
101             name = match_options.name
102         except Exception:
103             print "Must specify match name with -m"
104
105         if (match_dict.has_key(name)):
106             setattr(match_options, 'arguments', match_dict[name].arguments)
107         else:
108             raise Exception('Match %s not found'%name)
109
110     else:
111         match_options=None
112
113     if (command.targets):
114         if (len(pargs)<3):
115             raise Exception("Must specify a target for this command")
116         target_dict = load_xml_extensions("sfatables.targets",target_dir)
117         target_parser = create_parser_xml_ext(target_dict)
118         targets_str = ",".join(target_dict.keys())
119         target_parser.add_option('-j','--jump',dest='name',help='Target name (one of %s)'%targets_str, metavar = 'TARGET')
120         target_parser.add_option('-e','--element',dest='element',help='Element name', metavar = 'ELEMENT')
121         (target_options, args) = target_parser.parse_args(pargs[2])
122         try:
123             name = target_options.name
124         except Exception:
125             print "Must specify target name with -j"
126
127         if (target_dict.has_key(name)):
128             setattr(target_options, 'arguments', target_dict[name].arguments)
129         else:
130             raise Exception('Target %s not found'%name)
131
132     else:
133         target_options = None
134
135     command(options, match_options, target_options)
136
137 if __name__=='__main__':
138     main()