Merge "NSXv3: router intf support"
This commit is contained in:
commit
9f709d7612
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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):
|
||||||
|
Loading…
Reference in New Issue
Block a user