Nicira NVP plugin support for l3_ext_gw_mode extension
Bug 1121129 This patch adds support the 'configurable external gateway' extension in the NVP plugin. Change-Id: I531ebe0053b1b9e21d6f0685776acebe3173b170
This commit is contained in:
parent
69ebd0870a
commit
60a392f0aa
@ -43,8 +43,10 @@ class L3_NAT_db_mixin(l3_db.L3_NAT_db_mixin):
|
||||
'enable_snat': router.enable_snat}
|
||||
return self._fields(res, fields)
|
||||
|
||||
def _update_router_gw_info(self, context, router_id, info):
|
||||
router = self._get_router(context, router_id)
|
||||
def _update_router_gw_info(self, context, router_id, info, router=None):
|
||||
# Load the router only if necessary
|
||||
if not router:
|
||||
router = self._get_router(context, router_id)
|
||||
# if enable_snat is not specified use the value
|
||||
# stored in the database (default:True)
|
||||
enable_snat = not info or info.get('enable_snat', router.enable_snat)
|
||||
@ -54,6 +56,9 @@ class L3_NAT_db_mixin(l3_db.L3_NAT_db_mixin):
|
||||
# Calls superclass, pass router db object for avoiding re-loading
|
||||
super(L3_NAT_db_mixin, self)._update_router_gw_info(
|
||||
context, router_id, info, router=router)
|
||||
# Returning the router might come back useful if this
|
||||
# method is overriden in child classes
|
||||
return router
|
||||
|
||||
def _build_routers_list(self, routers, gw_ports):
|
||||
gw_port_id_gw_port_dict = {}
|
||||
|
@ -34,6 +34,7 @@ migration_for_plugins = [
|
||||
'neutron.plugins.linuxbridge.lb_neutron_plugin.LinuxBridgePluginV2',
|
||||
'neutron.plugins.metaplugin.meta_neutron_plugin.MetaPluginV2',
|
||||
'neutron.plugins.nec.nec_plugin.NECPluginV2',
|
||||
'neutron.plugins.nicira.NeutronPlugin.NvpPluginV2',
|
||||
'neutron.plugins.openvswitch.ovs_neutron_plugin.OVSNeutronPluginV2',
|
||||
'neutron.plugins.ryu.ryu_neutron_plugin.RyuNeutronPluginV2'
|
||||
]
|
||||
|
@ -44,6 +44,7 @@ from neutron.db import db_base_plugin_v2
|
||||
from neutron.db import dhcp_rpc_base
|
||||
from neutron.db import extraroute_db
|
||||
from neutron.db import l3_db
|
||||
from neutron.db import l3_gwmode_db
|
||||
from neutron.db import models_v2
|
||||
from neutron.db import portsecurity_db
|
||||
from neutron.db import quota_db # noqa
|
||||
@ -73,6 +74,7 @@ from neutron.plugins.nicira import nvplib
|
||||
|
||||
|
||||
LOG = logging.getLogger("NeutronPlugin")
|
||||
|
||||
NVP_NOSNAT_RULES_ORDER = 10
|
||||
NVP_FLOATINGIP_NAT_RULES_ORDER = 224
|
||||
NVP_EXTGW_NAT_RULES_ORDER = 255
|
||||
@ -127,6 +129,7 @@ class NVPRpcCallbacks(dhcp_rpc_base.DhcpRpcCallbackMixin):
|
||||
|
||||
class NvpPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
extraroute_db.ExtraRoute_db_mixin,
|
||||
l3_gwmode_db.L3_NAT_db_mixin,
|
||||
portsecurity_db.PortSecurityDbMixin,
|
||||
securitygroups_db.SecurityGroupDbMixin,
|
||||
mac_db.MacLearningDbMixin,
|
||||
@ -141,7 +144,8 @@ class NvpPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
functionality using NVP.
|
||||
"""
|
||||
|
||||
supported_extension_aliases = ["extraroute",
|
||||
supported_extension_aliases = ["ext_gw_mode",
|
||||
"extraroute",
|
||||
"mac-learning",
|
||||
"network-gateway",
|
||||
"nvp-qos",
|
||||
@ -278,6 +282,58 @@ class NvpPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
attachment_vlan)
|
||||
return lrouter_port
|
||||
|
||||
def _update_router_gw_info(self, context, router_id, info):
|
||||
# NOTE(salvatore-orlando): We need to worry about rollback of NVP
|
||||
# configuration in case of failures in the process
|
||||
# Ref. LP bug 1102301
|
||||
router = self._get_router(context, router_id)
|
||||
# Check whether SNAT rule update should be triggered
|
||||
# NVP also supports multiple external networks so there is also
|
||||
# the possibility that NAT rules should be replaced
|
||||
current_ext_net_id = router.gw_port_id and router.gw_port.network_id
|
||||
new_ext_net_id = info and info.get('network_id')
|
||||
# SNAT should be enabled unless info['enable_snat'] is
|
||||
# explicitly set to false
|
||||
enable_snat = new_ext_net_id and info.get('enable_snat', True)
|
||||
# Remove if ext net removed, changed, or if snat disabled
|
||||
remove_snat_rules = (current_ext_net_id and
|
||||
new_ext_net_id != current_ext_net_id or
|
||||
router.enable_snat and not enable_snat)
|
||||
# Add rules if snat is enabled, and if either the external network
|
||||
# changed or snat was previously disabled
|
||||
# NOTE: enable_snat == True implies new_ext_net_id != None
|
||||
add_snat_rules = (enable_snat and
|
||||
(new_ext_net_id != current_ext_net_id or
|
||||
not router.enable_snat))
|
||||
router = super(NvpPluginV2, self)._update_router_gw_info(
|
||||
context, router_id, info, router=router)
|
||||
# Add/Remove SNAT rules as needed
|
||||
# Create an elevated context for dealing with metadata access
|
||||
# cidrs which are created within admin context
|
||||
ctx_elevated = context.elevated()
|
||||
if remove_snat_rules or add_snat_rules:
|
||||
cidrs = self._find_router_subnets_cidrs(ctx_elevated, router_id)
|
||||
if remove_snat_rules:
|
||||
# Be safe and concede NAT rules might not exist.
|
||||
# Therefore use min_num_expected=0
|
||||
for cidr in cidrs:
|
||||
nvplib.delete_nat_rules_by_match(
|
||||
self.cluster, router_id, "SourceNatRule",
|
||||
max_num_expected=1, min_num_expected=0,
|
||||
source_ip_addresses=cidr)
|
||||
if add_snat_rules:
|
||||
ip_addresses = self._build_ip_address_list(
|
||||
ctx_elevated, router.gw_port['fixed_ips'])
|
||||
# Set the SNAT rule for each subnet (only first IP)
|
||||
for cidr in cidrs:
|
||||
cidr_prefix = int(cidr.split('/')[1])
|
||||
nvplib.create_lrouter_snat_rule(
|
||||
self.cluster, router_id,
|
||||
ip_addresses[0].split('/')[0],
|
||||
ip_addresses[0].split('/')[0],
|
||||
order=NVP_EXTGW_NAT_RULES_ORDER - cidr_prefix,
|
||||
match_criteria={'source_ip_addresses': cidr})
|
||||
|
||||
def _update_router_port_attachment(self, cluster, context,
|
||||
router_id, port_data,
|
||||
nvp_router_port_id,
|
||||
@ -526,15 +582,6 @@ class NvpPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
"L3GatewayAttachment",
|
||||
ext_network[pnet.PHYSICAL_NETWORK],
|
||||
ext_network[pnet.SEGMENTATION_ID])
|
||||
# Set the SNAT rule for each subnet (only first IP)
|
||||
for cidr in self._find_router_subnets_cidrs(context, router_id):
|
||||
cidr_prefix = int(cidr.split('/')[1])
|
||||
nvplib.create_lrouter_snat_rule(
|
||||
self.cluster, router_id,
|
||||
ip_addresses[0].split('/')[0],
|
||||
ip_addresses[0].split('/')[0],
|
||||
order=NVP_EXTGW_NAT_RULES_ORDER - cidr_prefix,
|
||||
match_criteria={'source_ip_addresses': cidr})
|
||||
|
||||
LOG.debug(_("_nvp_create_ext_gw_port completed on external network "
|
||||
"%(ext_net_id)s, attached to router:%(router_id)s. "
|
||||
@ -559,13 +606,6 @@ class NvpPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
port_data['name'],
|
||||
True,
|
||||
['0.0.0.0/31'])
|
||||
# Delete the SNAT rule for each subnet, keep in mind
|
||||
# that the rule might have already been removed from NVP
|
||||
for cidr in self._find_router_subnets_cidrs(context, router_id):
|
||||
nvplib.delete_nat_rules_by_match(
|
||||
self.cluster, router_id, "SourceNatRule",
|
||||
max_num_expected=1, min_num_expected=0,
|
||||
source_ip_addresses=cidr)
|
||||
# Reset attachment
|
||||
self._update_router_port_attachment(
|
||||
self.cluster, context, router_id, port_data,
|
||||
@ -1654,7 +1694,7 @@ class NvpPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
# Fetch router from DB
|
||||
router = self._get_router(context, router_id)
|
||||
gw_port = router.gw_port
|
||||
if gw_port:
|
||||
if gw_port and router.enable_snat:
|
||||
# There is a change gw_port might have multiple IPs
|
||||
# In that case we will consider only the first one
|
||||
if gw_port.get('fixed_ips'):
|
||||
@ -1869,7 +1909,7 @@ class NvpPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
match_criteria={'destination_ip_addresses':
|
||||
floating_ip})
|
||||
# setup snat rule such that src ip of a IP packet when
|
||||
# using floating is the floating ip itself.
|
||||
# using floating is the floating ip itself.
|
||||
nvplib.create_lrouter_snat_rule(
|
||||
self.cluster, router_id, floating_ip, floating_ip,
|
||||
order=NVP_FLOATINGIP_NAT_RULES_ORDER,
|
||||
|
@ -39,6 +39,7 @@ from neutron.plugins.nicira import nvplib
|
||||
from neutron.tests.unit.nicira import fake_nvpapiclient
|
||||
import neutron.tests.unit.nicira.test_networkgw as test_l2_gw
|
||||
import neutron.tests.unit.test_db_plugin as test_plugin
|
||||
import neutron.tests.unit.test_extension_ext_gw_mode as test_ext_gw_mode
|
||||
import neutron.tests.unit.test_extension_portsecurity as psec
|
||||
import neutron.tests.unit.test_extension_security_group as ext_sg
|
||||
from neutron.tests.unit import test_extensions
|
||||
@ -830,6 +831,11 @@ class TestNiciraQoSQueue(NiciraPluginV2TestCase):
|
||||
self.assertEqual(queue['qos_queue']['max'], 20)
|
||||
|
||||
|
||||
class NiciraExtGwModeTestCase(test_ext_gw_mode.ExtGwModeTestCase,
|
||||
NiciraPluginV2TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class NiciraNeutronNVPOutOfSync(test_l3_plugin.L3NatTestCaseBase,
|
||||
NiciraPluginV2TestCase):
|
||||
|
||||
|
@ -302,7 +302,7 @@ class ExtGwModeTestCase(test_db_plugin.NeutronDbPluginV2TestCase,
|
||||
test_l3_plugin.L3NatTestCaseMixin):
|
||||
|
||||
def setUp(self):
|
||||
# Store l3 resource attribute map as it's will be updated
|
||||
# Store l3 resource attribute map as it will be updated
|
||||
self._l3_attribute_map_bk = {}
|
||||
for item in l3.RESOURCE_ATTRIBUTE_MAP:
|
||||
self._l3_attribute_map_bk[item] = (
|
||||
|
Loading…
Reference in New Issue
Block a user