NSXv: Allow use of router edge for LBaaS

Add backward compatibility mode for LBaaSv2 implementation.

Change-Id: I6a16af010f47e92ab44d6e0c807add176bf54ce2
This commit is contained in:
Kobi Samoray 2018-04-12 16:11:34 +03:00
parent f1907bf1f5
commit ee45ea540b
4 changed files with 73 additions and 26 deletions

View File

@ -729,6 +729,10 @@ nsxv_opts = [
default=False, default=False,
help=_("Use default block all rule when no security groups " help=_("Use default block all rule when no security groups "
"are set on a port and port security is enabled")), "are set on a port and port security is enabled")),
cfg.BoolOpt('use_routers_as_lbaas_platform',
default=False,
help=_("Use subnet's exclusive router as a platform for "
"LBaaS")),
] ]
# define the configuration of each NSX-V availability zone. # define the configuration of each NSX-V availability zone.

View File

@ -39,6 +39,27 @@ def get_lb_resource_id(lb_id):
return (RESOURCE_ID_PFX + lb_id)[:36] return (RESOURCE_ID_PFX + lb_id)[:36]
def get_lbaas_edge_id_for_subnet(context, plugin, subnet_id, tenant_id):
"""
Grab the id of an Edge appliance that is connected to subnet_id.
"""
subnet = plugin.get_subnet(context, subnet_id)
net_id = subnet.get('network_id')
filters = {'network_id': [net_id],
'device_owner': ['network:router_interface'],
'tenant_id': [tenant_id]}
attached_routers = plugin.get_ports(context.elevated(),
filters=filters,
fields=['device_id'])
for attached_router in attached_routers:
router = plugin.get_router(context, attached_router['device_id'])
if router.get('router_type') == 'exclusive':
rtr_bindings = nsxv_db.get_nsxv_router_binding(context.session,
router['id'])
return rtr_bindings['edge_id']
def get_lb_edge_name(context, lb_id): def get_lb_edge_name(context, lb_id):
"""Look for the resource name of the edge hosting the LB. """Look for the resource name of the edge hosting the LB.

View File

@ -19,6 +19,7 @@ from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources from neutron_lib.callbacks import resources
from neutron_lib import constants from neutron_lib import constants
from neutron_lib import exceptions as n_exc from neutron_lib import exceptions as n_exc
from oslo_config import cfg
from oslo_log import helpers as log_helpers from oslo_log import helpers as log_helpers
from oslo_log import log as logging from oslo_log import log as logging
from oslo_utils import excutils from oslo_utils import excutils
@ -60,10 +61,18 @@ class EdgeLoadBalancerManager(base_mgr.EdgeLoadbalancerBaseManager):
@log_helpers.log_method_call @log_helpers.log_method_call
def create(self, context, lb): def create(self, context, lb):
lb_size = self._get_lb_flavor_size(context, lb.flavor_id) if cfg.CONF.nsxv.use_routers_as_lbaas_platform:
edge_id = lb_common.get_lbaas_edge_id( edge_id = lb_common.get_lbaas_edge_id_for_subnet(
context, self.core_plugin, lb.id, lb.vip_address, lb.vip_subnet_id, context, self.core_plugin, lb.vip_subnet_id, lb.tenant_id)
lb.tenant_id, lb_size) if not edge_id:
msg = _(
'No suitable Edge found for subnet %s') % lb.vip_subnet_id
raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)
else:
lb_size = self._get_lb_flavor_size(context, lb.flavor_id)
edge_id = lb_common.get_lbaas_edge_id(
context, self.core_plugin, lb.id, lb.vip_address,
lb.vip_subnet_id, lb.tenant_id, lb_size)
if not edge_id: if not edge_id:
msg = _('Failed to allocate Edge on subnet %(sub)s for ' msg = _('Failed to allocate Edge on subnet %(sub)s for '
@ -72,14 +81,22 @@ class EdgeLoadBalancerManager(base_mgr.EdgeLoadbalancerBaseManager):
raise n_exc.BadRequest(resource='edge-lbaas', msg=msg) raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)
try: try:
lb_common.enable_edge_acceleration(self.vcns, edge_id) if cfg.CONF.nsxv.use_routers_as_lbaas_platform:
if not nsxv_db.get_nsxv_lbaas_loadbalancer_binding_by_edge(
context.session, edge_id):
lb_common.enable_edge_acceleration(self.vcns, edge_id)
lb_common.add_vip_as_secondary_ip(self.vcns, edge_id,
lb.vip_address)
else:
lb_common.enable_edge_acceleration(self.vcns, edge_id)
edge_fw_rule_id = lb_common.add_vip_fw_rule( edge_fw_rule_id = lb_common.add_vip_fw_rule(
self.vcns, edge_id, lb.id, lb.vip_address) self.vcns, edge_id, lb.id, lb.vip_address)
# set LB default rule # set LB default rule
lb_common.set_lb_firewall_default_rule(self.vcns, edge_id, if not cfg.CONF.nsxv.use_routers_as_lbaas_platform:
'accept') lb_common.set_lb_firewall_default_rule(self.vcns, edge_id,
'accept')
nsxv_db.add_nsxv_lbaas_loadbalancer_binding( nsxv_db.add_nsxv_lbaas_loadbalancer_binding(
context.session, lb.id, edge_id, edge_fw_rule_id, context.session, lb.id, edge_id, edge_fw_rule_id,

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from oslo_config import cfg
from oslo_log import helpers as log_helpers from oslo_log import helpers as log_helpers
from oslo_log import log as logging from oslo_log import log as logging
from oslo_utils import excutils from oslo_utils import excutils
@ -61,8 +62,10 @@ class EdgeMemberManager(base_mgr.EdgeLoadbalancerBaseManager):
edge_pool_id = pool_binding['edge_pool_id'] edge_pool_id = pool_binding['edge_pool_id']
with locking.LockManager.get_lock(edge_id): with locking.LockManager.get_lock(edge_id):
if not lb_common.is_lb_on_router_edge( if (not cfg.CONF.nsxv.use_routers_as_lbaas_platform and
context.elevated(), self.core_plugin, edge_id): not lb_common.is_lb_on_router_edge(context.elevated(),
self.core_plugin,
edge_id)):
# Verify that Edge appliance is connected to the member's # Verify that Edge appliance is connected to the member's
# subnet (only if this is a dedicated loadbalancer edge) # subnet (only if this is a dedicated loadbalancer edge)
if not lb_common.get_lb_interface( if not lb_common.get_lb_interface(
@ -153,24 +156,26 @@ class EdgeMemberManager(base_mgr.EdgeLoadbalancerBaseManager):
context.session, lb_id, member.pool_id) context.session, lb_id, member.pool_id)
edge_id = lb_binding['edge_id'] edge_id = lb_binding['edge_id']
with locking.LockManager.get_lock(edge_id): if not cfg.CONF.nsxv.use_routers_as_lbaas_platform:
# we should remove LB subnet interface if no members are attached with locking.LockManager.get_lock(edge_id):
# and this is not the LB's VIP interface # we should remove LB subnet interface if no members are
remove_interface = True # attached and this is not the LB's VIP interface
if member.subnet_id == member.pool.loadbalancer.vip_subnet_id: remove_interface = True
remove_interface = False if member.subnet_id == member.pool.loadbalancer.vip_subnet_id:
else: remove_interface = False
for m in member.pool.members: else:
if m.subnet_id == member.subnet_id and m.id != member.id: for m in member.pool.members:
remove_interface = False if (m.subnet_id == member.subnet_id and
if remove_interface: m.id != member.id):
lb_common.delete_lb_interface(context, self.core_plugin, lb_id, remove_interface = False
member.subnet_id) if remove_interface:
lb_common.delete_lb_interface(context, self.core_plugin,
lb_id, member.subnet_id)
if not pool_binding: if not pool_binding:
self.lbv2_driver.member.successful_completion( self.lbv2_driver.member.successful_completion(
context, member, delete=True) context, member, delete=True)
return return
edge_pool_id = pool_binding['edge_pool_id'] edge_pool_id = pool_binding['edge_pool_id']
edge_pool = self.vcns.get_pool(edge_id, edge_pool_id)[1] edge_pool = self.vcns.get_pool(edge_id, edge_pool_id)[1]