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