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