NSXv3: router intf support
Change-Id: I9182bdb879be40370e905d417d7dba07f2ae1bf9
This commit is contained in:
parent
8d26063364
commit
c485c8af31
@ -35,8 +35,6 @@ LROUTER_TYPES = [LROUTERPORT_UPLINK,
|
||||
LROUTERPORT_DOWNLINK,
|
||||
LROUTERPORT_LINK]
|
||||
|
||||
ROUTER_INTF_PORT_NAME = "Tier1-RouterDownLinkPort"
|
||||
|
||||
|
||||
def get_edge_cluster(edge_cluster_uuid):
|
||||
resource = "edge-clusters/%s" % edge_cluster_uuid
|
||||
@ -243,23 +241,6 @@ def get_logical_router_port_by_ls_id(logical_switch_id):
|
||||
operation=err_msg)
|
||||
|
||||
|
||||
def create_logical_router_port_by_ls_id(logical_router_id,
|
||||
ls_id,
|
||||
logical_switch_port_id,
|
||||
resource_type,
|
||||
address_groups):
|
||||
try:
|
||||
port = get_logical_router_port_by_ls_id(ls_id)
|
||||
except nsx_exc.ResourceNotFound:
|
||||
return create_logical_router_port(logical_router_id,
|
||||
ROUTER_INTF_PORT_NAME,
|
||||
resource_type,
|
||||
logical_switch_port_id,
|
||||
address_groups)
|
||||
else:
|
||||
return update_logical_router_port(port['id'], subnets=address_groups)
|
||||
|
||||
|
||||
def create_logical_router_port(logical_router_id,
|
||||
display_name,
|
||||
resource_type,
|
||||
|
@ -34,6 +34,7 @@ MIN_EDGE_NODE_NUM = 1
|
||||
|
||||
TIER0_ROUTER_LINK_PORT_NAME = "TIER0-RouterLinkPort"
|
||||
TIER1_ROUTER_LINK_PORT_NAME = "TIER1-RouterLinkPort"
|
||||
ROUTER_INTF_PORT_NAME = "Tier1-RouterDownLinkPort"
|
||||
|
||||
|
||||
def validate_tier0(tier0_groups_dict, tier0_uuid):
|
||||
@ -126,3 +127,20 @@ def add_gw_snat_rule(logical_router_id, gw_ip):
|
||||
def update_router_edge_cluster(nsx_router_id, edge_cluster_uuid):
|
||||
return nsxlib.update_logical_router(nsx_router_id,
|
||||
edge_cluster_id=edge_cluster_uuid)
|
||||
|
||||
|
||||
def create_logical_router_intf_port_by_ls_id(logical_router_id,
|
||||
ls_id,
|
||||
logical_switch_port_id,
|
||||
address_groups):
|
||||
try:
|
||||
port = nsxlib.get_logical_router_port_by_ls_id(ls_id)
|
||||
except nsx_exc.ResourceNotFound:
|
||||
return nsxlib.create_logical_router_port(logical_router_id,
|
||||
ROUTER_INTF_PORT_NAME,
|
||||
nsxlib.LROUTERPORT_DOWNLINK,
|
||||
logical_switch_port_id,
|
||||
address_groups)
|
||||
else:
|
||||
return nsxlib.update_logical_router_port(
|
||||
port['id'], subnets=address_groups)
|
||||
|
@ -763,26 +763,54 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
address_groups.append(address_group)
|
||||
return (ports, address_groups)
|
||||
|
||||
def _validate_multiple_subnets_diff_routers(self, context, network_id):
|
||||
port_filters = {'device_owner': [l3_db.DEVICE_OWNER_ROUTER_INTF],
|
||||
'network_id': [network_id]}
|
||||
intf_ports = self.get_ports(context.elevated(), filters=port_filters)
|
||||
router_ids = [port['device_id'] for port in intf_ports]
|
||||
router_id_set = set(router_ids)
|
||||
if len(router_id_set) >= 2:
|
||||
err_msg = _("Subnets on network %s cannot be attached to "
|
||||
"different routers") % network_id
|
||||
raise n_exc.InvalidInput(error_message=err_msg)
|
||||
|
||||
def add_router_interface(self, context, router_id, interface_info):
|
||||
# TODO(berlin): disallow multiple subnets attached to different routers
|
||||
|
||||
info = super(NsxV3Plugin, self).add_router_interface(
|
||||
context, router_id, interface_info)
|
||||
subnet = self.get_subnet(context, info['subnet_ids'][0])
|
||||
port = self.get_port(context, info['port_id'])
|
||||
network_id = subnet['network_id']
|
||||
nsx_net_id, nsx_port_id = nsx_db.get_nsx_switch_and_port_id(
|
||||
context.session, port['id'])
|
||||
try:
|
||||
subnet = self.get_subnet(context, info['subnet_ids'][0])
|
||||
port = self.get_port(context, info['port_id'])
|
||||
network_id = subnet['network_id']
|
||||
# disallow multiple subnets belong to same network being attached
|
||||
# to different routers
|
||||
self._validate_multiple_subnets_diff_routers(context, network_id)
|
||||
nsx_net_id, nsx_port_id = nsx_db.get_nsx_switch_and_port_id(
|
||||
context.session, port['id'])
|
||||
|
||||
nsx_router_id = nsx_db.get_nsx_router_id(context.session,
|
||||
router_id)
|
||||
_ports, address_groups = self._get_ports_and_address_groups(
|
||||
context, router_id, network_id)
|
||||
nsxlib.create_logical_router_port_by_ls_id(
|
||||
logical_router_id=nsx_router_id,
|
||||
ls_id=nsx_net_id,
|
||||
logical_switch_port_id=nsx_port_id,
|
||||
resource_type="LogicalRouterDownLinkPort",
|
||||
address_groups=address_groups)
|
||||
nsx_router_id = nsx_db.get_nsx_router_id(context.session,
|
||||
router_id)
|
||||
_ports, address_groups = self._get_ports_and_address_groups(
|
||||
context, router_id, network_id)
|
||||
routerlib.create_logical_router_intf_port_by_ls_id(
|
||||
logical_router_id=nsx_router_id,
|
||||
ls_id=nsx_net_id,
|
||||
logical_switch_port_id=nsx_port_id,
|
||||
address_groups=address_groups)
|
||||
|
||||
router_db = self._get_router(context, router_id)
|
||||
if router_db.gw_port and not router_db.enable_snat:
|
||||
# TODO(berlin): Announce the subnet on tier0 if enable_snat
|
||||
# is False
|
||||
pass
|
||||
except n_exc.InvalidInput:
|
||||
with excutils.save_and_reraise_exception():
|
||||
super(NsxV3Plugin, self).remove_router_interface(
|
||||
context, router_id, interface_info)
|
||||
except nsx_exc.ManagerError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.remove_router_interface(
|
||||
context, router_id, interface_info)
|
||||
return info
|
||||
|
||||
def remove_router_interface(self, context, router_id, interface_info):
|
||||
@ -816,6 +844,12 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
raise l3.RouterInterfaceNotFoundForSubnet(router_id=router_id,
|
||||
subnet_id=subnet_id)
|
||||
try:
|
||||
# TODO(berlin): Revocate announce the subnet on tier0 if
|
||||
# enable_snat is False
|
||||
router_db = self._get_router(context, router_id)
|
||||
if router_db.gw_port and not router_db.enable_snat:
|
||||
pass
|
||||
|
||||
nsx_net_id, _nsx_port_id = nsx_db.get_nsx_switch_and_port_id(
|
||||
context.session, port_id)
|
||||
subnet = self.get_subnet(context, subnet_id)
|
||||
|
@ -18,6 +18,7 @@ from oslo_config import cfg
|
||||
import six
|
||||
|
||||
from neutron.api.v2 import attributes
|
||||
from neutron.common import exceptions as n_exc
|
||||
from neutron import context
|
||||
from neutron.extensions import external_net
|
||||
from neutron.extensions import extraroute
|
||||
@ -188,11 +189,11 @@ class L3NatTest(test_l3_plugin.L3BaseForIntTests, NsxPluginV3TestCase):
|
||||
ext_mgr = ext_mgr or TestL3ExtensionManager()
|
||||
super(L3NatTest, self).setUp(
|
||||
plugin=plugin, ext_mgr=ext_mgr, service_plugins=service_plugins)
|
||||
plugin_instance = manager.NeutronManager.get_plugin()
|
||||
self.plugin_instance = manager.NeutronManager.get_plugin()
|
||||
self._plugin_name = "%s.%s" % (
|
||||
plugin_instance.__module__,
|
||||
plugin_instance.__class__.__name__)
|
||||
self._plugin_class = plugin_instance.__class__
|
||||
self.plugin_instance.__module__,
|
||||
self.plugin_instance.__class__.__name__)
|
||||
self._plugin_class = self.plugin_instance.__class__
|
||||
nsxlib.create_logical_port = self.v3_mock.create_logical_port
|
||||
nsxlib.create_logical_router = self.v3_mock.create_logical_router
|
||||
nsxlib.update_logical_router = self.v3_mock.update_logical_router
|
||||
@ -251,6 +252,33 @@ class TestL3NatTestCase(L3NatTest,
|
||||
def test_floatingip_with_invalid_create_port(self):
|
||||
self._test_floatingip_with_invalid_create_port(self._plugin_name)
|
||||
|
||||
def test_routes_update_for_multiple_routers(self):
|
||||
self.skipTest('not supported')
|
||||
|
||||
def test_floatingip_multi_external_one_internal(self):
|
||||
self.skipTest('not supported')
|
||||
|
||||
def test_multiple_subnets_on_different_routers(self):
|
||||
with self.network() as network:
|
||||
with self.subnet(network=network) as s1,\
|
||||
self.subnet(network=network,
|
||||
cidr='11.0.0.0/24') as s2,\
|
||||
self.router() as r1,\
|
||||
self.router() as r2:
|
||||
self._router_interface_action('add', r1['router']['id'],
|
||||
s1['subnet']['id'], None)
|
||||
self.assertRaises(n_exc.InvalidInput,
|
||||
self.plugin_instance.add_router_interface,
|
||||
context.get_admin_context(),
|
||||
r2['router']['id'],
|
||||
{'subnet_id': s2['subnet']['id']})
|
||||
self._router_interface_action('remove', r1['router']['id'],
|
||||
s1['subnet']['id'], None)
|
||||
self._router_interface_action('add', r2['router']['id'],
|
||||
s2['subnet']['id'], None)
|
||||
self._router_interface_action('remove', r2['router']['id'],
|
||||
s2['subnet']['id'], None)
|
||||
|
||||
|
||||
class ExtGwModeTestCase(L3NatTest,
|
||||
test_ext_gw_mode.ExtGwModeIntTestCase):
|
||||
|
Loading…
Reference in New Issue
Block a user