(no commit message)
[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 libxml2
13
14 from optparse import OptionParser
15 from sfatables import commands, matches, targets
16 from sfatables.xmlextension import Xmlextension
17
18 def load_commands(module, list):
19     command_dict={}
20
21     for command_name in list:
22         command_module = __import__(".".join([module,command_name]),fromlist=[module])
23         command = getattr(command_module, command_name)
24         command_dict[command_name]=command()
25
26     return command_dict
27
28 def load_xml_extensions(module, list):
29     ext_dict={}
30
31     for ext_name in list:
32         module = Xmlextension(ext_name)
33         ext_dict[ext_name]=module
34
35     return ext_dict
36
37
38 def create_parser(command_dict):
39     parser = OptionParser(usage="sfatables [command] [chain] [match] [target]",
40                              description='See "man sfatables" for more detail.')
41     
42     for k in command_dict.keys():
43         command = command_dict[k]
44         for (short_option,long_option) in command.options:
45             parser.add_option(short_option,long_option,dest=command.type,action=command.action,const=k,help=command.help,metavar="CHAIN")
46
47     return parser
48
49 def create_parser_xml_ext(ext_dict):
50     parser = OptionParser(usage="sfatables [command] [chain] [match] [target]",
51                              description='See "man sfatables" for more detail.')
52     
53     for k in ext_dict.keys():
54         command = ext_dict[k]
55         for arg in command.arguments:
56             parser.add_option('',"--"+arg['name'],dest=arg['name'],help=arg['help'],metavar=arg['target'])
57
58     return parser
59
60
61 def partition(sep, lst):
62     ret = []
63     curpart = []
64     for item in lst:
65         if (item==sep):
66             ret.append(curpart)
67             curpart=[]
68         else:
69             curpart.append(item)
70     ret.append(curpart)
71
72     return ret
73
74
75 def main():
76     # sfatables <command> -- <match> -- <target>
77     pargs = partition('--', sys.argv[1:])
78
79     command_dict = load_commands("sfatables.commands",commands.all)
80     command_parser = create_parser(command_dict)
81     (options, args) = command_parser.parse_args(pargs[0])
82     setattr(options, 'args', args)
83
84     command = command_dict[options.command]
85
86     if (command.matches):
87         if (len(pargs)<2):
88             raise Exception("Must specify match for this command")
89         match_dict = load_xml_extensions("sfatables.matches",matches.all)
90         match_parser = create_parser_xml_ext(match_dict)
91         matches_str = ",".join(match_dict.keys())
92         match_parser.add_option('-m','--match',dest='match_name',help='Match name (one of %s)'%matches_str, metavar = 'MATCH')
93         (match_options, args) = match_parser.parse_args(pargs[1])
94         try:
95             match_name = match_options.match_name
96         except Exception:
97             print "Must specify match name with -m"
98
99         if (match_dict.has_key(match_name)):
100             setattr(match_options, 'arguments', match_dict[match_name].arguments)
101         else:
102             raise Exception('Match %s not found'%match_name)
103
104     else:
105         match_options=None
106
107     if (command.targets):
108         if (len(pargs)<3):
109             raise Exception("Must specify a target for this command")
110         target_dict = load_xml_extensions("sfatables.targets",targets.all)
111         target_parser = create_parser_xml_ext(target_dict)
112         targets_str = ",".join(target_dict.keys())
113         target_parser.add_option('-j','--jump',dest='target_name',help='Target name (one of %s)'%targets, metavar = 'TARGET')
114         (target_options, args) = target_parser.parse_args(pargs[2])
115         try:
116             target_name = target_options.target_name
117         except Exception:
118             print "Must specify target name with -m"
119
120 #        if (target_dict.has_key(target_name)):
121 #            setattr(target_options, 'arguments', target_dict[target_name].arguments)
122 #        else:
123 #            raise Exception('Target %s not found'%target_name)
124
125     else:
126         target_options = None
127
128     command(options, match_options, target_options)
129
130 if __name__=='__main__':
131     main()