diff options
-rw-r--r-- | nova/network/linux_net.py | 32 | ||||
-rw-r--r-- | nova/tests/test_iptables_network.py | 118 |
2 files changed, 106 insertions, 44 deletions
diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index edbabfc08..eb3560179 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -23,6 +23,7 @@ import calendar import inspect import netaddr import os +import re from nova import db from nova import exception @@ -102,6 +103,14 @@ linux_net_opts = [ cfg.IntOpt('metadata_port', default=8775, help='the port for the metadata api port'), + cfg.StrOpt('iptables_top_regex', + default='', + help='Regular expression to match iptables rule that should' + 'always be on the top.'), + cfg.StrOpt('iptables_bottom_regex', + default='', + help='Regular expression to match iptables rule that should' + 'always be on the bottom.'), ] CONF = cfg.CONF @@ -425,6 +434,25 @@ class IptablesManager(object): new_filter = filter(lambda line: binary_name not in line, current_lines) + top_rules = [] + bottom_rules = [] + + if CONF.iptables_top_regex: + regex = re.compile(CONF.iptables_top_regex) + temp_filter = filter(lambda line: regex.search(line), new_filter) + for rule_str in temp_filter: + new_filter = filter(lambda s: s.strip() != rule_str.strip(), + new_filter) + top_rules = temp_filter + + if CONF.iptables_bottom_regex: + regex = re.compile(CONF.iptables_bottom_regex) + temp_filter = filter(lambda line: regex.search(line), new_filter) + for rule_str in temp_filter: + new_filter = filter(lambda s: s.strip() != rule_str.strip(), + new_filter) + bottom_rules = temp_filter + seen_chains = False rules_index = 0 for rules_index, rule in enumerate(new_filter): @@ -438,7 +466,7 @@ class IptablesManager(object): if not seen_chains: rules_index = 2 - our_rules = [] + our_rules = top_rules bot_rules = [] for rule in rules: rule_str = str(rule) @@ -484,6 +512,8 @@ class IptablesManager(object): (binary_name, name,) for name in chains] + commit_index = new_filter.index('COMMIT') + new_filter[commit_index:commit_index] = bottom_rules seen_lines = set() def _weed_out_duplicates(line): diff --git a/nova/tests/test_iptables_network.py b/nova/tests/test_iptables_network.py index 95af25ebd..7e62d3a6e 100644 --- a/nova/tests/test_iptables_network.py +++ b/nova/tests/test_iptables_network.py @@ -30,32 +30,34 @@ class IptablesManagerTestCase(test.TestCase): ':INPUT ACCEPT [2223527:305688874]', ':FORWARD ACCEPT [0:0]', ':OUTPUT ACCEPT [2172501:140856656]', - ':nova-compute-FORWARD - [0:0]', - ':nova-compute-INPUT - [0:0]', - ':nova-compute-local - [0:0]', - ':nova-compute-OUTPUT - [0:0]', + ':iptables-top-rule - [0:0]', + ':iptables-bottom-rule - [0:0]', + ':%s-FORWARD - [0:0]' % (binary_name), + ':%s-INPUT - [0:0]' % (binary_name), + ':%s-local - [0:0]' % (binary_name), + ':%s-OUTPUT - [0:0]' % (binary_name), ':nova-filter-top - [0:0]', - '[0:0] -A FORWARD -j nova-filter-top ', - '[0:0] -A OUTPUT -j nova-filter-top ', - '[0:0] -A nova-filter-top -j nova-compute-local ', - '[0:0] -A INPUT -j nova-compute-INPUT ', - '[0:0] -A OUTPUT -j nova-compute-OUTPUT ', - '[0:0] -A FORWARD -j nova-compute-FORWARD ', + '[0:0] -A FORWARD -j nova-filter-top', + '[0:0] -A OUTPUT -j nova-filter-top', + '[0:0] -A nova-filter-top -j %s-local' % (binary_name), + '[0:0] -A INPUT -j %s-INPUT' % (binary_name), + '[0:0] -A OUTPUT -j %s-OUTPUT' % (binary_name), + '[0:0] -A FORWARD -j %s-FORWARD' % (binary_name), '[0:0] -A INPUT -i virbr0 -p udp -m udp --dport 53 ' - '-j ACCEPT ', + '-j ACCEPT', '[0:0] -A INPUT -i virbr0 -p tcp -m tcp --dport 53 ' - '-j ACCEPT ', + '-j ACCEPT', '[0:0] -A INPUT -i virbr0 -p udp -m udp --dport 67 ' - '-j ACCEPT ', + '-j ACCEPT', '[0:0] -A INPUT -i virbr0 -p tcp -m tcp --dport 67 ' - '-j ACCEPT ', + '-j ACCEPT', '[0:0] -A FORWARD -s 192.168.122.0/24 -i virbr0 ' - '-j ACCEPT ', - '[0:0] -A FORWARD -i virbr0 -o virbr0 -j ACCEPT ', + '-j ACCEPT', + '[0:0] -A FORWARD -i virbr0 -o virbr0 -j ACCEPT', '[0:0] -A FORWARD -o virbr0 -j REJECT --reject-with ' - 'icmp-port-unreachable ', + 'icmp-port-unreachable', '[0:0] -A FORWARD -i virbr0 -j REJECT --reject-with ' - 'icmp-port-unreachable ', + 'icmp-port-unreachable', 'COMMIT', '# Completed on Fri Feb 18 15:17:05 2011'] @@ -65,19 +67,20 @@ class IptablesManagerTestCase(test.TestCase): ':INPUT ACCEPT [2447:225266]', ':OUTPUT ACCEPT [63491:4191863]', ':POSTROUTING ACCEPT [63112:4108641]', - ':nova-compute-OUTPUT - [0:0]', - ':nova-compute-floating-ip-snat - [0:0]', - ':nova-compute-SNATTING - [0:0]', - ':nova-compute-PREROUTING - [0:0]', - ':nova-compute-POSTROUTING - [0:0]', + ':%s-OUTPUT - [0:0]' % (binary_name), + ':%s-float-snat - [0:0]' % (binary_name), + ':%s-snat - [0:0]' % (binary_name), + ':%s-PREROUTING - [0:0]' % (binary_name), + ':%s-POSTROUTING - [0:0]' % (binary_name), ':nova-postrouting-bottom - [0:0]', - '[0:0] -A PREROUTING -j nova-compute-PREROUTING ', - '[0:0] -A OUTPUT -j nova-compute-OUTPUT ', - '[0:0] -A POSTROUTING -j nova-compute-POSTROUTING ', - '[0:0] -A POSTROUTING -j nova-postrouting-bottom ', - '[0:0] -A nova-postrouting-bottom -j nova-compute-SNATTING ', - '[0:0] -A nova-compute-SNATTING ' - '-j nova-compute-floating-ip-snat ', + '[0:0] -A PREROUTING -j %s-PREROUTING' % (binary_name), + '[0:0] -A OUTPUT -j %s-OUTPUT' % (binary_name), + '[0:0] -A POSTROUTING -j %s-POSTROUTING' % (binary_name), + '[0:0] -A POSTROUTING -j nova-postrouting-bottom', + '[0:0] -A nova-postrouting-bottom ' + '-j %s-SNATTING' % (binary_name), + '[0:0] -A %s-SNATTING ' + '-j %s-floating-ip-snat' % (binary_name, binary_name), 'COMMIT', '# Completed on Fri Feb 18 15:17:05 2011'] @@ -105,13 +108,13 @@ class IptablesManagerTestCase(test.TestCase): new_lines = self.manager._modify_rules(current_lines, self.manager.ipv4['nat']) - for line in [':nova-compute-OUTPUT - [0:0]', - ':nova-compute-floating-ip-snat - [0:0]', - ':nova-compute-SNATTING - [0:0]', - ':nova-compute-PREROUTING - [0:0]', - ':nova-compute-POSTROUTING - [0:0]']: - self.assertTrue(line in new_lines, "One of nova-compute's chains " - "went missing.") + for line in [':%s-OUTPUT - [0:0]' % (self.binary_name), + ':%s-float-snat - [0:0]' % (self.binary_name), + ':%s-snat - [0:0]' % (self.binary_name), + ':%s-PREROUTING - [0:0]' % (self.binary_name), + ':%s-POSTROUTING - [0:0]' % (self.binary_name)]: + self.assertTrue(line in new_lines, "One of our chains went" + " missing.") seen_lines = set() for line in new_lines: @@ -140,12 +143,12 @@ class IptablesManagerTestCase(test.TestCase): new_lines = self.manager._modify_rules(current_lines, self.manager.ipv4['filter']) - for line in [':nova-compute-FORWARD - [0:0]', - ':nova-compute-INPUT - [0:0]', - ':nova-compute-local - [0:0]', - ':nova-compute-OUTPUT - [0:0]']: - self.assertTrue(line in new_lines, "One of nova-compute's chains" - " went missing.") + for line in [':%s-FORWARD - [0:0]' % (self.binary_name), + ':%s-INPUT - [0:0]' % (self.binary_name), + ':%s-local - [0:0]' % (self.binary_name), + ':%s-OUTPUT - [0:0]' % (self.binary_name)]: + self.assertTrue(line in new_lines, "One of our chains went" + " missing.") seen_lines = set() for line in new_lines: @@ -189,3 +192,32 @@ class IptablesManagerTestCase(test.TestCase): "COMMIT" == new_lines[-2] and "#Completed by nova" == new_lines[-1], "iptables rules not generated in the correct order") + + def test_iptables_top_order(self): + # Test iptables_top_regex + current_lines = list(self.sample_filter) + current_lines[12:12] = ['[0:0] -A FORWARD -j iptables-top-rule'] + self.flags(iptables_top_regex='-j iptables-top-rule') + new_lines = self.manager._modify_rules(current_lines, + self.manager.ipv4['filter']) + self.assertEqual(current_lines, new_lines) + + def test_iptables_bottom_order(self): + # Test iptables_bottom_regex + current_lines = list(self.sample_filter) + current_lines[26:26] = ['[0:0] -A FORWARD -j iptables-bottom-rule'] + self.flags(iptables_bottom_regex='-j iptables-bottom-rule') + new_lines = self.manager._modify_rules(current_lines, + self.manager.ipv4['filter']) + self.assertEqual(current_lines, new_lines) + + def test_iptables_preserve_order(self): + # Test both iptables_top_regex and iptables_bottom_regex + current_lines = list(self.sample_filter) + current_lines[12:12] = ['[0:0] -A FORWARD -j iptables-top-rule'] + current_lines[27:27] = ['[0:0] -A FORWARD -j iptables-bottom-rule'] + self.flags(iptables_top_regex='-j iptables-top-rule') + self.flags(iptables_bottom_regex='-j iptables-bottom-rule') + new_lines = self.manager._modify_rules(current_lines, + self.manager.ipv4['filter']) + self.assertEqual(current_lines, new_lines) |