Merge "NSXv3: router intf support"

This commit is contained in:
Jenkins 2015-09-14 16:10:59 +00:00 committed by Gerrit Code Review
commit 9f709d7612
4 changed files with 100 additions and 39 deletions

View File

@ -35,8 +35,6 @@ LROUTER_TYPES = [LROUTERPORT_UPLINK,
LROUTERPORT_DOWNLINK, LROUTERPORT_DOWNLINK,
LROUTERPORT_LINK] LROUTERPORT_LINK]
ROUTER_INTF_PORT_NAME = "Tier1-RouterDownLinkPort"
def get_edge_cluster(edge_cluster_uuid): def get_edge_cluster(edge_cluster_uuid):
resource = "edge-clusters/%s" % 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) 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, def create_logical_router_port(logical_router_id,
display_name, display_name,
resource_type, resource_type,

View File

@ -34,6 +34,7 @@ MIN_EDGE_NODE_NUM = 1
TIER0_ROUTER_LINK_PORT_NAME = "TIER0-RouterLinkPort" TIER0_ROUTER_LINK_PORT_NAME = "TIER0-RouterLinkPort"
TIER1_ROUTER_LINK_PORT_NAME = "TIER1-RouterLinkPort" TIER1_ROUTER_LINK_PORT_NAME = "TIER1-RouterLinkPort"
ROUTER_INTF_PORT_NAME = "Tier1-RouterDownLinkPort"
def validate_tier0(tier0_groups_dict, tier0_uuid): 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): def update_router_edge_cluster(nsx_router_id, edge_cluster_uuid):
return nsxlib.update_logical_router(nsx_router_id, return nsxlib.update_logical_router(nsx_router_id,
edge_cluster_id=edge_cluster_uuid) 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)

View File

@ -797,13 +797,28 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2,
address_groups.append(address_group) address_groups.append(address_group)
return (ports, address_groups) 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): 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( info = super(NsxV3Plugin, self).add_router_interface(
context, router_id, interface_info) context, router_id, interface_info)
try:
subnet = self.get_subnet(context, info['subnet_ids'][0]) subnet = self.get_subnet(context, info['subnet_ids'][0])
port = self.get_port(context, info['port_id']) port = self.get_port(context, info['port_id'])
network_id = subnet['network_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( nsx_net_id, nsx_port_id = nsx_db.get_nsx_switch_and_port_id(
context.session, port['id']) context.session, port['id'])
@ -811,12 +826,25 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2,
router_id) router_id)
_ports, address_groups = self._get_ports_and_address_groups( _ports, address_groups = self._get_ports_and_address_groups(
context, router_id, network_id) context, router_id, network_id)
nsxlib.create_logical_router_port_by_ls_id( routerlib.create_logical_router_intf_port_by_ls_id(
logical_router_id=nsx_router_id, logical_router_id=nsx_router_id,
ls_id=nsx_net_id, ls_id=nsx_net_id,
logical_switch_port_id=nsx_port_id, logical_switch_port_id=nsx_port_id,
resource_type="LogicalRouterDownLinkPort",
address_groups=address_groups) 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 return info
def remove_router_interface(self, context, router_id, interface_info): def remove_router_interface(self, context, router_id, interface_info):
@ -850,6 +878,12 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2,
raise l3.RouterInterfaceNotFoundForSubnet(router_id=router_id, raise l3.RouterInterfaceNotFoundForSubnet(router_id=router_id,
subnet_id=subnet_id) subnet_id=subnet_id)
try: 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( nsx_net_id, _nsx_port_id = nsx_db.get_nsx_switch_and_port_id(
context.session, port_id) context.session, port_id)
subnet = self.get_subnet(context, subnet_id) subnet = self.get_subnet(context, subnet_id)

View File

@ -18,6 +18,7 @@ from oslo_config import cfg
import six import six
from neutron.api.v2 import attributes from neutron.api.v2 import attributes
from neutron.common import exceptions as n_exc
from neutron import context from neutron import context
from neutron.extensions import external_net from neutron.extensions import external_net
from neutron.extensions import extraroute from neutron.extensions import extraroute
@ -188,11 +189,11 @@ class L3NatTest(test_l3_plugin.L3BaseForIntTests, NsxPluginV3TestCase):
ext_mgr = ext_mgr or TestL3ExtensionManager() ext_mgr = ext_mgr or TestL3ExtensionManager()
super(L3NatTest, self).setUp( super(L3NatTest, self).setUp(
plugin=plugin, ext_mgr=ext_mgr, service_plugins=service_plugins) 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" % ( self._plugin_name = "%s.%s" % (
plugin_instance.__module__, self.plugin_instance.__module__,
plugin_instance.__class__.__name__) self.plugin_instance.__class__.__name__)
self._plugin_class = plugin_instance.__class__ self._plugin_class = self.plugin_instance.__class__
nsxlib.create_logical_port = self.v3_mock.create_logical_port nsxlib.create_logical_port = self.v3_mock.create_logical_port
nsxlib.create_logical_router = self.v3_mock.create_logical_router nsxlib.create_logical_router = self.v3_mock.create_logical_router
nsxlib.update_logical_router = self.v3_mock.update_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): def test_floatingip_with_invalid_create_port(self):
self._test_floatingip_with_invalid_create_port(self._plugin_name) 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, class ExtGwModeTestCase(L3NatTest,
test_ext_gw_mode.ExtGwModeIntTestCase): test_ext_gw_mode.ExtGwModeIntTestCase):