NSXv: Make VDR transit net configurable

Allow the admin to set a global CIDR for VDR transit network which
connect the TLR with the PLR.
Value is global: set at the config file and will be used for all the
VDRs.

Change-Id: Idb0ac4c5629cfc00bb2c434a1771b4c4a551071e
This commit is contained in:
Kobi Samoray 2016-11-15 12:06:46 +02:00
parent e8b840f769
commit 2b1f21cbcb
8 changed files with 143 additions and 30 deletions

View File

@ -627,6 +627,10 @@ nsxv_opts = [
help=_("(Optional) If use_nsx_policies is True, this value "
"will determine if a tenants can add rules to their "
"security groups.")),
cfg.StrOpt('vdr_transit_network', default="169.254.2.0/28",
help=_("(Optional) Sets the network address for distributed "
"router TLR-PLR connectivity, with "
"<network IP>/<prefix> syntax")),
]
# Register the configuration options

View File

@ -59,5 +59,4 @@ CSR_REQUEST = ("<csr><subject>"
# Reserved IPs that cannot overlap defined subnets
RESERVED_IPS = ["169.254.128.0/17",
"169.254.1.0/24",
"169.254.2.0/28",
"169.254.64.192/26"]

View File

@ -26,8 +26,6 @@ from vmware_nsx.db import nsxv_db
from vmware_nsx.plugins.nsx_v.drivers import (
abstract_router_driver as router_driver)
from vmware_nsx.plugins.nsx_v import plugin as nsx_v
from vmware_nsx.plugins.nsx_v.vshield.common import (
constants as vcns_const)
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
LOG = logging.getLogger(__name__)
@ -52,8 +50,7 @@ class RouterDistributedDriver(router_driver.RouterBaseDriver):
for subnet in subnets:
routes.append({
'destination': subnet,
'nexthop': (vcns_const.INTEGRATION_LR_IPADDRESS.
split('/')[0]),
'nexthop': (edge_utils.get_vdr_transit_network_tlr_address()),
'network_id': lswitch_id
})
@ -67,7 +64,7 @@ class RouterDistributedDriver(router_driver.RouterBaseDriver):
def _update_routes_on_tlr(
self, context, router_id,
newnexthop=vcns_const.INTEGRATION_EDGE_IPADDRESS,
newnexthop=edge_utils.get_vdr_transit_network_plr_address(),
metadata_gateway=None):
routes = []

View File

@ -1840,22 +1840,14 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
For the V plugin we have a limitation that we should not use
some reserved ranges like: 169.254.128.0/17 and 169.254.1.0/24
"""
reserved_subnets = nsxv_constants.RESERVED_IPS
# translate the given subnet to a range object
data = subnet['subnet']
if data['cidr'] not in (constants.ATTR_NOT_SPECIFIED, None):
range = netaddr.IPNetwork(data['cidr'])
# Check each reserved subnet for intersection
for reserved_subnet in reserved_subnets:
# translate the reserved subnet to a range object
reserved_range = netaddr.IPNetwork(reserved_subnet)
# check if new subnet overlaps this reserved subnet
if (range.first <= reserved_range.last
and reserved_range.first <= range.last):
return True
reserved_subnets = list(nsxv_constants.RESERVED_IPS)
reserved_subnets.append(cfg.CONF.nsxv.vdr_transit_network)
return edge_utils.is_overlapping_reserved_subnets(data['cidr'],
reserved_subnets)
return False
@ -3551,6 +3543,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
error = _("Configured %s not found") % field
raise nsx_exc.NsxPluginException(err_msg=error)
if cfg.CONF.nsxv.vdr_transit_network:
edge_utils.validate_vdr_transit_network()
def _handle_qos_notification(self, qos_policys, event_type):
qos_utils.handle_qos_notification(qos_policys, event_type, self._dvs)

View File

@ -40,10 +40,6 @@ MAX_TUNNEL_NUM = (cfg.CONF.nsxv.maximum_tunnels_per_vnic if
cfg.CONF.nsxv.maximum_tunnels_per_vnic > 0)
else 10)
INTEGRATION_LR_IPADDRESS = "169.254.2.1/28"
INTEGRATION_EDGE_IPADDRESS = "169.254.2.3"
INTEGRATION_SUBNET_NETMASK = "255.255.255.240"
# SNAT rule location
PREPEND = 0
APPEND = -1

View File

@ -383,8 +383,8 @@ class EdgeApplianceDriver(object):
vnic_inside = self._assemble_edge_vnic(
constants.INTERNAL_VNIC_NAME, constants.INTERNAL_VNIC_INDEX,
internal_network,
constants.INTEGRATION_EDGE_IPADDRESS,
constants.INTEGRATION_SUBNET_NETMASK,
edge_utils.get_vdr_transit_network_plr_address(),
edge_utils.get_vdr_transit_network_netmask(),
type="internal")
edge['vnics']['vnics'].append(vnic_inside)
@ -457,8 +457,8 @@ class EdgeApplianceDriver(object):
internal_vnic = self._assemble_edge_vnic(
constants.INTERNAL_VNIC_NAME, constants.INTERNAL_VNIC_INDEX,
internal_network,
constants.INTEGRATION_EDGE_IPADDRESS,
constants.INTEGRATION_SUBNET_NETMASK,
edge_utils.get_vdr_transit_network_plr_address(),
edge_utils.get_vdr_transit_network_netmask(),
type="internal")
edge['vnics']['vnics'].append(internal_vnic)
if not dist and loadbalancer_enable:

View File

@ -56,6 +56,59 @@ LOG = logging.getLogger(__name__)
_uuid = uuidutils.generate_uuid
def _get_vdr_transit_network_ipobj():
transit_net = cfg.CONF.nsxv.vdr_transit_network
return netaddr.IPNetwork(transit_net)
def get_vdr_transit_network_netmask():
ip = _get_vdr_transit_network_ipobj()
return str(ip.netmask)
def get_vdr_transit_network_tlr_address():
ip = _get_vdr_transit_network_ipobj()
return str(ip[1])
def get_vdr_transit_network_plr_address():
ip = _get_vdr_transit_network_ipobj()
return str(ip[2])
def validate_vdr_transit_network():
try:
ip = _get_vdr_transit_network_ipobj()
except Exception:
raise n_exc.Invalid(_("Invalid VDR transit network"))
if len(ip) < 4:
raise n_exc.Invalid(_("VDR transit address range too small"))
if is_overlapping_reserved_subnets(cfg.CONF.nsxv.vdr_transit_network,
nsxv_constants.RESERVED_IPS):
raise n_exc.Invalid(_("VDR transit network overlaps reserved subnet"))
def is_overlapping_reserved_subnets(cidr, reserved_subnets):
"""Return True if the subnet overlaps with reserved subnets.
For the V plugin we have a limitation that we should not use
some reserved ranges like: 169.254.128.0/17 and 169.254.1.0/24
"""
range = netaddr.IPNetwork(cidr)
# Check each reserved subnet for intersection
for reserved_subnet in reserved_subnets:
# translate the reserved subnet to a range object
reserved_range = netaddr.IPNetwork(reserved_subnet)
# check if new subnet overlaps this reserved subnet
if (range.first <= reserved_range.last
and reserved_range.first <= range.last):
return True
return False
def parse_backup_edge_pool_opt():
"""Parse edge pool opts and returns result."""
edge_pool_opts = cfg.CONF.nsxv.backup_edge_pool
@ -1523,8 +1576,8 @@ class EdgeManager(object):
# add vdr's external interface to the lswitch
tlr_vnic_index = self.nsxv_manager.add_vdr_internal_interface(
tlr_edge_id, lswitch_id,
address=vcns_const.INTEGRATION_LR_IPADDRESS.split('/')[0],
netmask=vcns_const.INTEGRATION_SUBNET_NETMASK,
address=get_vdr_transit_network_tlr_address(),
netmask=get_vdr_transit_network_netmask(),
type="uplink")
nsxv_db.create_edge_vnic_binding(
context.session, tlr_edge_id, tlr_vnic_index, lswitch_id)
@ -1548,8 +1601,8 @@ class EdgeManager(object):
#TODO(berlin): the internal ip should change based on vnic_index
self.nsxv_manager.update_interface(
plr_router['id'], plr_edge_id, plr_vnic_index, lswitch_id,
address=vcns_const.INTEGRATION_EDGE_IPADDRESS,
netmask=vcns_const.INTEGRATION_SUBNET_NETMASK)
address=get_vdr_transit_network_plr_address(),
netmask=get_vdr_transit_network_netmask())
return plr_router['id']
def delete_plr_by_tlr_id(self, context, plr_id, router_id):

View File

@ -773,3 +773,72 @@ class EdgeManagerTestCase(EdgeUtilsTestCaseMixin):
availability_zone=self.az)
self.edge_manager._free_edge_appliance(
self.ctx, 'fake_id')
class VdrTransitNetUtilDefaultTestCase(EdgeUtilsTestCaseMixin):
EXPECTED_NETMASK = '255.255.255.240'
EXPECTED_TLR_IP = '169.254.2.1'
EXPECTED_PLR_IP = '169.254.2.2'
def setUp(self):
super(VdrTransitNetUtilDefaultTestCase, self).setUp()
def test_get_vdr_transit_network_netmask(self):
self.assertEqual(edge_utils.get_vdr_transit_network_netmask(),
self.EXPECTED_NETMASK)
def test_get_vdr_transit_network_tlr_address(self):
self.assertEqual(edge_utils.get_vdr_transit_network_tlr_address(),
self.EXPECTED_TLR_IP)
def test_get_vdr_transit_network_plr_address(self):
self.assertEqual(edge_utils.get_vdr_transit_network_plr_address(),
self.EXPECTED_PLR_IP)
def test_is_overlapping_reserved_subnets(self):
self.assertTrue(
edge_utils.is_overlapping_reserved_subnets('169.254.1.0/24',
['169.254.0.0/16']))
self.assertTrue(
edge_utils.is_overlapping_reserved_subnets('169.254.1.0/24',
['192.168.2.0/24',
'169.254.0.0/16']))
self.assertFalse(
edge_utils.is_overlapping_reserved_subnets('169.254.1.0/24',
['169.253.0.0/16']))
self.assertFalse(
edge_utils.is_overlapping_reserved_subnets('169.254.1.0/24',
['192.168.2.0/24',
'169.253.0.0/16']))
class VdrTransitNetUtilTestCase(EdgeUtilsTestCaseMixin):
EXPECTED_NETMASK = '255.255.255.0'
EXPECTED_TLR_IP = '192.168.1.1'
EXPECTED_PLR_IP = '192.168.1.2'
def setUp(self):
super(VdrTransitNetUtilTestCase, self).setUp()
class VdrTransitNetValidatorTestCase(EdgeUtilsTestCaseMixin):
def setUp(self):
super(VdrTransitNetValidatorTestCase, self).setUp()
def _test_validator(self, cidr):
cfg.CONF.set_override('vdr_transit_network', cidr, 'nsxv')
return edge_utils.validate_vdr_transit_network()
def test_vdr_transit_net_validator_success(self):
self.assertIsNone(self._test_validator('192.168.253.0/24'))
def test_vdr_transit_net_validator_junk_cidr(self):
self.assertRaises(n_exc.Invalid, self._test_validator, 'not_a_subnet')
def test_vdr_transit_net_validator_too_small_cidr(self):
self.assertRaises(
n_exc.Invalid, self._test_validator, '169.254.2.0/31')
def test_vdr_transit_net_validator_overlap_cidr(self):
self.assertRaises(
n_exc.Invalid, self._test_validator, '169.254.0.0/16')