Bug fixes and cleanups
[sfa.git] / sfatables / commands / Add.py
1 import os, time
2 import libxml2
3 from sfatables.command import Command
4 from sfatables.globals import *
5
6 class Add(Command):
7     def __init__(self):
8         self.options = [('-A','--add')]
9         self.help = 'Add a rule to a chain'
10         self.matches = True
11         self.targets = True
12         return
13
14     def getnextfilename(self,type,chain):
15         dir = sfatables_config + "/"+chain;
16         last_rule_number = 0
17
18         for (root, dirs, files) in os.walk(dir):
19             for file in files:
20                 if (file.startswith('sfatables-') and file.endswith(type)):
21                     number_str = file.split('-')[1]
22                     number = int(number_str)
23                     if (number>last_rule_number):
24                         last_rule_number = number
25
26         return "sfatables-%d-%s"%(last_rule_number+1,type)
27
28     def call_gen(self, chain, type, dir, options):
29         filename = os.path.join(dir, options.name+".xml")
30         xmldoc = libxml2.parseFile(filename)
31     
32         p = xmldoc.xpathNewContext()
33
34         supplied_arguments = options.arguments
35         if (hasattr(options,'element') and options.element):
36             element = options.element
37         else:
38             element='*'
39
40         for option in supplied_arguments:
41             option_name = option['name']
42             option_value = getattr(options,option_name)
43
44             if (hasattr(options,option_name)):
45                 context = p.xpathEval("//rule[@element='%s' or @element='*']/argument[name='%s']"%(element, option_name))
46                 if (not context):
47                     raise Exception('Unknown option %s for match %s and element %s'%(option,option['name'], element))
48                 else:
49                     # Add the value of option
50                     valueNode = libxml2.newNode('value')
51                     valueNode.addContent(option_value)
52                     context[0].addChild(valueNode)
53
54         filename = self.getnextfilename(type,chain)
55         file_path = os.path.join(sfatables_config, chain, filename)
56         if not os.path.isdir(os.path.dirname(file_path)):
57             os.makedirs(os.path.dirname(file_path))
58         xmldoc.saveFile(file_path)
59         p.xpathFreeContext()
60         xmldoc.freeDoc()
61
62         return True
63
64     def call(self, command_options, match_options, target_options):
65         chain = command_options.args[0]
66         ret = self.call_gen(chain, 'match',match_dir, match_options)
67         if (ret):
68             ret = self.call_gen(chain, 'target',target_dir, target_options)
69
70         return ret