Merge "NSXv: Connect LB interfaces to member subnets"

This commit is contained in:
Jenkins 2017-02-12 13:18:42 +00:00 committed by Gerrit Code Review
commit 2ce8e5fefc
3 changed files with 75 additions and 15 deletions

View File

@ -33,15 +33,20 @@ def get_lb_resource_id(lb_id):
return ('lbaas-' + lb_id)[:36]
def get_lbaas_edge_id(context, plugin, lb_id, vip_addr, subnet_id, tenant_id):
subnet = plugin.get_subnet(context, subnet_id)
def get_lb_interface(context, plugin, lb_id, subnet_id):
filters = {'fixed_ips': {'subnet_id': [subnet_id]},
'device_id': [lb_id],
'device_owner': [constants.DEVICE_OWNER_NEUTRON_PREFIX + 'LB']}
lb_ports = plugin.get_ports(context.elevated(), filters=filters)
return lb_ports
def create_lb_interface(context, plugin, lb_id, subnet_id, tenant_id,
vip_addr=None, subnet=None):
if not subnet:
subnet = plugin.get_subnet(context, subnet_id)
network_id = subnet.get('network_id')
availability_zone = plugin.get_network_az(context, network_id)
resource_id = get_lb_resource_id(lb_id)
edge_id = plugin.edge_manager.allocate_lb_edge_appliance(
context, resource_id, availability_zone=availability_zone)
port_dict = {'name': 'lb_if-' + lb_id,
'admin_state_up': True,
@ -55,18 +60,46 @@ def get_lbaas_edge_id(context, plugin, lb_id, vip_addr, subnet_id, tenant_id):
port = plugin.base_create_port(context, {'port': port_dict})
ip_addr = port['fixed_ips'][0]['ip_address']
net = netaddr.IPNetwork(subnet['cidr'])
resource_id = get_lb_resource_id(lb_id)
address_groups = [{'primaryAddress': ip_addr,
'subnetPrefixLength': str(net.prefixlen),
'subnetMask': str(net.netmask),
'secondaryAddresses': {
'type': 'secondary_addresses',
'ipAddress': [vip_addr]}
}]
'subnetMask': str(net.netmask)}]
if vip_addr:
address_groups[0]['secondaryAddresses'] = {
'type': 'secondary_addresses', 'ipAddress': [vip_addr]}
edge_utils.update_internal_interface(
plugin.nsx_v, context, resource_id,
network_id, address_groups)
def delete_lb_interface(context, plugin, lb_id, subnet_id):
resource_id = get_lb_resource_id(lb_id)
subnet = plugin.get_subnet(context, subnet_id)
network_id = subnet.get('network_id')
lb_ports = get_lb_interface(context, plugin, lb_id, subnet_id)
for lb_port in lb_ports:
plugin.delete_port(context, lb_port['id'])
edge_utils.delete_interface(plugin.nsx_v, context, resource_id, network_id,
dist=False)
def get_lbaas_edge_id(context, plugin, lb_id, vip_addr, subnet_id, tenant_id):
subnet = plugin.get_subnet(context, subnet_id)
network_id = subnet.get('network_id')
availability_zone = plugin.get_network_az(context, network_id)
resource_id = get_lb_resource_id(lb_id)
edge_id = plugin.edge_manager.allocate_lb_edge_appliance(
context, resource_id, availability_zone=availability_zone)
create_lb_interface(context, plugin, lb_id, subnet_id, tenant_id,
vip_addr=vip_addr, subnet=subnet)
gw_ip = subnet.get('gateway_ip')
if gw_ip:
plugin.nsx_v.update_routes(edge_id, gw_ip, [])

View File

@ -52,6 +52,13 @@ class EdgeMemberManager(base_mgr.EdgeLoadbalancerBaseManager):
edge_id = lb_binding['edge_id']
edge_pool_id = pool_binding['edge_pool_id']
with locking.LockManager.get_lock(edge_id):
# Verify that Edge appliance is connected to the member's subnet
if not lb_common.get_lb_interface(
context, self.core_plugin, lb_id, member.subnet_id):
lb_common.create_lb_interface(
context, self.core_plugin, lb_id, member.subnet_id,
member.tenant_id)
edge_pool = self.vcns.get_pool(edge_id, edge_pool_id)[1]
edge_member = {
'ipAddress': member.address,
@ -137,6 +144,19 @@ class EdgeMemberManager(base_mgr.EdgeLoadbalancerBaseManager):
edge_pool_id = pool_binding['edge_pool_id']
with locking.LockManager.get_lock(edge_id):
# we should remove LB subnet interface if no members are attached
# and this is not the LB's VIP interface
remove_interface = True
if member.subnet_id == member.pool.loadbalancer.vip_subnet_id:
remove_interface = False
else:
for m in member.pool.members:
if m.subnet_id == member.subnet_id and m.id != member.id:
remove_interface = False
if remove_interface:
lb_common.delete_lb_interface(context, self.core_plugin, lb_id,
member.subnet_id)
edge_pool = self.vcns.get_pool(edge_id, edge_pool_id)[1]
for i, m in enumerate(edge_pool['member']):

View File

@ -112,7 +112,8 @@ class BaseTestEdgeLbaasV2(base.BaseTestCase):
None, 'HTTP', 'ROUND_ROBIN',
loadbalancer_id=LB_ID,
listener=self.listener,
listeners=[self.listener])
listeners=[self.listener],
loadbalancer=self.lb)
self.member = lb_models.Member(MEMBER_ID, LB_TENANT_ID, POOL_ID,
MEMBER_ADDRESS, 80, 1, pool=self.pool)
self.hm = lb_models.HealthMonitor(HM_ID, LB_TENANT_ID, 'PING', 3, 3,
@ -510,6 +511,10 @@ class TestEdgeLbaasV2Member(BaseTestEdgeLbaasV2):
) as mock_get_pool_binding, \
mock.patch.object(self.edge_driver.vcns, 'get_pool'
) as mock_get_pool, \
mock.patch.object(self.core_plugin, 'get_ports'
) as mock_get_ports, \
mock.patch.object(lb_common, 'delete_lb_interface'
) as mock_del_lb_iface, \
mock.patch.object(self.edge_driver.vcns, 'update_pool'
) as mock_update_pool:
mock_get_lb_binding.return_value = LB_BINDING
@ -517,12 +522,14 @@ class TestEdgeLbaasV2Member(BaseTestEdgeLbaasV2):
edge_pool_def = EDGE_POOL_DEF.copy()
edge_pool_def['member'] = [EDGE_MEMBER_DEF]
mock_get_pool.return_value = (None, edge_pool_def)
mock_get_ports.return_value = []
self.edge_driver.member.delete(self.context, self.member)
edge_pool_def['member'] = []
mock_update_pool.assert_called_with(
LB_EDGE_ID, EDGE_POOL_ID, edge_pool_def)
mock_del_lb_iface.assert_called_with(
self.context, self.core_plugin, LB_ID, None)
mock_successful_completion = (
self.lbv2_driver.member.successful_completion)
mock_successful_completion.assert_called_with(self.context,