]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Adds Install_SNAT_rules_for_ipv4_only.patch. Note that without this patch,
authorThomas Goirand <thomas@goirand.fr>
Mon, 2 Jun 2014 16:08:25 +0000 (00:08 +0800)
committerThomas Goirand <thomas@goirand.fr>
Mon, 2 Jun 2014 16:08:25 +0000 (00:08 +0800)
it's possible to destroy an OpenStack cloud network, which is why I'm
putting urgency=high in this upload.

Change-Id: I34aa3c656f0218a1986ef6b78f7e28132d6172a6

debian/changelog
debian/patches/Install_SNAT_rules_for_ipv4_only.patch [new file with mode: 0644]
debian/patches/series

index dcc13dfdda0453c2eb885581073e8a0e96ce2bb3..98e50a5dc403282c2a6134d86b88aa79b1432ad5 100644 (file)
@@ -1,3 +1,11 @@
+neutron (2014.1-6) unstable; urgency=high
+
+  * Adds Install_SNAT_rules_for_ipv4_only.patch. Note that without this patch,
+    it's possible to destroy an OpenStack cloud network, which is why I'm
+    putting urgency=high in this upload.
+
+ -- Thomas Goirand <zigo@debian.org>  Tue, 03 Jun 2014 00:07:08 +0800
+
 neutron (2014.1-5) unstable; urgency=medium
 
   * Switched from restarting daemons to copytruncate for logrotate.
diff --git a/debian/patches/Install_SNAT_rules_for_ipv4_only.patch b/debian/patches/Install_SNAT_rules_for_ipv4_only.patch
new file mode 100644 (file)
index 0000000..a86f5c0
--- /dev/null
@@ -0,0 +1,204 @@
+Description: Install SNAT rules for ipv4 only
+Author: Baodong Li <baoli@cisco.com>
+Date: Thu, 24 Apr 2014 01:47:13 +0000 (+0000)
+X-Git-Url: https://review.openstack.org/gitweb?p=openstack%2Fneutron.git;a=commitdiff_plain;h=28a26dbfd7e95ad84e8c9eeac1e5aba0b111a16c
+Origin: https://review.openstack.org/95938/
+Change-Id: I37bd770aa0d54a985ac2bec708c571785084e0ec
+Bug-Ubuntu: https://launchpad.net/bugs/1309195
+Last-Update: 2014-06-02
+
+diff --git a/neutron/agent/l3_agent.py b/neutron/agent/l3_agent.py
+index f335da7..e9854fd 100644
+--- a/neutron/agent/l3_agent.py
++++ b/neutron/agent/l3_agent.py
+@@ -451,7 +451,9 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
+                                namespace=ri.ns_name,
+                                prefix=INTERNAL_DEV_PREFIX)
+-        internal_cidrs = [p['ip_cidr'] for p in ri.internal_ports]
++        # Get IPv4 only internal CIDRs
++        internal_cidrs = [p['ip_cidr'] for p in ri.internal_ports
++                          if netaddr.IPNetwork(p['ip_cidr']).version == 4]
+         # TODO(salv-orlando): RouterInfo would be a better place for
+         # this logic too
+         ex_gw_port_id = (ex_gw_port and ex_gw_port['id'] or
+@@ -530,11 +532,16 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
+         # And add them back if the action if add_rules
+         if action == 'add_rules' and ex_gw_port:
+             # ex_gw_port should not be None in this case
+-            ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
+-            for rule in self.external_gateway_nat_rules(ex_gw_ip,
+-                                                        internal_cidrs,
+-                                                        interface_name):
+-                ri.iptables_manager.ipv4['nat'].add_rule(*rule)
++            # NAT rules are added only if ex_gw_port has an IPv4 address
++            for ip_addr in ex_gw_port['fixed_ips']:
++                ex_gw_ip = ip_addr['ip_address']
++                if netaddr.IPAddress(ex_gw_ip).version == 4:
++                    rules = self.external_gateway_nat_rules(ex_gw_ip,
++                                                            internal_cidrs,
++                                                            interface_name)
++                    for rule in rules:
++                        ri.iptables_manager.ipv4['nat'].add_rule(*rule)
++                    break
+         ri.iptables_manager.apply()
+     def process_router_floating_ip_nat_rules(self, ri):
+diff --git a/neutron/tests/unit/test_l3_agent.py b/neutron/tests/unit/test_l3_agent.py
+index d1dffff..ec272ef 100644
+--- a/neutron/tests/unit/test_l3_agent.py
++++ b/neutron/tests/unit/test_l3_agent.py
+@@ -17,6 +17,7 @@ import contextlib
+ import copy
+ import mock
++import netaddr
+ from oslo.config import cfg
+ from testtools import matchers
+@@ -331,24 +332,37 @@ class TestBasicRouterOperations(base.BaseTestCase):
+             '! -i %s ! -o %s -m conntrack ! --ctstate DNAT -j ACCEPT' %
+             (interface_name, interface_name)]
+         for source_cidr in source_cidrs:
+-            value_dict = {'source_cidr': source_cidr,
+-                          'source_nat_ip': source_nat_ip}
+-            expected_rules.append('-s %(source_cidr)s -j SNAT --to-source '
+-                                  '%(source_nat_ip)s' % value_dict)
++            # Create SNAT rules for IPv4 only
++            if (netaddr.IPNetwork(source_cidr).version == 4 and
++                netaddr.IPNetwork(source_nat_ip).version == 4):
++                value_dict = {'source_cidr': source_cidr,
++                              'source_nat_ip': source_nat_ip}
++                expected_rules.append('-s %(source_cidr)s -j SNAT --to-source '
++                                      '%(source_nat_ip)s' % value_dict)
+         for r in rules:
+             if negate:
+                 self.assertNotIn(r.rule, expected_rules)
+             else:
+                 self.assertIn(r.rule, expected_rules)
+-    def _prepare_router_data(self, enable_snat=None, num_internal_ports=1):
++    def _prepare_router_data(self, ip_version=4,
++                             enable_snat=None, num_internal_ports=1):
++        if ip_version == 4:
++            ip_addr = '19.4.4.4'
++            cidr = '19.4.4.0/24'
++            gateway_ip = '19.4.4.1'
++        elif ip_version == 6:
++            ip_addr = 'fd00::4'
++            cidr = 'fd00::/64'
++            gateway_ip = 'fd00::1'
++
+         router_id = _uuid()
+         ex_gw_port = {'id': _uuid(),
+                       'network_id': _uuid(),
+-                      'fixed_ips': [{'ip_address': '19.4.4.4',
++                      'fixed_ips': [{'ip_address': ip_addr,
+                                      'subnet_id': _uuid()}],
+-                      'subnet': {'cidr': '19.4.4.0/24',
+-                                 'gateway_ip': '19.4.4.1'}}
++                      'subnet': {'cidr': cidr,
++                                 'gateway_ip': gateway_ip}}
+         int_ports = []
+         for i in range(num_internal_ports):
+             int_ports.append({'id': _uuid(),
+@@ -635,6 +649,99 @@ class TestBasicRouterOperations(base.BaseTestCase):
+         self._verify_snat_rules(nat_rules_delta, router)
+         self.send_arp.assert_called_once()
++    def test_process_ipv6_only_gw(self):
++        agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
++        router = self._prepare_router_data(ip_version=6)
++        # Get NAT rules without the gw_port
++        gw_port = router['gw_port']
++        router['gw_port'] = None
++        ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper,
++                                 self.conf.use_namespaces, router=router)
++        agent.external_gateway_added = mock.Mock()
++        agent.process_router(ri)
++        orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
++
++        # Get NAT rules with the gw_port
++        router['gw_port'] = gw_port
++        ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper,
++                                 self.conf.use_namespaces, router=router)
++        with mock.patch.object(
++                agent,
++                'external_gateway_nat_rules') as external_gateway_nat_rules:
++            agent.process_router(ri)
++            new_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
++
++            # There should be no change with the NAT rules
++            self.assertFalse(external_gateway_nat_rules.called)
++            self.assertEqual(orig_nat_rules, new_nat_rules)
++
++    def test_process_router_ipv6_interface_added(self):
++        agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
++        router = self._prepare_router_data()
++        ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper,
++                                 self.conf.use_namespaces, router=router)
++        agent.external_gateway_added = mock.Mock()
++        # Process with NAT
++        agent.process_router(ri)
++        orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
++        # Add an IPv6 interface and reprocess
++        router[l3_constants.INTERFACE_KEY].append(
++            {'id': _uuid(),
++             'network_id': _uuid(),
++             'admin_state_up': True,
++             'fixed_ips': [{'ip_address': 'fd00::2',
++                            'subnet_id': _uuid()}],
++             'mac_address': 'ca:fe:de:ad:be:ef',
++             'subnet': {'cidr': 'fd00::/64',
++                        'gateway_ip': 'fd00::1'}})
++        # Reassign the router object to RouterInfo
++        ri.router = router
++        agent.process_router(ri)
++        # For some reason set logic does not work well with
++        # IpTablesRule instances
++        nat_rules_delta = [r for r in ri.iptables_manager.ipv4['nat'].rules
++                           if r not in orig_nat_rules]
++        self.assertFalse(nat_rules_delta)
++
++    def test_process_router_ipv6v4_interface_added(self):
++        agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
++        router = self._prepare_router_data()
++        ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper,
++                                 self.conf.use_namespaces, router=router)
++        agent.external_gateway_added = mock.Mock()
++        # Process with NAT
++        agent.process_router(ri)
++        orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
++        # Add an IPv4 and IPv6 interface and reprocess
++        router[l3_constants.INTERFACE_KEY].append(
++            {'id': _uuid(),
++             'network_id': _uuid(),
++             'admin_state_up': True,
++             'fixed_ips': [{'ip_address': '35.4.1.4',
++                            'subnet_id': _uuid()}],
++             'mac_address': 'ca:fe:de:ad:be:ef',
++             'subnet': {'cidr': '35.4.1.0/24',
++                        'gateway_ip': '35.4.1.1'}})
++
++        router[l3_constants.INTERFACE_KEY].append(
++            {'id': _uuid(),
++             'network_id': _uuid(),
++             'admin_state_up': True,
++             'fixed_ips': [{'ip_address': 'fd00::2',
++                            'subnet_id': _uuid()}],
++             'mac_address': 'ca:fe:de:ad:be:ef',
++             'subnet': {'cidr': 'fd00::/64',
++                        'gateway_ip': 'fd00::1'}})
++        # Reassign the router object to RouterInfo
++        ri.router = router
++        agent.process_router(ri)
++        # For some reason set logic does not work well with
++        # IpTablesRule instances
++        nat_rules_delta = [r for r in ri.iptables_manager.ipv4['nat'].rules
++                           if r not in orig_nat_rules]
++        self.assertEqual(1, len(nat_rules_delta))
++        self._verify_snat_rules(nat_rules_delta, router)
++
+     def test_process_router_interface_removed(self):
+         agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+         router = self._prepare_router_data(num_internal_ports=2)
index ee7bdf34658892473df64f9212c02130383ac284..40d6ae75f8256a68ff0c1b18090ec7ef9d8b41bb 100644 (file)
@@ -4,3 +4,4 @@ OVS_lib_defer_apply_doesn_t_handle_concurrency.patch
 0001-Add-parameter-and-iptables-rules-to-protect-dnsmasq-.patch
 0004-Fix-Metering-doesn-t-respect-the-l3-agent-binding.patch
 Properly_apply_column_default_in_migration_pool_monitor_status.patch
+Install_SNAT_rules_for_ipv4_only.patch