Merge "By default, add floating IP NAT rules to each vnic on router"
This commit is contained in:
commit
854fb2098f
@ -631,6 +631,12 @@ nsxv_opts = [
|
||||
help=_("(Optional) Sets the network address for distributed "
|
||||
"router TLR-PLR connectivity, with "
|
||||
"<network IP>/<prefix> syntax")),
|
||||
cfg.BoolOpt('bind_floatingip_to_all_interfaces', default=True,
|
||||
help=_("If set to False, router will associate floating ip "
|
||||
"with external interface of only, thus denying "
|
||||
"connectivity between hosts on same network via "
|
||||
"their floating ips. If True, floating ip will "
|
||||
"be associated with all router interfaces.")),
|
||||
]
|
||||
|
||||
# Register the configuration options
|
||||
|
@ -213,9 +213,12 @@ class RouterSharedDriver(router_driver.RouterBaseDriver):
|
||||
snat, dnat = self.plugin._get_nat_rules(context, router)
|
||||
snats.extend(snat)
|
||||
dnats.extend(dnat)
|
||||
if len(dnat) > 0:
|
||||
if (not cfg.CONF.nsxv.bind_floatingip_to_all_interfaces and
|
||||
len(dnat) > 0):
|
||||
# Copy each DNAT rule to all vnics of the other routers,
|
||||
# to allow NAT-ed traffic between routers
|
||||
# no need for that if bind_floatingip_to_all_interfaces
|
||||
# is on (default)
|
||||
other_vnics = []
|
||||
for other_router_id in router_ids:
|
||||
if other_router_id != router_id:
|
||||
|
@ -539,14 +539,15 @@ class EdgeApplianceDriver(object):
|
||||
|
||||
def _assemble_nat_rule(self, action, original_address,
|
||||
translated_address,
|
||||
vnic_index=constants.EXTERNAL_VNIC_INDEX,
|
||||
vnic_index=None,
|
||||
enabled=True,
|
||||
protocol='any',
|
||||
original_port='any',
|
||||
translated_port='any'):
|
||||
nat_rule = {}
|
||||
nat_rule['action'] = action
|
||||
nat_rule['vnic'] = vnic_index
|
||||
if vnic_index is not None:
|
||||
nat_rule['vnic'] = vnic_index
|
||||
nat_rule['originalAddress'] = original_address
|
||||
nat_rule['translatedAddress'] = translated_address
|
||||
nat_rule['enabled'] = enabled
|
||||
@ -564,31 +565,57 @@ class EdgeApplianceDriver(object):
|
||||
e.response)
|
||||
raise e
|
||||
|
||||
def update_nat_rules(self, edge_id, snats, dnats):
|
||||
def update_nat_rules(self, edge_id, snats, dnats, indices=None):
|
||||
LOG.debug("VCNS: update nat rule\n"
|
||||
"SNAT:%(snat)s\n"
|
||||
"DNAT:%(dnat)s\n", {
|
||||
'snat': snats, 'dnat': dnats})
|
||||
"DNAT:%(dnat)s\n"
|
||||
"INDICES: %(index)s\n", {
|
||||
'snat': snats, 'dnat': dnats, 'index': indices})
|
||||
nat_rules = []
|
||||
|
||||
for dnat in dnats:
|
||||
vnic_index = constants.EXTERNAL_VNIC_INDEX
|
||||
vnic_index = None
|
||||
if 'vnic_index' in dnat:
|
||||
vnic_index = dnat['vnic_index']
|
||||
nat_rules.append(self._assemble_nat_rule(
|
||||
'dnat', dnat['dst'], dnat['translated'], vnic_index=vnic_index
|
||||
))
|
||||
nat_rules.append(self._assemble_nat_rule(
|
||||
'snat', dnat['translated'], dnat['dst'], vnic_index=vnic_index
|
||||
))
|
||||
if vnic_index or not indices:
|
||||
# we are adding a predefined index or
|
||||
# adding to all interfaces
|
||||
nat_rules.append(self._assemble_nat_rule(
|
||||
'dnat', dnat['dst'], dnat['translated'],
|
||||
vnic_index=vnic_index
|
||||
))
|
||||
nat_rules.append(self._assemble_nat_rule(
|
||||
'snat', dnat['translated'], dnat['dst'],
|
||||
vnic_index=vnic_index
|
||||
))
|
||||
else:
|
||||
for index in indices:
|
||||
nat_rules.append(self._assemble_nat_rule(
|
||||
'dnat', dnat['dst'], dnat['translated'],
|
||||
vnic_index=index
|
||||
))
|
||||
nat_rules.append(self._assemble_nat_rule(
|
||||
'snat', dnat['translated'], dnat['dst'],
|
||||
vnic_index=index
|
||||
))
|
||||
|
||||
for snat in snats:
|
||||
vnic_index = constants.EXTERNAL_VNIC_INDEX
|
||||
vnic_index = None
|
||||
if 'vnic_index' in snat:
|
||||
vnic_index = snat['vnic_index']
|
||||
nat_rules.append(self._assemble_nat_rule(
|
||||
'snat', snat['src'], snat['translated'], vnic_index=vnic_index
|
||||
))
|
||||
if vnic_index or not indices:
|
||||
# we are adding a predefined index
|
||||
# or adding to all interfaces
|
||||
nat_rules.append(self._assemble_nat_rule(
|
||||
'snat', snat['src'], snat['translated'],
|
||||
vnic_index=vnic_index
|
||||
))
|
||||
else:
|
||||
for index in indices:
|
||||
nat_rules.append(self._assemble_nat_rule(
|
||||
'snat', snat['src'], snat['translated'],
|
||||
vnic_index=index
|
||||
))
|
||||
|
||||
nat = {
|
||||
'featureType': 'nat',
|
||||
|
@ -2299,7 +2299,29 @@ def _delete_interface(nsxv_manager, context, router_id, network_id,
|
||||
def update_nat_rules(nsxv_manager, context, router_id, snat, dnat):
|
||||
binding = nsxv_db.get_nsxv_router_binding(context.session, router_id)
|
||||
if binding:
|
||||
nsxv_manager.update_nat_rules(binding['edge_id'], snat, dnat)
|
||||
bind_to_all = cfg.CONF.nsxv.bind_floatingip_to_all_interfaces
|
||||
|
||||
indices = None
|
||||
if bind_to_all:
|
||||
# from 6.2.4 onwards, unspecified vnic will result
|
||||
# in binding the rule to all interfaces
|
||||
ver = nsxv_manager.vcns.get_version()
|
||||
if version.LooseVersion(ver) < version.LooseVersion('6.2.4'):
|
||||
LOG.debug("NSX version %s requires explicit nat rule "
|
||||
"for each interface", ver)
|
||||
edge_id = binding['edge_id']
|
||||
vnic_bindings = nsxv_db.get_edge_vnic_bindings_by_edge(
|
||||
context.session, edge_id)
|
||||
indices = [vnic_binding.vnic_index
|
||||
for vnic_binding in vnic_bindings]
|
||||
|
||||
indices.append(vcns_const.EXTERNAL_VNIC_INDEX)
|
||||
else:
|
||||
LOG.debug("Configuring nat rules on external "
|
||||
"interface only for %s", router_id)
|
||||
indices = [vcns_const.EXTERNAL_VNIC_INDEX]
|
||||
|
||||
nsxv_manager.update_nat_rules(binding['edge_id'], snat, dnat, indices)
|
||||
else:
|
||||
LOG.warning(_LW("Bindings do not exists for %s"), router_id)
|
||||
|
||||
|
@ -411,6 +411,7 @@ class VcnsDriverTestCase(base.BaseTestCase):
|
||||
'translated': '192.168.2.1'
|
||||
}
|
||||
]
|
||||
|
||||
result = self.vcns_driver.update_nat_rules(self.edge_id, snats, dnats)
|
||||
self.assertTrue(result)
|
||||
|
||||
@ -425,6 +426,97 @@ class VcnsDriverTestCase(base.BaseTestCase):
|
||||
self.natEquals(rules[5], snats[1])
|
||||
self.natEquals(rules[6], snats[2])
|
||||
|
||||
def test_update_nat_rules_for_all_vnics(self):
|
||||
self._deploy_edge()
|
||||
snats = [{
|
||||
'src': '192.168.1.0/24',
|
||||
'translated': '10.0.0.1'
|
||||
}, {
|
||||
'src': '192.168.2.0/24',
|
||||
'translated': '10.0.0.2'
|
||||
}, {
|
||||
'src': '192.168.3.0/24',
|
||||
'translated': '10.0.0.3'
|
||||
}
|
||||
]
|
||||
dnats = [{
|
||||
'dst': '100.0.0.4',
|
||||
'translated': '192.168.1.1'
|
||||
}, {
|
||||
'dst': '100.0.0.5',
|
||||
'translated': '192.168.2.1'
|
||||
}
|
||||
]
|
||||
|
||||
indices = [0, 1, 2, 3]
|
||||
result = self.vcns_driver.update_nat_rules(self.edge_id,
|
||||
snats, dnats, indices)
|
||||
self.assertTrue(result)
|
||||
|
||||
natcfg = self.vcns_driver.get_nat_config(self.edge_id)
|
||||
rules = natcfg['rules']['natRulesDtos']
|
||||
|
||||
self.assertEqual(len(rules), 2 * len(indices) * len(dnats)
|
||||
+ len(indices) * len(snats))
|
||||
|
||||
sorted_rules = sorted(rules, key=lambda k: k['vnic'])
|
||||
for i in range(0, len(sorted_rules), 7):
|
||||
self.natEquals(sorted_rules[i], dnats[0])
|
||||
self.natEquals(sorted_rules[i + 1], self.snat_for_dnat(dnats[0]))
|
||||
self.natEquals(sorted_rules[i + 2], dnats[1])
|
||||
self.natEquals(sorted_rules[i + 3], self.snat_for_dnat(dnats[1]))
|
||||
self.natEquals(sorted_rules[i + 4], snats[0])
|
||||
self.natEquals(sorted_rules[i + 5], snats[1])
|
||||
self.natEquals(sorted_rules[i + 6], snats[2])
|
||||
|
||||
def test_update_nat_rules_for_specific_vnics(self):
|
||||
self._deploy_edge()
|
||||
snats = [{
|
||||
'src': '192.168.1.0/24',
|
||||
'translated': '10.0.0.1',
|
||||
'vnic_index': 5
|
||||
}, {
|
||||
'src': '192.168.2.0/24',
|
||||
'translated': '10.0.0.2'
|
||||
}, {
|
||||
'src': '192.168.3.0/24',
|
||||
'translated': '10.0.0.3'
|
||||
}
|
||||
]
|
||||
dnats = [{
|
||||
'dst': '100.0.0.4',
|
||||
'translated': '192.168.1.1',
|
||||
'vnic_index': 2
|
||||
}, {
|
||||
'dst': '100.0.0.5',
|
||||
'translated': '192.168.2.1'
|
||||
}
|
||||
]
|
||||
|
||||
result = self.vcns_driver.update_nat_rules(self.edge_id, snats, dnats)
|
||||
self.assertTrue(result)
|
||||
|
||||
natcfg = self.vcns_driver.get_nat_config(self.edge_id)
|
||||
|
||||
rules = natcfg['rules']['natRulesDtos']
|
||||
|
||||
self.assertEqual(len(rules), 2 * len(dnats) + len(snats))
|
||||
|
||||
self.natEquals(rules[0], dnats[0])
|
||||
self.assertEqual(rules[0]['vnic'], 2)
|
||||
self.natEquals(rules[1], self.snat_for_dnat(dnats[0]))
|
||||
self.assertEqual(rules[1]['vnic'], 2)
|
||||
self.natEquals(rules[2], dnats[1])
|
||||
self.assertNotIn('vnic', rules[2])
|
||||
self.natEquals(rules[3], self.snat_for_dnat(dnats[1]))
|
||||
self.assertNotIn('vnic', rules[3])
|
||||
self.natEquals(rules[4], snats[0])
|
||||
self.assertEqual(rules[4]['vnic'], 5)
|
||||
self.natEquals(rules[5], snats[1])
|
||||
self.assertNotIn('vnic', rules[5])
|
||||
self.natEquals(rules[6], snats[2])
|
||||
self.assertNotIn('vnic', rules[6])
|
||||
|
||||
def snat_for_dnat(self, dnat):
|
||||
return {
|
||||
'src': dnat['translated'],
|
||||
|
Loading…
x
Reference in New Issue
Block a user