Remove iptables assumption that all routers have external networks

In order to remove the auto-addition of external networks, we need
to remove the assumption in the appliance that all routers have one.
This avoids adding external network related iptables rules when the
router config does not have an external port.

Change-Id: Ifaf53a26f6d89da199101f386f4674c9f39f8326
This commit is contained in:
Adam Gandelman 2016-03-02 11:57:38 -08:00
parent 0dc45a3fd8
commit 33ee88897c
3 changed files with 59 additions and 34 deletions

View File

@ -118,7 +118,10 @@ class IPTablesManager(base.Manager):
:rtype: astara_router.models.Network
'''
return self.networks_by_type(config, Network.TYPE_EXTERNAL)[0]
try:
return self.networks_by_type(config, Network.TYPE_EXTERNAL)[0]
except IndexError:
return None
def get_management_network(self, config):
'''
@ -219,7 +222,11 @@ class IPTablesManager(base.Manager):
Add rules specific to private tenant networks.
'''
rules = []
ext_if = self.get_external_network(config).interface
ext_net = self.get_external_network(config)
if ext_net:
ext_if = ext_net.interface
else:
ext_if = None
for network in self.get_internal_networks(config):
@ -245,10 +252,11 @@ class IPTablesManager(base.Manager):
rules.append(Rule(
'-A INPUT -i %s -j ACCEPT' % network.interface.ifname
))
rules.append(Rule(
'-A INPUT -i %s -m state '
'--state RELATED,ESTABLISHED -j ACCEPT' % ext_if.ifname
))
if ext_if:
rules.append(Rule(
'-A INPUT -i %s -m state '
'--state RELATED,ESTABLISHED -j ACCEPT' % ext_if.ifname
))
rules.append(Rule('COMMIT'))
return rules
@ -271,6 +279,7 @@ class IPTablesManager(base.Manager):
])
rules.extend(self._build_floating_ips(config))
rules.extend(self._build_v4_nat(config))
rules.append(Rule('COMMIT', ip_version=4))
@ -296,12 +305,14 @@ class IPTablesManager(base.Manager):
))
# Add a masquerade catch-all for VMs without floating IPs
ext_if = self.get_external_network(config).interface
rules.append(Rule(
'-A POSTROUTING -o %s -j MASQUERADE' % (
ext_if.ifname
), ip_version=4
))
ext_net = self.get_external_network(config)
if ext_net:
ext_if = ext_net.interface
rules.append(Rule(
'-A POSTROUTING -o %s -j MASQUERADE' % (
ext_if.ifname
), ip_version=4
))
return rules
@ -310,23 +321,29 @@ class IPTablesManager(base.Manager):
Add rules for neutron FloatingIPs.
'''
rules = []
ext_if = self.get_external_network(config).interface
ext_net = self.get_external_network(config)
if ext_net:
ext_if = ext_net.interface
else:
return []
# NAT floating IP addresses
for fip in self.get_external_network(config).floating_ips:
for fip in ext_net.floating_ips:
# Neutron has a bug whereby you can create a floating ip that has
# mixed IP versions between the fixed and floating address. If
# people create these accidentally, just ignore them (because
# iptables will barf if it encounters them)
if fip.fixed_ip.version == fip.floating_ip.version:
rules.append(Rule(
'-A PREROUTING -i %s -d %s -j DNAT --to-destination %s' % (
ext_if.ifname,
fip.floating_ip,
fip.fixed_ip
), ip_version=4
))
if ext_if:
rules.append(Rule(
'-A PREROUTING -i %s -d %s -j DNAT --to-destination %s'
% (
ext_if.ifname,
fip.floating_ip,
fip.fixed_ip
), ip_version=4
))
for network in self.get_internal_networks(config):
rules.append(Rule(
'-A PREROUTING -i %s -d %s -j DNAT '
@ -354,6 +371,10 @@ class IPTablesManager(base.Manager):
Build a chain for SNAT for neutron FloatingIPs. This chain ignores NAT
for traffic marked as private.
'''
external_network = self.get_external_network(config)
if not external_network:
return []
rules = [
Rule(':PUBLIC_SNAT - [0:0]', ip_version=4),
Rule(
@ -362,8 +383,6 @@ class IPTablesManager(base.Manager):
)
]
external_network = self.get_external_network(config)
# NAT floating IP addresses
for fip in external_network.floating_ips:
@ -414,11 +433,13 @@ class IPTablesManager(base.Manager):
Rule(':FORWARD - [0:0]', ip_version=4),
Rule(':PREROUTING - [0:0]', ip_version=4)
]
ext_if = self.get_external_network(config).interface
rules.append(Rule(
'-A PREROUTING -i %s -j MARK --set-mark 0xACDA' % ext_if.ifname,
ip_version=4
))
ext_net = self.get_external_network(config)
if ext_net:
ext_if = ext_net.interface
rules.append(Rule(
'-A PREROUTING -i %s -j MARK --set-mark 0xACDA' %
ext_if.ifname, ip_version=4
))
for network in self.networks_by_type(config, Network.TYPE_INTERNAL):
if network.interface.first_v4:

View File

@ -40,9 +40,3 @@ console_scripts =
all_files = 1
build-dir = doc/build
source-dir = doc/source
[nosetests]
where = test
verbosity = 2
detailed-errors = 1
cover-package = astara_router

View File

@ -205,3 +205,13 @@ class TestIPTablesRouterConfiguration(TestCase):
'-A POSTROUTING -s 192.168.0.0/24 -j PUBLIC_SNAT'
]
assert mgr._build_floating_ips(config) == []
@mock.patch.object(iptables.IPTablesManager, 'get_external_network')
def test_no_ext_port(self, fake_get_ext_net):
fake_get_ext_net.return_value = None
mgr = iptables.IPTablesManager()
mgr.save_config(CONFIG, {
'ge0': 'eth0',
'ge1': 'eth1',
'ge2': 'eth2'
})