LBaaSv2 driver
Implement LBaaSv2 driver for NSXv Edge appliance load balancer. Includes TLS support for Edge appliance, and certificate management For SSL termination. Change-Id: I60093c0186cce3e99fb26e1fc6bd5175cbd1a560
This commit is contained in:
parent
c96d12ccab
commit
9b6d3b1b47
@ -16,6 +16,7 @@
|
||||
ZUUL_CLONER=/usr/zuul-env/bin/zuul-cloner
|
||||
neutron_installed=$(echo "import neutron" | python 2>/dev/null ; echo $?)
|
||||
networking_l2gw_installed=$(echo "import networking_l2gw" | python 2>/dev/null ; echo $?)
|
||||
neutron_lbaas_installed=$(echo "import neutron_lbaas" | python 2>/dev/null ; echo $?)
|
||||
|
||||
set -ex
|
||||
|
||||
@ -56,5 +57,14 @@ else
|
||||
pip_hardcode openstack/networking-l2gw#egg=networking-l2gw
|
||||
fi
|
||||
|
||||
if [ $neutron_lbaas_installed -eq 0 ]; then
|
||||
echo "NEUTRON_LBAAS ALREADY INSTALLED" >> /tmp/tox_install.txt
|
||||
echo "Neutron_lbaas already installed; using existing package"
|
||||
elif [ -x "$ZUUL_CLONER" ]; then
|
||||
zuul_cloner openstack/neutron-lbaas
|
||||
else
|
||||
pip_hardcode openstack/neutron-lbaas#egg=neutron-lbaas
|
||||
fi
|
||||
|
||||
pip install -U $*
|
||||
exit $?
|
||||
|
@ -1,2 +1,2 @@
|
||||
279b70ac3ae8
|
||||
312211a5725f
|
||||
3c88bdea3054
|
||||
|
@ -0,0 +1,68 @@
|
||||
# Copyright 2015 VMware, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
"""nsxv_lbv2
|
||||
|
||||
Revision ID: 312211a5725f
|
||||
Revises: 279b70ac3ae8
|
||||
Create Date: 2015-09-09 02:02:59.990122
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '312211a5725f'
|
||||
down_revision = '279b70ac3ae8'
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table(
|
||||
'nsxv_lbaas_loadbalancer_bindings',
|
||||
sa.Column('loadbalancer_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('edge_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('edge_fw_rule_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('vip_address', sa.String(length=36), nullable=False),
|
||||
sa.PrimaryKeyConstraint('loadbalancer_id'))
|
||||
op.create_table(
|
||||
'nsxv_lbaas_listener_bindings',
|
||||
sa.Column('loadbalancer_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('listener_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('app_profile_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('vse_id', sa.String(length=36), nullable=False),
|
||||
sa.PrimaryKeyConstraint('loadbalancer_id', 'listener_id'))
|
||||
op.create_table(
|
||||
'nsxv_lbaas_pool_bindings',
|
||||
sa.Column('loadbalancer_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('listener_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('pool_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('edge_pool_id', sa.String(length=36), nullable=False),
|
||||
sa.PrimaryKeyConstraint('loadbalancer_id', 'listener_id', 'pool_id'))
|
||||
op.create_table(
|
||||
'nsxv_lbaas_monitor_bindings',
|
||||
sa.Column('loadbalancer_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('listener_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('pool_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('hm_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('edge_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('edge_mon_id', sa.String(length=36), nullable=False),
|
||||
sa.PrimaryKeyConstraint('loadbalancer_id', 'listener_id', 'pool_id',
|
||||
'hm_id', 'edge_id'))
|
||||
op.create_table(
|
||||
'nsxv_lbaas_certificate_bindings',
|
||||
sa.Column('cert_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('edge_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('edge_cert_id', sa.String(length=36), nullable=False),
|
||||
sa.PrimaryKeyConstraint('cert_id', 'edge_id'))
|
@ -536,3 +536,153 @@ def get_vdr_dhcp_binding_by_vdr(session, vdr_router_id):
|
||||
def delete_vdr_dhcp_binding(session, vdr_router_id):
|
||||
return (session.query(nsxv_models.NsxvVdrDhcpBinding).
|
||||
filter_by(vdr_router_id=vdr_router_id).delete())
|
||||
|
||||
|
||||
def add_nsxv_lbaas_loadbalancer_binding(
|
||||
session, loadbalancer_id, edge_id, edge_fw_rule_id, vip_address):
|
||||
with session.begin(subtransactions=True):
|
||||
binding = nsxv_models.NsxvLbaasLoadbalancerBinding(
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
edge_id=edge_id,
|
||||
edge_fw_rule_id=edge_fw_rule_id,
|
||||
vip_address=vip_address)
|
||||
session.add(binding)
|
||||
return binding
|
||||
|
||||
|
||||
def get_nsxv_lbaas_loadbalancer_binding(session, loadbalancer_id):
|
||||
try:
|
||||
return session.query(
|
||||
nsxv_models.NsxvLbaasLoadbalancerBinding).filter_by(
|
||||
loadbalancer_id=loadbalancer_id).one()
|
||||
except exc.NoResultFound:
|
||||
return
|
||||
|
||||
|
||||
def del_nsxv_lbaas_loadbalancer_binding(session, loadbalancer_id):
|
||||
return (session.query(nsxv_models.NsxvLbaasLoadbalancerBinding).
|
||||
filter_by(loadbalancer_id=loadbalancer_id).delete())
|
||||
|
||||
|
||||
def add_nsxv_lbaas_listener_binding(session, loadbalancer_id, listener_id,
|
||||
app_profile_id, vse_id):
|
||||
with session.begin(subtransactions=True):
|
||||
binding = nsxv_models.NsxvLbaasListenerBinding(
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
listener_id=listener_id,
|
||||
app_profile_id=app_profile_id,
|
||||
vse_id=vse_id)
|
||||
session.add(binding)
|
||||
return binding
|
||||
|
||||
|
||||
def get_nsxv_lbaas_listener_binding(session, loadbalancer_id, listener_id):
|
||||
try:
|
||||
return session.query(
|
||||
nsxv_models.NsxvLbaasListenerBinding).filter_by(
|
||||
loadbalancer_id=loadbalancer_id, listener_id=listener_id).one()
|
||||
except exc.NoResultFound:
|
||||
return
|
||||
|
||||
|
||||
def del_nsxv_lbaas_listener_binding(session, loadbalancer_id, listener_id):
|
||||
return (session.query(nsxv_models.NsxvLbaasListenerBinding).
|
||||
filter_by(loadbalancer_id=loadbalancer_id,
|
||||
listener_id=listener_id).delete())
|
||||
|
||||
|
||||
def add_nsxv_lbaas_pool_binding(session, loadbalancer_id, listener_id,
|
||||
pool_id, edge_pool_id):
|
||||
with session.begin(subtransactions=True):
|
||||
binding = nsxv_models.NsxvLbaasPoolBinding(
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
listener_id=listener_id,
|
||||
pool_id=pool_id,
|
||||
edge_pool_id=edge_pool_id)
|
||||
session.add(binding)
|
||||
return binding
|
||||
|
||||
|
||||
def get_nsxv_lbaas_pool_binding(session, loadbalancer_id, listener_id,
|
||||
pool_id):
|
||||
try:
|
||||
return session.query(
|
||||
nsxv_models.NsxvLbaasPoolBinding).filter_by(
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
listener_id=listener_id,
|
||||
pool_id=pool_id).one()
|
||||
except exc.NoResultFound:
|
||||
return
|
||||
|
||||
|
||||
def del_nsxv_lbaas_pool_binding(session, loadbalancer_id, listener_id,
|
||||
pool_id):
|
||||
return (session.query(nsxv_models.NsxvLbaasPoolBinding).
|
||||
filter_by(loadbalancer_id=loadbalancer_id,
|
||||
listener_id=listener_id,
|
||||
pool_id=pool_id).delete())
|
||||
|
||||
|
||||
def add_nsxv_lbaas_monitor_binding(session, loadbalancer_id, listener_id,
|
||||
pool_id, hm_id, edge_id, edge_mon_id):
|
||||
with session.begin(subtransactions=True):
|
||||
binding = nsxv_models.NsxvLbaasMonitorBinding(
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
listener_id=listener_id,
|
||||
pool_id=pool_id,
|
||||
hm_id=hm_id,
|
||||
edge_id=edge_id,
|
||||
edge_mon_id=edge_mon_id)
|
||||
session.add(binding)
|
||||
return binding
|
||||
|
||||
|
||||
def get_nsxv_lbaas_monitor_binding(session, loadbalancer_id, listener_id,
|
||||
pool_id, hm_id, edge_id):
|
||||
try:
|
||||
return session.query(
|
||||
nsxv_models.NsxvLbaasMonitorBinding).filter_by(
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
listener_id=listener_id,
|
||||
pool_id=pool_id,
|
||||
hm_id=hm_id,
|
||||
edge_id=edge_id).one()
|
||||
except exc.NoResultFound:
|
||||
return
|
||||
|
||||
|
||||
def del_nsxv_lbaas_monitor_binding(session, loadbalancer_id, listener_id,
|
||||
pool_id, hm_id, edge_id):
|
||||
return (session.query(nsxv_models.NsxvLbaasMonitorBinding).
|
||||
filter_by(loadbalancer_id=loadbalancer_id,
|
||||
listener_id=listener_id,
|
||||
pool_id=pool_id,
|
||||
hm_id=hm_id,
|
||||
edge_id=edge_id).delete())
|
||||
|
||||
|
||||
def add_nsxv_lbaas_certificate_binding(session, cert_id, edge_id,
|
||||
edge_cert_id):
|
||||
with session.begin(subtransactions=True):
|
||||
binding = nsxv_models.NsxvLbaasCertificateBinding(
|
||||
cert_id=cert_id,
|
||||
edge_id=edge_id,
|
||||
edge_cert_id=edge_cert_id)
|
||||
session.add(binding)
|
||||
return binding
|
||||
|
||||
|
||||
def get_nsxv_lbaas_certificate_binding(session, cert_id, edge_id):
|
||||
try:
|
||||
return session.query(
|
||||
nsxv_models.NsxvLbaasCertificateBinding).filter_by(
|
||||
cert_id=cert_id,
|
||||
edge_id=edge_id).one()
|
||||
except exc.NoResultFound:
|
||||
return
|
||||
|
||||
|
||||
def del_nsxv_lbaas_certificate_binding(session, cert_id, edge_id):
|
||||
return (session.query(nsxv_models.NsxvLbaasCertificateBinding).
|
||||
filter_by(cert_id=cert_id,
|
||||
edge_id=edge_id).delete())
|
||||
|
@ -254,3 +254,59 @@ class NsxvVdrDhcpBinding(model_base.BASEV2):
|
||||
dhcp_edge_id,
|
||||
name='unique_nsxv_vdr_dhcp_bindings0dhcp_edge_id'),
|
||||
model_base.BASEV2.__table_args__)
|
||||
|
||||
|
||||
class NsxvLbaasLoadbalancerBinding(model_base.BASEV2):
|
||||
"""Mapping between Edge LB and LBaaSv2"""
|
||||
|
||||
__tablename__ = 'nsxv_lbaas_loadbalancer_bindings'
|
||||
|
||||
loadbalancer_id = sa.Column(sa.String(36), primary_key=True)
|
||||
edge_id = sa.Column(sa.String(36), nullable=False)
|
||||
edge_fw_rule_id = sa.Column(sa.String(36), nullable=False)
|
||||
vip_address = sa.Column(sa.String(36), nullable=False)
|
||||
|
||||
|
||||
class NsxvLbaasListenerBinding(model_base.BASEV2):
|
||||
"""Mapping between Edge VSE and LBaaSv2"""
|
||||
|
||||
__tablename__ = 'nsxv_lbaas_listener_bindings'
|
||||
|
||||
loadbalancer_id = sa.Column(sa.String(36), primary_key=True)
|
||||
listener_id = sa.Column(sa.String(36), primary_key=True)
|
||||
app_profile_id = sa.Column(sa.String(36), nullable=False)
|
||||
vse_id = sa.Column(sa.String(36), nullable=False)
|
||||
|
||||
|
||||
class NsxvLbaasPoolBinding(model_base.BASEV2):
|
||||
"""Mapping between Edge Pool and LBaaSv2"""
|
||||
|
||||
__tablename__ = 'nsxv_lbaas_pool_bindings'
|
||||
|
||||
loadbalancer_id = sa.Column(sa.String(36), primary_key=True)
|
||||
listener_id = sa.Column(sa.String(36), primary_key=True)
|
||||
pool_id = sa.Column(sa.String(36), primary_key=True)
|
||||
edge_pool_id = sa.Column(sa.String(36), nullable=False)
|
||||
|
||||
|
||||
class NsxvLbaasMonitorBinding(model_base.BASEV2):
|
||||
"""Mapping between Edge Monitor and LBaaSv2"""
|
||||
|
||||
__tablename__ = 'nsxv_lbaas_monitor_bindings'
|
||||
|
||||
loadbalancer_id = sa.Column(sa.String(36), primary_key=True)
|
||||
listener_id = sa.Column(sa.String(36), primary_key=True)
|
||||
pool_id = sa.Column(sa.String(36), primary_key=True)
|
||||
hm_id = sa.Column(sa.String(36), primary_key=True)
|
||||
edge_id = sa.Column(sa.String(36), primary_key=True)
|
||||
edge_mon_id = sa.Column(sa.String(36), nullable=False)
|
||||
|
||||
|
||||
class NsxvLbaasCertificateBinding(model_base.BASEV2):
|
||||
"""Mapping between Edge certificate and LBaaSv2 object"""
|
||||
|
||||
__tablename__ = 'nsxv_lbaas_certificate_bindings'
|
||||
|
||||
cert_id = sa.Column(sa.String(36), primary_key=True)
|
||||
edge_id = sa.Column(sa.String(36), primary_key=True)
|
||||
edge_cert_id = sa.Column(sa.String(36), nullable=False)
|
||||
|
@ -792,3 +792,8 @@ class Vcns(object):
|
||||
"""Enable HA in the given edge."""
|
||||
uri = "/api/4.0/edges/%s/highavailability/config?async=true" % edge_id
|
||||
return self.do_request(HTTP_PUT, uri, request_config)
|
||||
|
||||
def upload_edge_certificate(self, edge_id, request):
|
||||
"""Creates a certificate on the specified Edge appliance."""
|
||||
uri = '/api/2.0/services/truststore/certificate/%s' % edge_id
|
||||
return self.do_request(HTTP_POST, uri, request, decode=True)
|
||||
|
@ -19,18 +19,20 @@ import os
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from vmware_nsx.common import config # noqa
|
||||
from vmware_nsx.plugins.nsx_v.vshield import edge_appliance_driver
|
||||
from vmware_nsx.plugins.nsx_v.vshield import edge_firewall_driver
|
||||
from vmware_nsx.plugins.nsx_v.vshield import edge_loadbalancer_driver
|
||||
from vmware_nsx.plugins.nsx_v.vshield.tasks import tasks
|
||||
from vmware_nsx.plugins.nsx_v.vshield import vcns
|
||||
from vmware_nsx.services.lbaas.nsx_v.v1 import edge_loadbalancer_driver
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import (
|
||||
edge_loadbalancer_driver_v2 as lbaas_v2)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class VcnsDriver(edge_appliance_driver.EdgeApplianceDriver,
|
||||
edge_loadbalancer_driver.EdgeLbDriver,
|
||||
lbaas_v2.EdgeLoadbalancerDriverV2,
|
||||
edge_firewall_driver.EdgeFirewallDriver):
|
||||
|
||||
def __init__(self, callbacks):
|
||||
|
0
vmware_nsx/services/lbaas/__init__.py
Normal file
0
vmware_nsx/services/lbaas/__init__.py
Normal file
0
vmware_nsx/services/lbaas/nsx_v/__init__.py
Normal file
0
vmware_nsx/services/lbaas/nsx_v/__init__.py
Normal file
250
vmware_nsx/services/lbaas/nsx_v/lbaas_common.py
Normal file
250
vmware_nsx/services/lbaas/nsx_v/lbaas_common.py
Normal file
@ -0,0 +1,250 @@
|
||||
# Copyright 2015 VMware, Inc.
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import netaddr
|
||||
import xml.etree.ElementTree as et
|
||||
|
||||
from neutron.common import exceptions as n_exc
|
||||
|
||||
from vmware_nsx.common import locking
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.plugins.nsx_v.vshield import vcns as nsxv_api
|
||||
|
||||
MEMBER_ID_PFX = 'member-'
|
||||
LBAAS_FW_SECTION_NAME = 'LBaaS FW Rules'
|
||||
|
||||
|
||||
def get_member_id(member_id):
|
||||
return MEMBER_ID_PFX + member_id
|
||||
|
||||
|
||||
def get_lbaas_edge_id_for_subnet(context, plugin, subnet_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']}
|
||||
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['router_type'] == 'exclusive':
|
||||
rtr_bindings = nsxv_db.get_nsxv_router_binding(context.session,
|
||||
router['id'])
|
||||
return rtr_bindings['edge_id']
|
||||
|
||||
|
||||
def find_address_in_same_subnet(ip_addr, address_groups):
|
||||
"""
|
||||
Lookup an address group with a matching subnet to ip_addr.
|
||||
If found, return address_group.
|
||||
"""
|
||||
for address_group in address_groups['addressGroups']:
|
||||
net_addr = '%(primaryAddress)s/%(subnetPrefixLength)s' % address_group
|
||||
if netaddr.IPAddress(ip_addr) in netaddr.IPNetwork(net_addr):
|
||||
return address_group
|
||||
|
||||
|
||||
def add_address_to_address_groups(ip_addr, address_groups):
|
||||
"""
|
||||
Add ip_addr as a secondary IP address to an address group which belongs to
|
||||
the same subnet.
|
||||
"""
|
||||
address_group = find_address_in_same_subnet(
|
||||
ip_addr, address_groups)
|
||||
if address_group:
|
||||
sec_addr = address_group.get('secondaryAddresses')
|
||||
if not sec_addr:
|
||||
sec_addr = {
|
||||
'type': 'secondary_addresses',
|
||||
'ipAddress': [ip_addr]}
|
||||
else:
|
||||
sec_addr['ipAddress'].append(ip_addr)
|
||||
address_group['secondaryAddresses'] = sec_addr
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def del_address_from_address_groups(ip_addr, address_groups):
|
||||
"""
|
||||
Delete ip_addr from secondary address list in address groups.
|
||||
"""
|
||||
address_group = find_address_in_same_subnet(ip_addr, address_groups)
|
||||
if address_group:
|
||||
sec_addr = address_group.get('secondaryAddresses')
|
||||
if sec_addr and ip_addr in sec_addr['ipAddress']:
|
||||
sec_addr['ipAddress'].remove(ip_addr)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def vip_as_secondary_ip(vcns, edge_id, vip, handler):
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
r = vcns.get_interfaces(edge_id)[1]
|
||||
vnics = r.get('vnics', [])
|
||||
for vnic in vnics:
|
||||
if vnic['type'] == 'trunk':
|
||||
for sub_interface in vnic.get('subInterfaces', {}).get(
|
||||
'subInterfaces', []):
|
||||
address_groups = sub_interface.get('addressGroups')
|
||||
if handler(vip, address_groups):
|
||||
vcns.update_interface(edge_id, vnic)
|
||||
return True
|
||||
else:
|
||||
address_groups = vnic.get('addressGroups')
|
||||
if handler(vip, address_groups):
|
||||
vcns.update_interface(edge_id, vnic)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def add_vip_as_secondary_ip(vcns, edge_id, vip):
|
||||
"""
|
||||
Edge appliance requires that a VIP will be configured as a primary
|
||||
or a secondary IP address on an interface.
|
||||
To do so, we locate an interface which is connected to the same subnet
|
||||
that vip belongs to.
|
||||
This can be a regular interface, on a sub-interface on a trunk.
|
||||
"""
|
||||
if not vip_as_secondary_ip(vcns, edge_id, vip,
|
||||
add_address_to_address_groups):
|
||||
|
||||
msg = _('Failed to add VIP %(vip)s as secondary IP on '
|
||||
'Edge %(edge_id)s') % {'vip': vip, 'edge_id': edge_id}
|
||||
raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)
|
||||
|
||||
|
||||
def del_vip_as_secondary_ip(vcns, edge_id, vip):
|
||||
"""
|
||||
While removing vip, delete the secondary interface from Edge config.
|
||||
"""
|
||||
if not vip_as_secondary_ip(vcns, edge_id, vip,
|
||||
del_address_from_address_groups):
|
||||
|
||||
msg = _('Failed to delete VIP %(vip)s as secondary IP on '
|
||||
'Edge %(edge_id)s') % {'vip': vip, 'edge_id': edge_id}
|
||||
raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)
|
||||
|
||||
|
||||
def extract_resource_id(location_uri):
|
||||
"""
|
||||
Edge assigns an ID for each resource that is being created:
|
||||
it is postfixes the uri specified in the Location header.
|
||||
This ID should be used while updating/deleting this resource.
|
||||
"""
|
||||
uri_elements = location_uri.split('/')
|
||||
return uri_elements[-1]
|
||||
|
||||
|
||||
def add_vip_fw_rule(vcns, edge_id, vip_id, ip_address):
|
||||
fw_rule = {
|
||||
'firewallRules': [
|
||||
{'action': 'accept', 'destination': {
|
||||
'ipAddress': [ip_address]},
|
||||
'enabled': True,
|
||||
'name': vip_id}]}
|
||||
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
h = vcns.add_firewall_rule(edge_id, fw_rule)[0]
|
||||
fw_rule_id = extract_resource_id(h['location'])
|
||||
|
||||
return fw_rule_id
|
||||
|
||||
|
||||
def del_vip_fw_rule(vcns, edge_id, vip_fw_rule_id):
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
vcns.delete_firewall_rule(edge_id, vip_fw_rule_id)
|
||||
|
||||
|
||||
def get_edge_ip_addresses(vcns, edge_id):
|
||||
edge_ips = []
|
||||
r = vcns.get_interfaces(edge_id)[1]
|
||||
vnics = r.get('vnics', [])
|
||||
for vnic in vnics:
|
||||
if vnic['type'] == 'trunk':
|
||||
for sub_interface in vnic.get('subInterfaces', {}).get(
|
||||
'subInterfaces', []):
|
||||
address_groups = sub_interface.get('addressGroups')
|
||||
for address_group in address_groups['addressGroups']:
|
||||
edge_ips.append(address_group['primaryAddress'])
|
||||
|
||||
else:
|
||||
address_groups = vnic.get('addressGroups')
|
||||
for address_group in address_groups['addressGroups']:
|
||||
edge_ips.append(address_group['primaryAddress'])
|
||||
return edge_ips
|
||||
|
||||
|
||||
def update_pool_fw_rule(vcns, pool_id, edge_id, section_id, member_ips):
|
||||
edge_ips = get_edge_ip_addresses(vcns, edge_id)
|
||||
|
||||
with locking.LockManager.get_lock('lbaas-fw-section', external=True):
|
||||
section_uri = '%s/%s/%s' % (nsxv_api.FIREWALL_PREFIX,
|
||||
'layer3sections',
|
||||
section_id)
|
||||
xml_section = vcns.get_section(section_uri)[1]
|
||||
section = et.fromstring(xml_section)
|
||||
pool_rule = None
|
||||
for rule in section.iter('rule'):
|
||||
if rule.find('name').text == pool_id:
|
||||
pool_rule = rule
|
||||
if member_ips:
|
||||
pool_rule.find('sources').find('source').find(
|
||||
'value').text = (','.join(edge_ips))
|
||||
pool_rule.find('destinations').find(
|
||||
'destination').find('value').text = ','.join(
|
||||
member_ips)
|
||||
else:
|
||||
section.remove(pool_rule)
|
||||
break
|
||||
|
||||
if member_ips and pool_rule is None:
|
||||
pool_rule = et.SubElement(section, 'rule')
|
||||
et.SubElement(pool_rule, 'name').text = pool_id
|
||||
et.SubElement(pool_rule, 'action').text = 'allow'
|
||||
sources = et.SubElement(pool_rule, 'sources')
|
||||
sources.attrib['excluded'] = 'false'
|
||||
source = et.SubElement(sources, 'source')
|
||||
et.SubElement(source, 'type').text = 'Ipv4Address'
|
||||
et.SubElement(source, 'value').text = ','.join(edge_ips)
|
||||
|
||||
destinations = et.SubElement(pool_rule, 'destinations')
|
||||
destinations.attrib['excluded'] = 'false'
|
||||
destination = et.SubElement(destinations, 'destination')
|
||||
et.SubElement(destination, 'type').text = 'Ipv4Address'
|
||||
et.SubElement(destination, 'value').text = ','.join(member_ips)
|
||||
|
||||
vcns.update_section(section_uri,
|
||||
et.tostring(section, encoding="us-ascii"),
|
||||
None)
|
||||
|
||||
|
||||
def get_lbaas_fw_section_id(vcns):
|
||||
# Avoid concurrent creation of section by multiple neutron
|
||||
# instances
|
||||
with locking.LockManager.get_lock('lbaas-fw-section',
|
||||
external=True):
|
||||
fw_section_id = vcns.get_section_id(LBAAS_FW_SECTION_NAME)
|
||||
if not fw_section_id:
|
||||
section = et.Element('section')
|
||||
section.attrib['name'] = LBAAS_FW_SECTION_NAME
|
||||
sect = vcns.create_section('ip', et.tostring(section))[1]
|
||||
fw_section_id = et.fromstring(sect).attrib['id']
|
||||
|
||||
return fw_section_id
|
56
vmware_nsx/services/lbaas/nsx_v/lbaas_const.py
Normal file
56
vmware_nsx/services/lbaas/nsx_v/lbaas_const.py
Normal file
@ -0,0 +1,56 @@
|
||||
# Copyright 2015 VMware, Inc.
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
LB_METHOD_ROUND_ROBIN = 'ROUND_ROBIN'
|
||||
LB_METHOD_LEAST_CONNECTIONS = 'LEAST_CONNECTIONS'
|
||||
LB_METHOD_SOURCE_IP = 'SOURCE_IP'
|
||||
|
||||
BALANCE_MAP = {
|
||||
LB_METHOD_ROUND_ROBIN: 'round-robin',
|
||||
LB_METHOD_LEAST_CONNECTIONS: 'leastconn',
|
||||
LB_METHOD_SOURCE_IP: 'ip-hash'}
|
||||
|
||||
LB_PROTOCOL_TCP = 'TCP'
|
||||
LB_PROTOCOL_HTTP = 'HTTP'
|
||||
LB_PROTOCOL_HTTPS = 'HTTPS'
|
||||
|
||||
PROTOCOL_MAP = {
|
||||
LB_PROTOCOL_TCP: 'tcp',
|
||||
LB_PROTOCOL_HTTP: 'http',
|
||||
LB_PROTOCOL_HTTPS: 'tcp'}
|
||||
|
||||
LB_HEALTH_MONITOR_PING = 'PING'
|
||||
LB_HEALTH_MONITOR_TCP = 'TCP'
|
||||
LB_HEALTH_MONITOR_HTTP = 'HTTP'
|
||||
LB_HEALTH_MONITOR_HTTPS = 'HTTPS'
|
||||
|
||||
HEALTH_MONITOR_MAP = {
|
||||
LB_HEALTH_MONITOR_PING: 'icmp',
|
||||
LB_HEALTH_MONITOR_TCP: 'tcp',
|
||||
LB_HEALTH_MONITOR_HTTP: 'http',
|
||||
LB_HEALTH_MONITOR_HTTPS: 'tcp'}
|
||||
|
||||
LB_SESSION_PERSISTENCE_SOURCE_IP = 'SOURCE_IP'
|
||||
LB_SESSION_PERSISTENCE_HTTP_COOKIE = 'HTTP_COOKIE'
|
||||
LB_SESSION_PERSISTENCE_APP_COOKIE = 'APP_COOKIE'
|
||||
|
||||
SESSION_PERSISTENCE_METHOD_MAP = {
|
||||
LB_SESSION_PERSISTENCE_SOURCE_IP: 'sourceip',
|
||||
LB_SESSION_PERSISTENCE_APP_COOKIE: 'cookie',
|
||||
LB_SESSION_PERSISTENCE_HTTP_COOKIE: 'cookie'}
|
||||
|
||||
SESSION_PERSISTENCE_COOKIE_MAP = {
|
||||
LB_SESSION_PERSISTENCE_APP_COOKIE: 'app',
|
||||
LB_SESSION_PERSISTENCE_HTTP_COOKIE: 'insert'}
|
0
vmware_nsx/services/lbaas/nsx_v/v1/__init__.py
Normal file
0
vmware_nsx/services/lbaas/nsx_v/v1/__init__.py
Normal file
@ -13,71 +13,20 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import xml.etree.ElementTree as et
|
||||
|
||||
import netaddr
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
||||
from neutron.common import exceptions as n_exc
|
||||
from neutron.i18n import _LE
|
||||
from neutron import manager
|
||||
from neutron.plugins.common import constants
|
||||
from vmware_nsx.common import locking
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import (
|
||||
exceptions as nsxv_exc)
|
||||
from vmware_nsx.plugins.nsx_v.vshield import vcns as nsxv_api
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
||||
from vmware_nsx.common import locking
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as nsxv_exc
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_const as lb_const
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
LB_METHOD_ROUND_ROBIN = 'ROUND_ROBIN'
|
||||
LB_METHOD_LEAST_CONNECTIONS = 'LEAST_CONNECTIONS'
|
||||
LB_METHOD_SOURCE_IP = 'SOURCE_IP'
|
||||
|
||||
LB_PROTOCOL_TCP = 'TCP'
|
||||
LB_PROTOCOL_HTTP = 'HTTP'
|
||||
LB_PROTOCOL_HTTPS = 'HTTPS'
|
||||
|
||||
LB_HEALTH_MONITOR_PING = 'PING'
|
||||
LB_HEALTH_MONITOR_TCP = 'TCP'
|
||||
LB_HEALTH_MONITOR_HTTP = 'HTTP'
|
||||
LB_HEALTH_MONITOR_HTTPS = 'HTTPS'
|
||||
|
||||
LB_SESSION_PERSISTENCE_SOURCE_IP = 'SOURCE_IP'
|
||||
LB_SESSION_PERSISTENCE_HTTP_COOKIE = 'HTTP_COOKIE'
|
||||
LB_SESSION_PERSISTENCE_APP_COOKIE = 'APP_COOKIE'
|
||||
|
||||
BALANCE_MAP = {
|
||||
LB_METHOD_ROUND_ROBIN: 'round-robin',
|
||||
LB_METHOD_LEAST_CONNECTIONS: 'leastconn',
|
||||
LB_METHOD_SOURCE_IP: 'ip-hash'}
|
||||
|
||||
PROTOCOL_MAP = {
|
||||
LB_PROTOCOL_TCP: 'tcp',
|
||||
LB_PROTOCOL_HTTP: 'http',
|
||||
LB_PROTOCOL_HTTPS: 'tcp'}
|
||||
|
||||
HEALTH_MONITOR_MAP = {
|
||||
LB_HEALTH_MONITOR_PING: 'icmp',
|
||||
LB_HEALTH_MONITOR_TCP: 'tcp',
|
||||
LB_HEALTH_MONITOR_HTTP: 'http',
|
||||
LB_HEALTH_MONITOR_HTTPS: 'tcp'}
|
||||
|
||||
SESSION_PERSISTENCE_METHOD_MAP = {
|
||||
LB_SESSION_PERSISTENCE_SOURCE_IP: 'sourceip',
|
||||
LB_SESSION_PERSISTENCE_APP_COOKIE: 'cookie',
|
||||
LB_SESSION_PERSISTENCE_HTTP_COOKIE: 'cookie'}
|
||||
|
||||
SESSION_PERSISTENCE_COOKIE_MAP = {
|
||||
LB_SESSION_PERSISTENCE_APP_COOKIE: 'app',
|
||||
LB_SESSION_PERSISTENCE_HTTP_COOKIE: 'insert'}
|
||||
|
||||
LBAAS_FW_SECTION_NAME = 'LBaaS FW Rules'
|
||||
|
||||
MEMBER_ID_PFX = 'member-'
|
||||
|
||||
|
||||
def convert_lbaas_pool(lbaas_pool):
|
||||
"""
|
||||
@ -87,7 +36,7 @@ def convert_lbaas_pool(lbaas_pool):
|
||||
'name': 'pool_' + lbaas_pool['id'],
|
||||
'description': lbaas_pool.get('description',
|
||||
lbaas_pool.get('name')),
|
||||
'algorithm': BALANCE_MAP.get(
|
||||
'algorithm': lb_const.BALANCE_MAP.get(
|
||||
lbaas_pool.get('lb_method'), 'round-robin'),
|
||||
'transparent': False
|
||||
}
|
||||
@ -110,25 +59,27 @@ def convert_lbaas_app_profile(name, sess_persist, protocol):
|
||||
}
|
||||
# Since SSL Termination is not supported right now, so just use
|
||||
# sslPassthrough method if the protocol is HTTPS.
|
||||
if protocol == LB_PROTOCOL_HTTPS:
|
||||
if protocol == lb_const.LB_PROTOCOL_HTTPS:
|
||||
vcns_app_profile['sslPassthrough'] = True
|
||||
|
||||
persist_type = sess_persist.get('type')
|
||||
if persist_type:
|
||||
# If protocol is not HTTP, only source_ip is supported
|
||||
if (protocol != LB_PROTOCOL_HTTP and
|
||||
persist_type != LB_SESSION_PERSISTENCE_SOURCE_IP):
|
||||
if (protocol != lb_const.LB_PROTOCOL_HTTP and
|
||||
persist_type != lb_const.LB_SESSION_PERSISTENCE_SOURCE_IP):
|
||||
msg = (_('Invalid %(protocol)s persistence method: %(type)s') %
|
||||
{'protocol': protocol,
|
||||
'type': persist_type})
|
||||
raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)
|
||||
persistence = {
|
||||
'method': SESSION_PERSISTENCE_METHOD_MAP.get(persist_type)}
|
||||
if persist_type in SESSION_PERSISTENCE_COOKIE_MAP:
|
||||
'method':
|
||||
lb_const.SESSION_PERSISTENCE_METHOD_MAP.get(persist_type)}
|
||||
if persist_type in lb_const.SESSION_PERSISTENCE_COOKIE_MAP:
|
||||
persistence.update({
|
||||
'cookieName': sess_persist.get('cookie_name',
|
||||
'default_cookie_name'),
|
||||
'cookieMode': SESSION_PERSISTENCE_COOKIE_MAP[persist_type]})
|
||||
'cookieMode':
|
||||
lb_const.SESSION_PERSISTENCE_COOKIE_MAP[persist_type]})
|
||||
|
||||
vcns_app_profile['persistence'] = persistence
|
||||
return vcns_app_profile
|
||||
@ -159,7 +110,7 @@ def convert_lbaas_member(member):
|
||||
'weight': member['weight'],
|
||||
'port': member['protocol_port'],
|
||||
'monitorPort': member['protocol_port'],
|
||||
'name': get_member_id(member['id']),
|
||||
'name': lb_common.get_member_id(member['id']),
|
||||
'condition': 'enabled' if member['admin_state_up'] else 'disabled'}
|
||||
|
||||
|
||||
@ -168,8 +119,7 @@ def convert_lbaas_monitor(monitor):
|
||||
Transform OpenStack health monitor dict to NSXv health monitor dict.
|
||||
"""
|
||||
mon = {
|
||||
'type': HEALTH_MONITOR_MAP.get(
|
||||
monitor['type'], 'icmp'),
|
||||
'type': lb_const.HEALTH_MONITOR_MAP.get(monitor['type'], 'icmp'),
|
||||
'interval': monitor['delay'],
|
||||
'timeout': monitor['timeout'],
|
||||
'maxRetries': monitor['max_retries'],
|
||||
@ -183,72 +133,6 @@ def convert_lbaas_monitor(monitor):
|
||||
return mon
|
||||
|
||||
|
||||
def extract_resource_id(location_uri):
|
||||
"""
|
||||
Edge assigns an ID for each resource that is being created:
|
||||
it is postfixes the uri specified in the Location header.
|
||||
This ID should be used while updating/deleting this resource.
|
||||
"""
|
||||
uri_elements = location_uri.split('/')
|
||||
return uri_elements[-1]
|
||||
|
||||
|
||||
def get_subnet_primary_ip(ip_addr, address_groups):
|
||||
"""
|
||||
Retrieve the primary IP of an interface that's attached to the same subnet.
|
||||
"""
|
||||
addr_group = find_address_in_same_subnet(ip_addr, address_groups)
|
||||
return addr_group['primaryAddress'] if addr_group else None
|
||||
|
||||
|
||||
def find_address_in_same_subnet(ip_addr, address_groups):
|
||||
"""
|
||||
Lookup an address group with a matching subnet to ip_addr.
|
||||
If found, return address_group.
|
||||
"""
|
||||
for address_group in address_groups['addressGroups']:
|
||||
net_addr = '%(primaryAddress)s/%(subnetPrefixLength)s' % address_group
|
||||
if netaddr.IPAddress(ip_addr) in netaddr.IPNetwork(net_addr):
|
||||
return address_group
|
||||
|
||||
|
||||
def add_address_to_address_groups(ip_addr, address_groups):
|
||||
"""
|
||||
Add ip_addr as a secondary IP address to an address group which belongs to
|
||||
the same subnet.
|
||||
"""
|
||||
address_group = find_address_in_same_subnet(
|
||||
ip_addr, address_groups)
|
||||
if address_group:
|
||||
sec_addr = address_group.get('secondaryAddresses')
|
||||
if not sec_addr:
|
||||
sec_addr = {
|
||||
'type': 'secondary_addresses',
|
||||
'ipAddress': [ip_addr]}
|
||||
else:
|
||||
sec_addr['ipAddress'].append(ip_addr)
|
||||
address_group['secondaryAddresses'] = sec_addr
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def del_address_from_address_groups(ip_addr, address_groups):
|
||||
"""
|
||||
Delete ip_addr from secondary address list in address groups.
|
||||
"""
|
||||
address_group = find_address_in_same_subnet(ip_addr, address_groups)
|
||||
if address_group:
|
||||
sec_addr = address_group.get('secondaryAddresses')
|
||||
if sec_addr and ip_addr in sec_addr['ipAddress']:
|
||||
sec_addr['ipAddress'].remove(ip_addr)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def get_member_id(member_id):
|
||||
return MEMBER_ID_PFX + member_id
|
||||
|
||||
|
||||
class EdgeLbDriver(object):
|
||||
def __init__(self):
|
||||
super(EdgeLbDriver, self).__init__()
|
||||
@ -257,7 +141,7 @@ class EdgeLbDriver(object):
|
||||
self.vcns = None
|
||||
self._fw_section_id = None
|
||||
self._lb_plugin = None
|
||||
self._lb_driver_prop = None
|
||||
self._lbv1_driver_prop = None
|
||||
|
||||
def _get_lb_plugin(self):
|
||||
if not self._lb_plugin:
|
||||
@ -266,220 +150,70 @@ class EdgeLbDriver(object):
|
||||
return self._lb_plugin
|
||||
|
||||
@property
|
||||
def _lb_driver(self):
|
||||
if not self._lb_driver_prop:
|
||||
def lbv1_driver(self):
|
||||
if not self._lbv1_driver_prop:
|
||||
plugin = self._get_lb_plugin()
|
||||
self._lb_driver_prop = plugin.drivers['vmwareedge']
|
||||
self._lbv1_driver_prop = plugin.drivers['vmwareedge']
|
||||
|
||||
return self._lb_driver_prop
|
||||
return self._lbv1_driver_prop
|
||||
|
||||
def _get_lbaas_fw_section_id(self):
|
||||
if not self._fw_section_id:
|
||||
# Avoid concurrent creation of section by multiple neutron
|
||||
# instances
|
||||
with locking.LockManager.get_lock('lbaas-section-creation'):
|
||||
fw_section_id = self.vcns.get_section_id(LBAAS_FW_SECTION_NAME)
|
||||
if not fw_section_id:
|
||||
section = et.Element('section')
|
||||
section.attrib['name'] = LBAAS_FW_SECTION_NAME
|
||||
sect = self.vcns.create_section('ip',
|
||||
et.tostring(section))[1]
|
||||
fw_section_id = et.fromstring(sect).attrib['id']
|
||||
self._fw_section_id = fw_section_id
|
||||
self._fw_section_id = lb_common.get_lbaas_fw_section_id(self.vcns)
|
||||
return self._fw_section_id
|
||||
|
||||
def _get_lb_edge_id(self, context, subnet_id):
|
||||
"""
|
||||
Grab the id of an Edge appliance that is connected to subnet_id.
|
||||
"""
|
||||
subnet = self.callbacks.plugin.get_subnet(context, subnet_id)
|
||||
net_id = subnet.get('network_id')
|
||||
filters = {'network_id': [net_id],
|
||||
'device_owner': ['network:router_interface']}
|
||||
attached_routers = self.callbacks.plugin.get_ports(
|
||||
context.elevated(), filters=filters,
|
||||
fields=['device_id'])
|
||||
|
||||
for attached_router in attached_routers:
|
||||
router = self.callbacks.plugin.get_router(
|
||||
context, attached_router['device_id'])
|
||||
if router['router_type'] == 'exclusive':
|
||||
rtr_bindings = nsxv_db.get_nsxv_router_binding(
|
||||
context.session, router['id'])
|
||||
return rtr_bindings['edge_id']
|
||||
|
||||
def _vip_as_secondary_ip(self, edge_id, vip, handler):
|
||||
with locking.LockManager.get_lock(edge_id):
|
||||
r = self.vcns.get_interfaces(edge_id)[1]
|
||||
vnics = r.get('vnics', [])
|
||||
for vnic in vnics:
|
||||
if vnic['type'] == 'trunk':
|
||||
for sub_interface in vnic.get('subInterfaces').get(
|
||||
'subInterfaces'):
|
||||
address_groups = sub_interface.get('addressGroups')
|
||||
if handler(vip, address_groups):
|
||||
self.vcns.update_interface(edge_id, vnic)
|
||||
return True
|
||||
else:
|
||||
address_groups = vnic.get('addressGroups')
|
||||
if handler(vip, address_groups):
|
||||
self.vcns.update_interface(edge_id, vnic)
|
||||
return True
|
||||
return False
|
||||
|
||||
def _add_vip_as_secondary_ip(self, edge_id, vip):
|
||||
"""
|
||||
Edge appliance requires that a VIP will be configured as a primary
|
||||
or a secondary IP address on an interface.
|
||||
To do so, we locate an interface which is connected to the same subnet
|
||||
that vip belongs to.
|
||||
This can be a regular interface, on a sub-interface on a trunk.
|
||||
"""
|
||||
if not self._vip_as_secondary_ip(
|
||||
edge_id, vip, add_address_to_address_groups):
|
||||
|
||||
msg = _('Failed to add VIP %(vip)s as secondary IP on '
|
||||
'Edge %(edge_id)s') % {'vip': vip, 'edge_id': edge_id}
|
||||
raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)
|
||||
|
||||
def _del_vip_as_secondary_ip(self, edge_id, vip):
|
||||
"""
|
||||
While removing vip, delete the secondary interface from Edge config.
|
||||
"""
|
||||
if not self._vip_as_secondary_ip(
|
||||
edge_id, vip, del_address_from_address_groups):
|
||||
|
||||
msg = _('Failed to delete VIP %(vip)s as secondary IP on '
|
||||
'Edge %(edge_id)s') % {'vip': vip, 'edge_id': edge_id}
|
||||
raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)
|
||||
|
||||
def _get_edge_ips(self, edge_id):
|
||||
edge_ips = []
|
||||
r = self.vcns.get_interfaces(edge_id)[1]
|
||||
vnics = r.get('vnics', [])
|
||||
for vnic in vnics:
|
||||
if vnic['type'] == 'trunk':
|
||||
for sub_interface in vnic.get('subInterfaces').get(
|
||||
'subInterfaces'):
|
||||
address_groups = sub_interface.get('addressGroups')
|
||||
for address_group in address_groups['addressGroups']:
|
||||
edge_ips.append(address_group['primaryAddress'])
|
||||
|
||||
else:
|
||||
address_groups = vnic.get('addressGroups')
|
||||
for address_group in address_groups['addressGroups']:
|
||||
edge_ips.append(address_group['primaryAddress'])
|
||||
return edge_ips
|
||||
|
||||
def _update_pool_fw_rule(self, context, pool_id, edge_id,
|
||||
operation=None, address=None):
|
||||
edge_ips = self._get_edge_ips(edge_id)
|
||||
|
||||
def _get_pool_member_ips(self, context, pool_id, operation, address):
|
||||
plugin = self._get_lb_plugin()
|
||||
with locking.LockManager.get_lock('lbaas-fw-section'):
|
||||
members = plugin.get_members(
|
||||
context,
|
||||
filters={'pool_id': [pool_id]},
|
||||
fields=['address'])
|
||||
member_ips = [member['address'] for member in members]
|
||||
if operation == 'add' and address not in member_ips:
|
||||
member_ips.append(address)
|
||||
member_ips = {member['address'] for member in members}
|
||||
if operation == 'add':
|
||||
member_ips.add(address)
|
||||
elif operation == 'del' and address in member_ips:
|
||||
member_ips.remove(address)
|
||||
|
||||
section_uri = '%s/%s/%s' % (nsxv_api.FIREWALL_PREFIX,
|
||||
'layer3sections',
|
||||
self._get_lbaas_fw_section_id())
|
||||
xml_section = self.vcns.get_section(section_uri)[1]
|
||||
section = et.fromstring(xml_section)
|
||||
pool_rule = None
|
||||
for rule in section.iter('rule'):
|
||||
if rule.find('name').text == pool_id:
|
||||
pool_rule = rule
|
||||
if member_ips:
|
||||
pool_rule.find('sources').find('source').find(
|
||||
'value').text = (','.join(edge_ips))
|
||||
pool_rule.find('destinations').find(
|
||||
'destination').find('value').text = ','.join(
|
||||
member_ips)
|
||||
else:
|
||||
section.remove(pool_rule)
|
||||
break
|
||||
|
||||
if member_ips and pool_rule is None:
|
||||
pool_rule = et.SubElement(section, 'rule')
|
||||
et.SubElement(pool_rule, 'name').text = pool_id
|
||||
et.SubElement(pool_rule, 'action').text = 'allow'
|
||||
sources = et.SubElement(pool_rule, 'sources')
|
||||
sources.attrib['excluded'] = 'false'
|
||||
source = et.SubElement(sources, 'source')
|
||||
et.SubElement(source, 'type').text = 'Ipv4Address'
|
||||
et.SubElement(source, 'value').text = ','.join(edge_ips)
|
||||
|
||||
destinations = et.SubElement(pool_rule, 'destinations')
|
||||
destinations.attrib['excluded'] = 'false'
|
||||
destination = et.SubElement(destinations, 'destination')
|
||||
et.SubElement(destination, 'type').text = 'Ipv4Address'
|
||||
et.SubElement(destination, 'value').text = ','.join(member_ips)
|
||||
|
||||
self.vcns.update_section(section_uri,
|
||||
et.tostring(section, encoding="us-ascii"),
|
||||
None)
|
||||
|
||||
def _add_vip_fw_rule(self, edge_id, vip_id, ip_address):
|
||||
fw_rule = {
|
||||
'firewallRules': [
|
||||
{'action': 'accept', 'destination': {
|
||||
'ipAddress': [ip_address]},
|
||||
'enabled': True,
|
||||
'name': vip_id}]}
|
||||
|
||||
with locking.LockManager.get_lock(edge_id):
|
||||
h = self.vcns.add_firewall_rule(edge_id, fw_rule)[0]
|
||||
fw_rule_id = extract_resource_id(h['location'])
|
||||
|
||||
return fw_rule_id
|
||||
|
||||
def _del_vip_fw_rule(self, edge_id, vip_fw_rule_id):
|
||||
with locking.LockManager.get_lock(edge_id):
|
||||
self.vcns.delete_firewall_rule(edge_id, vip_fw_rule_id)
|
||||
return list(member_ips)
|
||||
|
||||
def create_pool(self, context, pool):
|
||||
LOG.debug('Creating pool %s', pool)
|
||||
edge_id = self._get_lb_edge_id(context, pool['subnet_id'])
|
||||
edge_id = lb_common.get_lbaas_edge_id_for_subnet(
|
||||
context, self.callbacks.plugin, pool['subnet_id'])
|
||||
|
||||
if edge_id is None:
|
||||
self._lb_driver.pool_failed(context, pool)
|
||||
self.lbv1_driver.pool_failed(context, pool)
|
||||
msg = _(
|
||||
'No suitable Edge found for subnet %s') % pool['subnet_id']
|
||||
raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)
|
||||
|
||||
edge_pool = convert_lbaas_pool(pool)
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id):
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
h = self.vcns.create_pool(edge_id, edge_pool)[0]
|
||||
edge_pool_id = extract_resource_id(h['location'])
|
||||
self._lb_driver.create_pool_successful(
|
||||
edge_pool_id = lb_common.extract_resource_id(h['location'])
|
||||
self.lbv1_driver.create_pool_successful(
|
||||
context, pool, edge_id, edge_pool_id)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.pool_failed(context, pool)
|
||||
self.lbv1_driver.pool_failed(context, pool)
|
||||
LOG.error(_LE('Failed to create pool %s'), pool['id'])
|
||||
|
||||
def update_pool(self, context, old_pool, pool, pool_mapping):
|
||||
LOG.debug('Updating pool %s to %s', old_pool, pool)
|
||||
edge_pool = convert_lbaas_pool(pool)
|
||||
try:
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id']):
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id'],
|
||||
external=True):
|
||||
self.vcns.update_pool(pool_mapping['edge_id'],
|
||||
pool_mapping['edge_pool_id'],
|
||||
edge_pool)
|
||||
self._lb_driver.pool_successful(context, pool)
|
||||
self.lbv1_driver.pool_successful(context, pool)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.pool_failed(context, pool)
|
||||
self.lbv1_driver.pool_failed(context, pool)
|
||||
LOG.error(_LE('Failed to update pool %s'), pool['id'])
|
||||
|
||||
def delete_pool(self, context, pool, pool_mapping):
|
||||
@ -487,23 +221,24 @@ class EdgeLbDriver(object):
|
||||
|
||||
if pool_mapping:
|
||||
try:
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id']):
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id'],
|
||||
external=True):
|
||||
self.vcns.delete_pool(pool_mapping['edge_id'],
|
||||
pool_mapping['edge_pool_id'])
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.pool_failed(context, pool)
|
||||
self.lbv1_driver.pool_failed(context, pool)
|
||||
LOG.error(_LE('Failed to delete pool %s'), pool['id'])
|
||||
else:
|
||||
LOG.error(_LE('No mapping found for pool %s'), pool['id'])
|
||||
|
||||
self._lb_driver.delete_pool_successful(context, pool)
|
||||
self.lbv1_driver.delete_pool_successful(context, pool)
|
||||
|
||||
def create_vip(self, context, vip, pool_mapping):
|
||||
LOG.debug('Create VIP %s', vip)
|
||||
|
||||
app_profile = convert_lbaas_app_profile(
|
||||
vip['id'], vip.get('session_persistence') or {},
|
||||
vip['id'], vip.get('session_persistence', {}),
|
||||
vip.get('protocol'))
|
||||
|
||||
if not pool_mapping:
|
||||
@ -512,34 +247,35 @@ class EdgeLbDriver(object):
|
||||
raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)
|
||||
edge_id = pool_mapping['edge_id']
|
||||
|
||||
app_profile_id = None
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id):
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
h = (self.vcns.create_app_profile(edge_id, app_profile))[0]
|
||||
app_profile_id = extract_resource_id(h['location'])
|
||||
app_profile_id = lb_common.extract_resource_id(h['location'])
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.vip_failed(context, vip)
|
||||
self.lbv1_driver.vip_failed(context, vip)
|
||||
LOG.error(_LE('Failed to create app profile on edge: %s'),
|
||||
edge_id)
|
||||
|
||||
edge_vip = convert_lbaas_vip(vip, app_profile_id, pool_mapping)
|
||||
try:
|
||||
self._add_vip_as_secondary_ip(edge_id, vip['address'])
|
||||
with locking.LockManager.get_lock(edge_id):
|
||||
h = self.vcns.create_vip(edge_id, edge_vip)[0]
|
||||
edge_vip_id = extract_resource_id(h['location'])
|
||||
edge_fw_rule_id = self._add_vip_fw_rule(edge_id, vip['id'],
|
||||
lb_common.add_vip_as_secondary_ip(self.vcns, edge_id,
|
||||
vip['address'])
|
||||
self._lb_driver.create_vip_successful(
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
h = self.vcns.create_vip(edge_id, edge_vip)[0]
|
||||
edge_vip_id = lb_common.extract_resource_id(h['location'])
|
||||
edge_fw_rule_id = lb_common.add_vip_fw_rule(self.vcns,
|
||||
edge_id, vip['id'],
|
||||
vip['address'])
|
||||
self.lbv1_driver.create_vip_successful(
|
||||
context, vip, edge_id, app_profile_id, edge_vip_id,
|
||||
edge_fw_rule_id)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.vip_failed(context, vip)
|
||||
self.lbv1_driver.vip_failed(context, vip)
|
||||
LOG.error(_LE('Failed to create vip on Edge: %s'), edge_id)
|
||||
with locking.LockManager.get_lock(edge_id):
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.delete_app_profile(edge_id, app_profile_id)
|
||||
|
||||
def update_vip(self, context, old_vip, vip, pool_mapping, vip_mapping):
|
||||
@ -549,26 +285,26 @@ class EdgeLbDriver(object):
|
||||
edge_vip_id = vip_mapping['edge_vse_id']
|
||||
app_profile_id = vip_mapping['edge_app_profile_id']
|
||||
app_profile = convert_lbaas_app_profile(
|
||||
vip['name'], vip.get('session_persistence') or {},
|
||||
vip['name'], vip.get('session_persistence', {}),
|
||||
vip.get('protocol'))
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id):
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.update_app_profile(edge_id, app_profile_id,
|
||||
app_profile)
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.vip_failed(context, vip)
|
||||
self.lbv1_driver.vip_failed(context, vip)
|
||||
LOG.error(_LE('Failed to update app profile on edge: %s'),
|
||||
edge_id)
|
||||
|
||||
edge_vip = convert_lbaas_vip(vip, app_profile_id, pool_mapping)
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id):
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.update_vip(edge_id, edge_vip_id, edge_vip)
|
||||
self._lb_driver.vip_successful(context, vip)
|
||||
self.lbv1_driver.vip_successful(context, vip)
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.vip_failed(context, vip)
|
||||
self.lbv1_driver.vip_failed(context, vip)
|
||||
LOG.error(_LE('Failed to update vip on edge: %s'), edge_id)
|
||||
|
||||
def delete_vip(self, context, vip, vip_mapping):
|
||||
@ -582,36 +318,40 @@ class EdgeLbDriver(object):
|
||||
app_profile_id = vip_mapping['edge_app_profile_id']
|
||||
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id):
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.delete_vip(edge_id, edge_vse_id)
|
||||
self._del_vip_as_secondary_ip(edge_id, vip['address'])
|
||||
self._del_vip_fw_rule(edge_id, vip_mapping['edge_fw_rule_id'])
|
||||
lb_common.del_vip_as_secondary_ip(self.vcns, edge_id,
|
||||
vip['address'])
|
||||
lb_common.del_vip_fw_rule(self.vcns, edge_id,
|
||||
vip_mapping['edge_fw_rule_id'])
|
||||
|
||||
except nsxv_exc.ResourceNotFound:
|
||||
LOG.error(_LE('vip not found on edge: %s'), edge_id)
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.vip_failed(context, vip)
|
||||
self.lbv1_driver.vip_failed(context, vip)
|
||||
LOG.error(
|
||||
_LE('Failed to delete vip on edge: %s'), edge_id)
|
||||
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id):
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.delete_app_profile(edge_id, app_profile_id)
|
||||
except nsxv_exc.ResourceNotFound:
|
||||
LOG.error(_LE('app profile not found on edge: %s'), edge_id)
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.vip_failed(context, vip)
|
||||
self.lbv1_driver.vip_failed(context, vip)
|
||||
LOG.error(
|
||||
_LE('Failed to delete app profile on Edge: %s'),
|
||||
edge_id)
|
||||
|
||||
self._lb_driver.delete_vip_successful(context, vip)
|
||||
self.lbv1_driver.delete_vip_successful(context, vip)
|
||||
|
||||
def create_member(self, context, member, pool_mapping):
|
||||
LOG.debug('Creating member %s', member)
|
||||
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id']):
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id'],
|
||||
external=True):
|
||||
edge_pool = self.vcns.get_pool(pool_mapping['edge_id'],
|
||||
pool_mapping['edge_pool_id'])[1]
|
||||
edge_member = convert_lbaas_member(member)
|
||||
@ -627,28 +367,31 @@ class EdgeLbDriver(object):
|
||||
pool_mapping['edge_pool_id'],
|
||||
edge_pool)
|
||||
|
||||
self._update_pool_fw_rule(context, member['pool_id'],
|
||||
pool_mapping['edge_id'],
|
||||
'add',
|
||||
member['address'])
|
||||
self._lb_driver.member_successful(context, member)
|
||||
member_ips = self._get_pool_member_ips(
|
||||
context, member['pool_id'], 'add', member['address'])
|
||||
lb_common.update_pool_fw_rule(
|
||||
self.vcns, member['pool_id'], pool_mapping['edge_id'],
|
||||
self._get_lbaas_fw_section_id(), member_ips)
|
||||
|
||||
self.lbv1_driver.member_successful(context, member)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.member_failed(context, member)
|
||||
self.lbv1_driver.member_failed(context, member)
|
||||
LOG.error(_LE('Failed to create member on edge: %s'),
|
||||
pool_mapping['edge_id'])
|
||||
|
||||
def update_member(self, context, old_member, member, pool_mapping):
|
||||
LOG.debug('Updating member %s to %s', old_member, member)
|
||||
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id']):
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id'],
|
||||
external=True):
|
||||
edge_pool = self.vcns.get_pool(pool_mapping['edge_id'],
|
||||
pool_mapping['edge_pool_id'])[1]
|
||||
|
||||
edge_member = convert_lbaas_member(member)
|
||||
for i, m in enumerate(edge_pool['member']):
|
||||
if m['name'] == get_member_id(member['id']):
|
||||
if m['name'] == lb_common.get_member_id(member['id']):
|
||||
edge_pool['member'][i] = edge_member
|
||||
break
|
||||
|
||||
@ -656,10 +399,10 @@ class EdgeLbDriver(object):
|
||||
self.vcns.update_pool(pool_mapping['edge_id'],
|
||||
pool_mapping['edge_pool_id'],
|
||||
edge_pool)
|
||||
self._lb_driver.member_successful(context, member)
|
||||
self.lbv1_driver.member_successful(context, member)
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.member_failed(context, member)
|
||||
self.lbv1_driver.member_failed(context, member)
|
||||
LOG.error(_LE('Failed to update member on edge: %s'),
|
||||
pool_mapping['edge_id'])
|
||||
|
||||
@ -667,13 +410,14 @@ class EdgeLbDriver(object):
|
||||
LOG.debug('Deleting member %s', member)
|
||||
|
||||
if pool_mapping:
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id']):
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id'],
|
||||
external=True):
|
||||
edge_pool = self.vcns.get_pool(
|
||||
pool_mapping['edge_id'],
|
||||
pool_mapping['edge_pool_id'])[1]
|
||||
|
||||
for i, m in enumerate(edge_pool['member']):
|
||||
if m['name'] == get_member_id(member['id']):
|
||||
if m['name'] == lb_common.get_member_id(member['id']):
|
||||
edge_pool['member'].pop(i)
|
||||
break
|
||||
|
||||
@ -681,13 +425,15 @@ class EdgeLbDriver(object):
|
||||
self.vcns.update_pool(pool_mapping['edge_id'],
|
||||
pool_mapping['edge_pool_id'],
|
||||
edge_pool)
|
||||
self._update_pool_fw_rule(context, member['pool_id'],
|
||||
pool_mapping['edge_id'],
|
||||
'del',
|
||||
member['address'])
|
||||
member_ips = self._get_pool_member_ips(
|
||||
context, member['pool_id'], 'del', member['address'])
|
||||
lb_common.update_pool_fw_rule(
|
||||
self.vcns, member['pool_id'], pool_mapping['edge_id'],
|
||||
self._get_lbaas_fw_section_id(), member_ips)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.member_failed(context, member)
|
||||
self.lbv1_driver.member_failed(context, member)
|
||||
LOG.error(_LE('Failed to update member on edge: %s'),
|
||||
pool_mapping['edge_id'])
|
||||
|
||||
@ -699,7 +445,8 @@ class EdgeLbDriver(object):
|
||||
LOG.debug('Create HM %s', health_monitor)
|
||||
|
||||
edge_mon_id = None
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id']):
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id'],
|
||||
external=True):
|
||||
# 1st, we find if we already have a pool with the same monitor, on
|
||||
# the same Edge appliance.
|
||||
# If there is no pool on this Edge which is already associated with
|
||||
@ -711,10 +458,10 @@ class EdgeLbDriver(object):
|
||||
try:
|
||||
h = self.vcns.create_health_monitor(
|
||||
pool_mapping['edge_id'], edge_monitor)[0]
|
||||
edge_mon_id = extract_resource_id(h['location'])
|
||||
edge_mon_id = lb_common.extract_resource_id(h['location'])
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
self._lb_driver.pool_health_monitor_failed(context,
|
||||
self.lbv1_driver.pool_health_monitor_failed(context,
|
||||
health_monitor,
|
||||
pool_id)
|
||||
with excutils.save_and_reraise_exception():
|
||||
@ -737,14 +484,14 @@ class EdgeLbDriver(object):
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.pool_health_monitor_failed(context,
|
||||
self.lbv1_driver.pool_health_monitor_failed(context,
|
||||
health_monitor,
|
||||
pool_id)
|
||||
LOG.error(
|
||||
_LE('Failed to associate monitor on edge: %s'),
|
||||
pool_mapping['edge_id'])
|
||||
|
||||
self._lb_driver.create_pool_health_monitor_successful(
|
||||
self.lbv1_driver.create_pool_health_monitor_successful(
|
||||
context, health_monitor, pool_id, pool_mapping['edge_id'],
|
||||
edge_mon_id)
|
||||
|
||||
@ -755,7 +502,8 @@ class EdgeLbDriver(object):
|
||||
edge_monitor = convert_lbaas_monitor(health_monitor)
|
||||
|
||||
try:
|
||||
with locking.LockManager.get_lock(mon_mapping['edge_id']):
|
||||
with locking.LockManager.get_lock(mon_mapping['edge_id'],
|
||||
external=True):
|
||||
self.vcns.update_health_monitor(
|
||||
mon_mapping['edge_id'],
|
||||
mon_mapping['edge_monitor_id'],
|
||||
@ -763,14 +511,14 @@ class EdgeLbDriver(object):
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.pool_health_monitor_failed(context,
|
||||
self.lbv1_driver.pool_health_monitor_failed(context,
|
||||
health_monitor,
|
||||
pool_id)
|
||||
LOG.error(
|
||||
_LE('Failed to update monitor on edge: %s'),
|
||||
mon_mapping['edge_id'])
|
||||
|
||||
self._lb_driver.pool_health_monitor_successful(context,
|
||||
self.lbv1_driver.pool_health_monitor_successful(context,
|
||||
health_monitor,
|
||||
pool_id)
|
||||
|
||||
@ -782,7 +530,8 @@ class EdgeLbDriver(object):
|
||||
if not mon_mapping:
|
||||
return
|
||||
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id']):
|
||||
with locking.LockManager.get_lock(pool_mapping['edge_id'],
|
||||
external=True):
|
||||
edge_pool = self.vcns.get_pool(edge_id,
|
||||
pool_mapping['edge_pool_id'])[1]
|
||||
edge_pool['monitorId'].remove(mon_mapping['edge_monitor_id'])
|
||||
@ -793,7 +542,7 @@ class EdgeLbDriver(object):
|
||||
edge_pool)
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.pool_health_monitor_failed(context,
|
||||
self.lbv1_driver.pool_health_monitor_failed(context,
|
||||
health_monitor,
|
||||
pool_id)
|
||||
LOG.error(
|
||||
@ -808,13 +557,13 @@ class EdgeLbDriver(object):
|
||||
mon_mapping['edge_monitor_id'])
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self._lb_driver.pool_health_monitor_failed(
|
||||
self.lbv1_driver.pool_health_monitor_failed(
|
||||
context, health_monitor, pool_id)
|
||||
LOG.error(
|
||||
_LE('Failed to delete monitor on edge: %s'),
|
||||
mon_mapping['edge_id'])
|
||||
|
||||
self._lb_driver.delete_pool_health_monitor_successful(
|
||||
self.lbv1_driver.delete_pool_health_monitor_successful(
|
||||
context, health_monitor, pool_id, mon_mapping)
|
||||
|
||||
def stats(self, context, pool_id, pool_mapping):
|
||||
@ -849,7 +598,7 @@ class EdgeLbDriver(object):
|
||||
|
||||
member_stats = {}
|
||||
for member in pool_stats.get('member', []):
|
||||
member_id = member['name'][len(MEMBER_ID_PFX):]
|
||||
member_id = member['name'][len(lb_common.MEMBER_ID_PFX):]
|
||||
if member_map[member_id] != 'ERROR':
|
||||
member_stats[member_id] = {
|
||||
'status': ('INACTIVE'
|
||||
@ -865,7 +614,7 @@ class EdgeLbDriver(object):
|
||||
'total_connections': 0}
|
||||
|
||||
def is_edge_in_use(self, edge_id):
|
||||
return self._lb_driver.is_edge_in_use(edge_id)
|
||||
return self.lbv1_driver.is_edge_in_use(edge_id)
|
||||
|
||||
def is_subnet_in_use(self, context, subnet_id):
|
||||
plugin = self._get_lb_plugin()
|
0
vmware_nsx/services/lbaas/nsx_v/v2/__init__.py
Normal file
0
vmware_nsx/services/lbaas/nsx_v/v2/__init__.py
Normal file
52
vmware_nsx/services/lbaas/nsx_v/v2/base_mgr.py
Normal file
52
vmware_nsx/services/lbaas/nsx_v/v2/base_mgr.py
Normal file
@ -0,0 +1,52 @@
|
||||
# Copyright 2015 VMware, Inc.
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron import manager
|
||||
from neutron.plugins.common import constants
|
||||
|
||||
|
||||
class EdgeLoadbalancerBaseManager(object):
|
||||
_lbv2_driver = None
|
||||
_core_plugin = None
|
||||
|
||||
def __init__(self, vcns_driver):
|
||||
super(EdgeLoadbalancerBaseManager, self).__init__()
|
||||
self.vcns_driver = vcns_driver
|
||||
|
||||
def _get_plugin(self, plugin_type):
|
||||
loaded_plugins = manager.NeutronManager.get_service_plugins()
|
||||
return loaded_plugins[plugin_type]
|
||||
|
||||
@property
|
||||
def lbv2_driver(self):
|
||||
if not EdgeLoadbalancerBaseManager._lbv2_driver:
|
||||
plugin = self._get_plugin(
|
||||
constants.LOADBALANCERV2)
|
||||
EdgeLoadbalancerBaseManager._lbv2_driver = (
|
||||
plugin.drivers['vmwareedge'])
|
||||
|
||||
return EdgeLoadbalancerBaseManager._lbv2_driver
|
||||
|
||||
@property
|
||||
def core_plugin(self):
|
||||
if not EdgeLoadbalancerBaseManager._core_plugin:
|
||||
EdgeLoadbalancerBaseManager._core_plugin = (
|
||||
self._get_plugin(constants.CORE))
|
||||
|
||||
return EdgeLoadbalancerBaseManager._core_plugin
|
||||
|
||||
@property
|
||||
def vcns(self):
|
||||
return self.vcns_driver.vcns
|
@ -0,0 +1,36 @@
|
||||
# Copyright 2015 VMware, Inc.
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from oslo_log import helpers as log_helpers
|
||||
from oslo_log import log as logging
|
||||
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import healthmon_mgr as hm_mgr
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import listener_mgr
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import loadbalancer_mgr as lb_mgr
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import member_mgr
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import pool_mgr
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EdgeLoadbalancerDriverV2(object):
|
||||
@log_helpers.log_method_call
|
||||
def __init__(self):
|
||||
self.loadbalancer = lb_mgr.EdgeLoadBalancerManager(self)
|
||||
self.listener = listener_mgr.EdgeListenerManager(self)
|
||||
self.pool = pool_mgr.EdgePoolManager(self)
|
||||
self.member = member_mgr.EdgeMemberManager(self)
|
||||
self.healthmonitor = hm_mgr.EdgeHealthMonitorManager(self)
|
186
vmware_nsx/services/lbaas/nsx_v/v2/healthmon_mgr.py
Normal file
186
vmware_nsx/services/lbaas/nsx_v/v2/healthmon_mgr.py
Normal file
@ -0,0 +1,186 @@
|
||||
# Copyright 2015 VMware, Inc.
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron.i18n import _LE
|
||||
from oslo_log import helpers as log_helpers
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
||||
from vmware_nsx.common import locking
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as nsxv_exc
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_const as lb_const
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import base_mgr
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EdgeHealthMonitorManager(base_mgr.EdgeLoadbalancerBaseManager):
|
||||
|
||||
def _convert_lbaas_monitor(self, hm):
|
||||
"""
|
||||
Transform OpenStack health monitor dict to NSXv health monitor dict.
|
||||
"""
|
||||
mon = {
|
||||
'type': lb_const.HEALTH_MONITOR_MAP.get(hm.type, 'icmp'),
|
||||
'interval': hm.delay,
|
||||
'timeout': hm.timeout,
|
||||
'maxRetries': hm.max_retries,
|
||||
'name': hm.id}
|
||||
|
||||
if hm.http_method:
|
||||
mon['method'] = hm.http_method
|
||||
|
||||
if hm.url_path:
|
||||
mon['url'] = hm.url_path
|
||||
return mon
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def __init__(self, vcns_driver):
|
||||
super(EdgeHealthMonitorManager, self).__init__(vcns_driver)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def create(self, context, hm):
|
||||
listener = hm.pool.listener
|
||||
lb_id = listener.loadbalancer_id
|
||||
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb_id)
|
||||
pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding(
|
||||
context.session, lb_id, listener.id, hm.pool.id)
|
||||
|
||||
edge_id = lb_binding['edge_id']
|
||||
edge_pool_id = pool_binding['edge_pool_id']
|
||||
|
||||
hm_binding = nsxv_db.get_nsxv_lbaas_monitor_binding(
|
||||
context.session, lb_id, listener.id, hm.pool.id, hm.id, edge_id)
|
||||
edge_mon_id = None
|
||||
|
||||
if hm_binding:
|
||||
edge_mon_id = hm_binding['edge_mon_id']
|
||||
else:
|
||||
edge_monitor = self._convert_lbaas_monitor(hm)
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
h = self.vcns.create_health_monitor(edge_id,
|
||||
edge_monitor)[0]
|
||||
edge_mon_id = lb_common.extract_resource_id(h['location'])
|
||||
|
||||
nsxv_db.add_nsxv_lbaas_monitor_binding(
|
||||
context.session, lb_id, listener.id, hm.pool.id, hm.id,
|
||||
edge_id, edge_mon_id)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.health_monitor.failed_completion(
|
||||
context, hm)
|
||||
LOG.error(_LE('Failed to create health monitor on edge: %s'
|
||||
), edge_id)
|
||||
|
||||
try:
|
||||
# Associate monitor with Edge pool
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
edge_pool = self.vcns.get_pool(edge_id, edge_pool_id)[1]
|
||||
if edge_pool.get('monitorId'):
|
||||
edge_pool['monitorId'].append(edge_mon_id)
|
||||
else:
|
||||
edge_pool['monitorId'] = [edge_mon_id]
|
||||
|
||||
self.vcns.update_pool(edge_id, edge_pool_id, edge_pool)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.health_monitor.failed_completion(context, hm)
|
||||
LOG.error(
|
||||
_LE('Failed to create health monitor on edge: %s'),
|
||||
edge_id)
|
||||
|
||||
self.lbv2_driver.health_monitor.successful_completion(context, hm)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def update(self, context, old_hm, new_hm):
|
||||
listener = new_hm.pool.listener
|
||||
lb_id = listener.loadbalancer_id
|
||||
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb_id)
|
||||
|
||||
edge_id = lb_binding['edge_id']
|
||||
|
||||
hm_binding = nsxv_db.get_nsxv_lbaas_monitor_binding(
|
||||
context.session, lb_id, listener.id, new_hm.pool.id, new_hm.id,
|
||||
edge_id)
|
||||
|
||||
edge_monitor = self._convert_lbaas_monitor(new_hm)
|
||||
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.update_health_monitor(edge_id,
|
||||
hm_binding['edge_mon_id'],
|
||||
edge_monitor)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.health_monitor.failed_completion(context,
|
||||
new_hm)
|
||||
LOG.error(
|
||||
_LE('Failed to update monitor on edge: %s'), edge_id)
|
||||
|
||||
self.lbv2_driver.health_monitor.successful_completion(context, new_hm)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def delete(self, context, hm):
|
||||
listener = hm.pool.listener
|
||||
lb_id = listener.loadbalancer_id
|
||||
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb_id)
|
||||
pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding(
|
||||
context.session, lb_id, listener.id, hm.pool.id)
|
||||
|
||||
edge_id = lb_binding['edge_id']
|
||||
edge_pool_id = pool_binding['edge_pool_id']
|
||||
|
||||
hm_binding = nsxv_db.get_nsxv_lbaas_monitor_binding(
|
||||
context.session, lb_id, listener.id, hm.pool.id, hm.id, edge_id)
|
||||
|
||||
edge_pool = self.vcns.get_pool(edge_id, edge_pool_id)[1]
|
||||
edge_pool['monitorId'].remove(hm_binding['edge_mon_id'])
|
||||
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.update_pool(edge_id, edge_pool_id, edge_pool)
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.health_monitor.failed_completion(context, hm)
|
||||
LOG.error(
|
||||
_LE('Failed to delete monitor mapping on edge: %s'),
|
||||
edge_id)
|
||||
|
||||
# If this monitor is not used on this edge anymore, delete it
|
||||
if not edge_pool['monitorId']:
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.delete_health_monitor(hm_binding['edge_id'],
|
||||
hm_binding['edge_mon_id'])
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.health_monitor.failed_completion(context,
|
||||
hm)
|
||||
LOG.error(
|
||||
_LE('Failed to delete monitor on edge: %s'), edge_id)
|
||||
|
||||
nsxv_db.del_nsxv_lbaas_monitor_binding(
|
||||
context.session, lb_id, listener.id, hm.pool.id, hm.id, edge_id)
|
||||
self.lbv2_driver.health_monitor.successful_completion(
|
||||
context, hm, delete=True)
|
278
vmware_nsx/services/lbaas/nsx_v/v2/listener_mgr.py
Normal file
278
vmware_nsx/services/lbaas/nsx_v/v2/listener_mgr.py
Normal file
@ -0,0 +1,278 @@
|
||||
# Copyright 2015 VMware, Inc.
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron.i18n import _LE
|
||||
from oslo_log import helpers as log_helpers
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
||||
from vmware_nsx.common import exceptions as nsxv_exc
|
||||
from vmware_nsx.common import locking
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as vcns_exc
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_const as lb_const
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import base_mgr
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def listener_to_edge_app_profile(listener, edge_cert_id):
|
||||
edge_app_profile = {
|
||||
'insertXForwardedFor': False,
|
||||
'name': listener.id,
|
||||
'serverSslEnabled': False,
|
||||
'sslPassthrough': False,
|
||||
'template': listener.protocol,
|
||||
}
|
||||
|
||||
if listener.protocol == 'HTTPS':
|
||||
if edge_cert_id:
|
||||
edge_app_profile['clientSsl'] = {
|
||||
'caCertificate': [],
|
||||
'clientAuth': 'ignore',
|
||||
'crlCertificate': [],
|
||||
'serviceCertificate': [edge_cert_id]}
|
||||
else:
|
||||
edge_app_profile['sslPassthrough'] = True
|
||||
|
||||
if listener.default_pool:
|
||||
persistence = None
|
||||
if listener.pool.sessionpersistence:
|
||||
persistence = {
|
||||
'method':
|
||||
lb_const.SESSION_PERSISTENCE_METHOD_MAP.get(
|
||||
listener.pool.sessionpersistence.type)}
|
||||
|
||||
if (listener.pool.sessionpersistence.type in
|
||||
lb_const.SESSION_PERSISTENCE_COOKIE_MAP):
|
||||
persistence.update({
|
||||
'cookieName': getattr(listener.pool.sessionpersistence,
|
||||
'cookie_name',
|
||||
'default_cookie_name'),
|
||||
'cookieMode': lb_const.SESSION_PERSISTENCE_COOKIE_MAP[
|
||||
listener.pool.sessionpersistence.type]})
|
||||
|
||||
edge_app_profile['persistence'] = persistence
|
||||
|
||||
return edge_app_profile
|
||||
|
||||
|
||||
def listener_to_edge_vse(listener, vip_address, default_pool, app_profile_id):
|
||||
return {
|
||||
'name': 'vip_' + listener.id,
|
||||
'description': listener.description,
|
||||
'ipAddress': vip_address,
|
||||
'protocol': listener.protocol,
|
||||
'port': listener.protocol_port,
|
||||
'connectionLimit': max(0, listener.connection_limit),
|
||||
'defaultPoolId': default_pool,
|
||||
'applicationProfileId': app_profile_id}
|
||||
|
||||
|
||||
class EdgeListenerManager(base_mgr.EdgeLoadbalancerBaseManager):
|
||||
@log_helpers.log_method_call
|
||||
def __init__(self, vcns_driver):
|
||||
super(EdgeListenerManager, self).__init__(vcns_driver)
|
||||
|
||||
def _upload_certificate(self, context, edge_id, cert_id, certificate):
|
||||
cert_binding = nsxv_db.get_nsxv_lbaas_certificate_binding(
|
||||
context.session, cert_id, edge_id)
|
||||
if cert_binding:
|
||||
return cert_binding['edge_cert_id']
|
||||
|
||||
request = {
|
||||
'pemEncoding': certificate.get_certificate(),
|
||||
'privateKey': certificate.get_private_key()}
|
||||
passphrase = certificate.get_private_key_passphrase()
|
||||
if passphrase:
|
||||
request['passphrase'] = passphrase
|
||||
cert_obj = self.vcns.upload_edge_certificate(edge_id, request)[1]
|
||||
cert_list = cert_obj.get('certificates', {})
|
||||
if cert_list:
|
||||
edge_cert_id = cert_list[0]['objectId']
|
||||
else:
|
||||
error = _("Failed to upload a certificate to edge %s") % edge_id
|
||||
raise nsxv_exc.NsxPluginException(err_msg=error)
|
||||
nsxv_db.add_nsxv_lbaas_certificate_binding(
|
||||
context.session, cert_id, edge_id, edge_cert_id)
|
||||
return edge_cert_id
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def create(self, context, listener, certificate=None):
|
||||
default_pool = None
|
||||
|
||||
lb_id = listener.loadbalancer_id
|
||||
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb_id)
|
||||
edge_id = lb_binding['edge_id']
|
||||
|
||||
if listener.default_pool and listener.default_pool.id:
|
||||
pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding(
|
||||
context.session, lb_id, listener.id, listener.default_pool.id)
|
||||
if pool_binding:
|
||||
default_pool = pool_binding['edge_pool_id']
|
||||
|
||||
edge_cert_id = None
|
||||
if certificate:
|
||||
try:
|
||||
edge_cert_id = self._upload_certificate(
|
||||
context, edge_id, listener.default_tls_container_id,
|
||||
certificate)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.listener.failed_completion(context,
|
||||
listener)
|
||||
|
||||
app_profile = listener_to_edge_app_profile(listener, edge_cert_id)
|
||||
app_profile_id = None
|
||||
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
h = (self.vcns.create_app_profile(edge_id, app_profile))[0]
|
||||
app_profile_id = lb_common.extract_resource_id(h['location'])
|
||||
except vcns_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.listener.failed_completion(context, listener)
|
||||
LOG.error(_LE('Failed to create app profile on edge: %s'),
|
||||
lb_binding['edge_id'])
|
||||
|
||||
vse = listener_to_edge_vse(listener, lb_binding['vip_address'],
|
||||
default_pool,
|
||||
app_profile_id)
|
||||
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
h = self.vcns.create_vip(edge_id, vse)[0]
|
||||
edge_vse_id = lb_common.extract_resource_id(h['location'])
|
||||
|
||||
nsxv_db.add_nsxv_lbaas_listener_binding(context.session,
|
||||
lb_id,
|
||||
listener.id,
|
||||
app_profile_id,
|
||||
edge_vse_id)
|
||||
self.lbv2_driver.listener.successful_completion(context, listener)
|
||||
|
||||
except vcns_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.listener.failed_completion(context, listener)
|
||||
LOG.error(_LE('Failed to create vip on Edge: %s'), edge_id)
|
||||
self.vcns.delete_app_profile(edge_id, app_profile_id)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def update(self, context, old_listener, new_listener, certificate=None):
|
||||
|
||||
default_pool = None
|
||||
if new_listener.default_pool and new_listener.default_pool.id:
|
||||
pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding(
|
||||
context.session, new_listener.default_pool.id)
|
||||
if pool_binding:
|
||||
default_pool = pool_binding['edge_pool_id']
|
||||
|
||||
lb_id = new_listener.loadbalancer_id
|
||||
listener_binding = nsxv_db.get_nsxv_lbaas_listener_binding(
|
||||
context.session, lb_id, new_listener.id)
|
||||
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb_id)
|
||||
edge_id = lb_binding['edge_id']
|
||||
|
||||
edge_cert_id = None
|
||||
if certificate:
|
||||
if (old_listener.default_tls_container_id !=
|
||||
new_listener.default_tls_container_id):
|
||||
try:
|
||||
edge_cert_id = self._upload_certificate(
|
||||
context, edge_id,
|
||||
new_listener.default_tls_container_id,
|
||||
certificate)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.listener.failed_completion(
|
||||
context, new_listener)
|
||||
else:
|
||||
cert_binding = nsxv_db.get_nsxv_lbaas_certificate_binding(
|
||||
context.session, new_listener.default_tls_container_id,
|
||||
edge_id)
|
||||
edge_cert_id = cert_binding['edge_cert_id']
|
||||
|
||||
app_profile_id = listener_binding['app_profile_id']
|
||||
app_profile = listener_to_edge_app_profile(new_listener, edge_cert_id)
|
||||
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.update_app_profile(
|
||||
edge_id, app_profile_id, app_profile)
|
||||
|
||||
vse = listener_to_edge_vse(new_listener,
|
||||
lb_binding['vip_address'],
|
||||
default_pool,
|
||||
app_profile_id)
|
||||
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.update_vip(edge_id, listener_binding['vse_id'], vse)
|
||||
|
||||
self.lbv2_driver.listener.successful_completion(context,
|
||||
new_listener)
|
||||
except vcns_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.listener.failed_completion(context,
|
||||
new_listener)
|
||||
LOG.error(_LE('Failed to update app profile on edge: %s'),
|
||||
edge_id)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def delete(self, context, listener):
|
||||
lb_id = listener.loadbalancer_id
|
||||
listener_binding = nsxv_db.get_nsxv_lbaas_listener_binding(
|
||||
context.session, lb_id, listener.id)
|
||||
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb_id)
|
||||
|
||||
if lb_binding and listener_binding:
|
||||
edge_id = lb_binding['edge_id']
|
||||
edge_vse_id = listener_binding['vse_id']
|
||||
app_profile_id = listener_binding['app_profile_id']
|
||||
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.delete_vip(edge_id, edge_vse_id)
|
||||
|
||||
except vcns_exc.ResourceNotFound:
|
||||
LOG.error(_LE('vip not found on edge: %s'), edge_id)
|
||||
except vcns_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.listener.failed_completion(context,
|
||||
listener)
|
||||
LOG.error(
|
||||
_LE('Failed to delete vip on edge: %s'), edge_id)
|
||||
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.delete_app_profile(edge_id, app_profile_id)
|
||||
except vcns_exc.ResourceNotFound:
|
||||
LOG.error(_LE('app profile not found on edge: %s'), edge_id)
|
||||
except vcns_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.listener.failed_completion(context,
|
||||
listener)
|
||||
LOG.error(
|
||||
_LE('Failed to delete app profile on Edge: %s'),
|
||||
edge_id)
|
||||
|
||||
nsxv_db.del_nsxv_lbaas_listener_binding(context.session, lb_id,
|
||||
listener.id)
|
||||
|
||||
self.lbv2_driver.listener.successful_completion(
|
||||
context, listener, delete=True)
|
89
vmware_nsx/services/lbaas/nsx_v/v2/loadbalancer_mgr.py
Normal file
89
vmware_nsx/services/lbaas/nsx_v/v2/loadbalancer_mgr.py
Normal file
@ -0,0 +1,89 @@
|
||||
# Copyright 2015 VMware, Inc.
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron.i18n import _LE
|
||||
from oslo_log import helpers as log_helpers
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as nsxv_exc
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import base_mgr
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EdgeLoadBalancerManager(base_mgr.EdgeLoadbalancerBaseManager):
|
||||
@log_helpers.log_method_call
|
||||
def __init__(self, vcns_driver):
|
||||
super(EdgeLoadBalancerManager, self).__init__(vcns_driver)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def create(self, context, lb):
|
||||
try:
|
||||
edge_id = lb_common.get_lbaas_edge_id_for_subnet(
|
||||
context, self.core_plugin, lb.vip_subnet_id)
|
||||
|
||||
lb_common.add_vip_as_secondary_ip(self.vcns, edge_id,
|
||||
lb.vip_address)
|
||||
edge_fw_rule_id = lb_common.add_vip_fw_rule(
|
||||
self.vcns, edge_id, lb.id, lb.vip_address)
|
||||
|
||||
nsxv_db.add_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb.id, edge_id, edge_fw_rule_id,
|
||||
lb.vip_address)
|
||||
self.lbv2_driver.load_balancer.successful_completion(context, lb)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.load_balancer.failed_completion(context, lb)
|
||||
LOG.error(_LE('Failed to create pool %s'), lb.id)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def update(self, context, old_lb, new_lb):
|
||||
self.lbv2_driver.load_balancer.successful_completion(context, new_lb)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def delete(self, context, lb):
|
||||
try:
|
||||
binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb.id)
|
||||
lb_common.del_vip_fw_rule(self.vcns, binding['edge_id'],
|
||||
binding['edge_fw_rule_id'])
|
||||
lb_common.del_vip_as_secondary_ip(self.vcns, binding['edge_id'],
|
||||
lb.vip_address)
|
||||
nsxv_db.del_nsxv_lbaas_loadbalancer_binding(context.session, lb.id)
|
||||
self.lbv2_driver.load_balancer.successful_completion(
|
||||
context, lb, delete=True)
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.load_balancer.failed_completion(context, lb)
|
||||
LOG.error(_LE('Failed to delete pool %s'), lb.id)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def refresh(self, context, lb):
|
||||
# TODO(kobis): implememnt
|
||||
pass
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def stats(self, context, lb):
|
||||
# TODO(kobis): implement
|
||||
stats = {'bytes_in': 0,
|
||||
'bytes_out': 0,
|
||||
'active_connections': 0,
|
||||
'total_connections': 0}
|
||||
|
||||
return stats
|
173
vmware_nsx/services/lbaas/nsx_v/v2/member_mgr.py
Normal file
173
vmware_nsx/services/lbaas/nsx_v/v2/member_mgr.py
Normal file
@ -0,0 +1,173 @@
|
||||
# Copyright 2015 VMware, Inc.
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron.i18n import _LE
|
||||
from oslo_log import helpers as log_helpers
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
||||
from vmware_nsx.common import locking
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as nsxv_exc
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import base_mgr
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EdgeMemberManager(base_mgr.EdgeLoadbalancerBaseManager):
|
||||
@log_helpers.log_method_call
|
||||
def __init__(self, vcns_driver):
|
||||
super(EdgeMemberManager, self).__init__(vcns_driver)
|
||||
self._fw_section_id = None
|
||||
|
||||
def _get_pool_member_ips(self, pool, operation, address):
|
||||
member_ips = [member.address for member in pool.members]
|
||||
if operation == 'add' and address not in member_ips:
|
||||
member_ips.append(address)
|
||||
elif operation == 'del' and address in member_ips:
|
||||
member_ips.remove(address)
|
||||
return member_ips
|
||||
|
||||
def _get_lbaas_fw_section_id(self):
|
||||
if not self._fw_section_id:
|
||||
self._fw_section_id = lb_common.get_lbaas_fw_section_id(self.vcns)
|
||||
return self._fw_section_id
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def create(self, context, member):
|
||||
listener = member.pool.listener
|
||||
lb_id = listener.loadbalancer_id
|
||||
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb_id)
|
||||
pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding(
|
||||
context.session, lb_id, listener.id, member.pool_id)
|
||||
|
||||
edge_id = lb_binding['edge_id']
|
||||
edge_pool_id = pool_binding['edge_pool_id']
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
edge_pool = self.vcns.get_pool(edge_id, edge_pool_id)[1]
|
||||
edge_member = {
|
||||
'ipAddress': member.address,
|
||||
'weight': member.weight,
|
||||
'port': member.protocol_port,
|
||||
'monitorPort': member.protocol_port,
|
||||
'name': lb_common.get_member_id(member.id),
|
||||
'condition':
|
||||
'enabled' if member.admin_state_up else 'disabled'}
|
||||
|
||||
if edge_pool.get('member'):
|
||||
edge_pool['member'].append(edge_member)
|
||||
else:
|
||||
edge_pool['member'] = [edge_member]
|
||||
|
||||
try:
|
||||
self.vcns.update_pool(edge_id, edge_pool_id, edge_pool)
|
||||
|
||||
member_ips = self._get_pool_member_ips(member.pool, 'add',
|
||||
member.address)
|
||||
lb_common.update_pool_fw_rule(self.vcns, member.pool_id,
|
||||
edge_id,
|
||||
self._get_lbaas_fw_section_id(),
|
||||
member_ips)
|
||||
|
||||
self.lbv2_driver.member.successful_completion(context, member)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.member.failed_completion(context, member)
|
||||
LOG.error(_LE('Failed to create member on edge: %s'),
|
||||
edge_id)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def update(self, context, old_member, new_member):
|
||||
listener = new_member.pool.listener
|
||||
lb_id = listener.loadbalancer_id
|
||||
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb_id)
|
||||
pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding(context.session,
|
||||
lb_id, listener.id,
|
||||
new_member.pool_id)
|
||||
|
||||
edge_id = lb_binding['edge_id']
|
||||
edge_pool_id = pool_binding['edge_pool_id']
|
||||
|
||||
edge_member = {
|
||||
'ipAddress': new_member.address,
|
||||
'weight': new_member.weight,
|
||||
'port': new_member.protocol_port,
|
||||
'monitorPort': new_member.protocol_port,
|
||||
'name': lb_common.get_member_id(new_member.id),
|
||||
'condition':
|
||||
'enabled' if new_member.admin_state_up else 'disabled'}
|
||||
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
edge_pool = self.vcns.get_pool(edge_id, edge_pool_id)[1]
|
||||
|
||||
if edge_pool.get('member'):
|
||||
for i, m in enumerate(edge_pool['member']):
|
||||
if m['name'] == lb_common.get_member_id(new_member.id):
|
||||
edge_pool['member'][i] = edge_member
|
||||
break
|
||||
|
||||
try:
|
||||
self.vcns.update_pool(edge_id, edge_pool_id, edge_pool)
|
||||
|
||||
self.lbv2_driver.member.successful_completion(
|
||||
context, new_member)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.member.failed_completion(
|
||||
context, new_member)
|
||||
LOG.error(_LE('Failed to update member on edge: %s'),
|
||||
edge_id)
|
||||
else:
|
||||
LOG.error(_LE('Pool %(pool_id)s on Edge %(edge_id)s has no '
|
||||
'members to update')
|
||||
% {'pool_id': new_member.pool.id,
|
||||
'edge_id': edge_id})
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def delete(self, context, member):
|
||||
listener = member.pool.listener
|
||||
lb_id = listener.loadbalancer_id
|
||||
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb_id)
|
||||
pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding(
|
||||
context.session, lb_id, listener.id, member.pool_id)
|
||||
|
||||
edge_id = lb_binding['edge_id']
|
||||
edge_pool_id = pool_binding['edge_pool_id']
|
||||
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
edge_pool = self.vcns.get_pool(edge_id, edge_pool_id)[1]
|
||||
|
||||
for i, m in enumerate(edge_pool['member']):
|
||||
if m['name'] == lb_common.get_member_id(member.id):
|
||||
edge_pool['member'].pop(i)
|
||||
break
|
||||
|
||||
try:
|
||||
self.vcns.update_pool(edge_id, edge_pool_id, edge_pool)
|
||||
|
||||
self.lbv2_driver.member.successful_completion(
|
||||
context, member, delete=True)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.member.failed_completion(context, member)
|
||||
LOG.error(_LE('Failed to delete member on edge: %s'),
|
||||
edge_id)
|
143
vmware_nsx/services/lbaas/nsx_v/v2/pool_mgr.py
Normal file
143
vmware_nsx/services/lbaas/nsx_v/v2/pool_mgr.py
Normal file
@ -0,0 +1,143 @@
|
||||
# Copyright 2015 VMware, Inc.
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron.i18n import _LE
|
||||
from oslo_log import helpers as log_helpers
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
||||
from vmware_nsx.common import locking
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as nsxv_exc
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_const as lb_const
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import base_mgr
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import listener_mgr
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EdgePoolManager(base_mgr.EdgeLoadbalancerBaseManager):
|
||||
@log_helpers.log_method_call
|
||||
def __init__(self, vcns_driver):
|
||||
super(EdgePoolManager, self).__init__(vcns_driver)
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def create(self, context, pool):
|
||||
|
||||
edge_pool = {
|
||||
'name': 'pool_' + pool.id,
|
||||
'description': getattr(pool, 'description', getattr(pool, 'name')),
|
||||
'algorithm': lb_const.BALANCE_MAP.get(pool.lb_algorithm,
|
||||
'round-robin'),
|
||||
'transparent': False
|
||||
}
|
||||
|
||||
listener = pool.listener
|
||||
lb_id = listener.loadbalancer_id
|
||||
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb_id)
|
||||
listener_binding = nsxv_db.get_nsxv_lbaas_listener_binding(
|
||||
context.session, lb_id, listener.id)
|
||||
|
||||
edge_id = lb_binding['edge_id']
|
||||
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
h = self.vcns.create_pool(edge_id, edge_pool)[0]
|
||||
edge_pool_id = lb_common.extract_resource_id(h['location'])
|
||||
nsxv_db.add_nsxv_lbaas_pool_binding(context.session, lb_id,
|
||||
listener.id,
|
||||
pool.id,
|
||||
edge_pool_id)
|
||||
|
||||
# Associate listener with pool
|
||||
vse = listener_mgr.listener_to_edge_vse(
|
||||
listener,
|
||||
lb_binding['vip_address'],
|
||||
edge_pool_id,
|
||||
listener_binding['app_profile_id'])
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.update_vip(edge_id, listener_binding['vse_id'], vse)
|
||||
|
||||
self.lbv2_driver.pool.successful_completion(context, pool)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.pool.failed_completion(context, pool)
|
||||
LOG.error(_LE('Failed to create pool %s'), pool['id'])
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def update(self, context, old_pool, new_pool):
|
||||
edge_pool = {
|
||||
'name': 'pool_' + new_pool.id,
|
||||
'description': getattr(new_pool, 'description',
|
||||
getattr(new_pool, 'name')),
|
||||
'algorithm': lb_const.BALANCE_MAP.get(
|
||||
new_pool.lb_algorithm, 'round-robin'),
|
||||
'transparent': False
|
||||
}
|
||||
|
||||
listener = new_pool.listener
|
||||
lb_id = listener.loadbalancer_id
|
||||
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb_id)
|
||||
pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding(
|
||||
context.session, lb_id, listener.id, new_pool.id)
|
||||
|
||||
edge_id = lb_binding['edge_id']
|
||||
edge_pool_id = pool_binding['edge_pool_id']
|
||||
|
||||
try:
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.update_pool(edge_id, edge_pool_id, edge_pool)
|
||||
|
||||
self.lbv2_driver.pool.successful_completion(context, new_pool)
|
||||
|
||||
except nsxv_exc.VcnsApiException:
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.lbv2_driver.pool.failed_completion(context, new_pool)
|
||||
LOG.error(_LE('Failed to update pool %s'), new_pool['id'])
|
||||
|
||||
@log_helpers.log_method_call
|
||||
def delete(self, context, pool):
|
||||
listener = pool.listener
|
||||
lb_id = listener.loadbalancer_id
|
||||
lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
|
||||
context.session, lb_id)
|
||||
pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding(
|
||||
context.session, lb_id, listener.id, pool.id)
|
||||
listener_binding = nsxv_db.get_nsxv_lbaas_listener_binding(
|
||||
context.session, lb_id, listener.id)
|
||||
|
||||
edge_id = lb_binding['edge_id']
|
||||
edge_pool_id = pool_binding['edge_pool_id']
|
||||
|
||||
try:
|
||||
vse = listener_mgr.listener_to_edge_vse(
|
||||
listener,
|
||||
lb_binding['vip_address'],
|
||||
None,
|
||||
listener_binding['app_profile_id'])
|
||||
with locking.LockManager.get_lock(edge_id, external=True):
|
||||
self.vcns.update_vip(edge_id, listener_binding['vse_id'], vse)
|
||||
self.vcns.delete_pool(edge_id, edge_pool_id)
|
||||
self.lbv2_driver.pool.successful_completion(
|
||||
context, pool, delete=True)
|
||||
nsxv_db.del_nsxv_lbaas_pool_binding(
|
||||
context.session, lb_id, listener.id, pool.id)
|
||||
except nsxv_exc.VcnsApiException:
|
||||
self.lbv2_driver.pool.failed_completion(context, pool)
|
||||
LOG.error(_LE('Failed to delete pool %s'), pool['id'])
|
@ -19,6 +19,7 @@ from neutron import context
|
||||
from neutron.tests import base
|
||||
|
||||
from vmware_nsx.plugins.nsx_v.vshield import vcns_driver
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
|
||||
|
||||
EDGE_PROVIDER = ('LOADBALANCER:vmwareedge:neutron.services.'
|
||||
'loadbalancer.drivers.vmware.edge_driver.'
|
||||
@ -62,51 +63,6 @@ def lbaas_pool_maker(**kwargs):
|
||||
return lbaas_dict
|
||||
|
||||
|
||||
def if_list_maker(ip_list):
|
||||
if_list = {
|
||||
'vnics': [
|
||||
{'index': 0, 'name': 'external', 'addressGroups': {
|
||||
'addressGroups': [
|
||||
{'subnetMask': '255.255.255.0',
|
||||
'primaryAddress': '172.24.4.2',
|
||||
'subnetPrefixLength': '24'}]},
|
||||
'portgroupName': 'VM Network', 'label': 'vNic_0',
|
||||
'type': 'uplink', 'portgroupId': 'network-13'},
|
||||
{'index': 1, 'name': 'internal1', 'addressGroups': {
|
||||
'addressGroups': [
|
||||
{'subnetPrefixLength': '24',
|
||||
'secondaryAddresses': {
|
||||
'ipAddress': ip_list,
|
||||
'type': 'secondary_addresses'},
|
||||
'primaryAddress': '10.0.0.1',
|
||||
'subnetMask': '255.255.255.0'}]},
|
||||
'portgroupName': 'pg1234',
|
||||
'label': 'vNic_1', 'type': 'internal',
|
||||
'portgroupId': 'virtualwire-31'},
|
||||
{'index': 2, 'name': 'vnic2',
|
||||
'addressGroups': {'addressGroups': []},
|
||||
'label': 'vNic_2', 'type': 'internal'},
|
||||
{'index': 3, 'name': 'vnic3',
|
||||
'addressGroups': {'addressGroups': []},
|
||||
'label': 'vNic_3', 'type': 'internal'}]}
|
||||
return if_list
|
||||
|
||||
|
||||
def if_maker(ip_list):
|
||||
intf = {
|
||||
'index': 1, 'name': 'internal1', 'addressGroups': {
|
||||
'addressGroups': [
|
||||
{'subnetPrefixLength': '24',
|
||||
'secondaryAddresses': {
|
||||
'ipAddress': ip_list,
|
||||
'type': 'secondary_addresses'},
|
||||
'primaryAddress': '10.0.0.1',
|
||||
'subnetMask': '255.255.255.0'}]},
|
||||
'portgroupName': 'pg1234', 'label': 'vNic_1',
|
||||
'type': 'internal', 'portgroupId': 'virtualwire-31'}
|
||||
return intf
|
||||
|
||||
|
||||
def lbaas_vip_maker(**kwargs):
|
||||
lbaas_vip = {
|
||||
'status': 'PENDING_CREATE',
|
||||
@ -160,22 +116,37 @@ def lbaas_hmon_maker(**kwargs):
|
||||
return hmon
|
||||
|
||||
|
||||
def firewall_section_maker(ip_list_str):
|
||||
return (
|
||||
'<section id="1132" name="LBaaS FW Rules"><rule><name>' + POOL_ID +
|
||||
'</name><action>allow</action><sources excluded="false"><source>'
|
||||
'<type>Ipv4Address</type><value>10.0.0.1,11.0.0.1</value></source>'
|
||||
'</sources><destinations excluded="false"><destination>'
|
||||
'<type>Ipv4Address</type><value>' + ip_list_str +
|
||||
'</value></destination></destinations></rule></section>')
|
||||
|
||||
|
||||
class TestEdgeLbDriver(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestEdgeLbDriver, self).setUp()
|
||||
self.context = context.get_admin_context()
|
||||
self.edge_driver = vcns_driver.VcnsDriver(self)
|
||||
self.edge_driver._lb_driver_prop = mock.Mock()
|
||||
callbacks = mock.Mock()
|
||||
callbacks.plugin = mock.Mock()
|
||||
self.edge_driver = vcns_driver.VcnsDriver(callbacks)
|
||||
self.edge_driver._lbv1_driver_prop = mock.Mock()
|
||||
self._temp_get_lbaas_edge_id_for_subnet = (
|
||||
lb_common.get_lbaas_edge_id_for_subnet)
|
||||
self._temp_update_pool_fw_rule = lb_common.update_pool_fw_rule
|
||||
self._temp_add_vip_as_secondary_ip = lb_common.add_vip_as_secondary_ip
|
||||
self._temp_add_vip_fw_rule = lb_common.add_vip_fw_rule
|
||||
self._temp_del_vip_as_secondary_ip = lb_common.del_vip_as_secondary_ip
|
||||
self._temp_del_vip_fw_rule = lb_common.del_vip_fw_rule
|
||||
lb_common.get_lbaas_edge_id_for_subnet = mock.Mock()
|
||||
lb_common.update_pool_fw_rule = mock.Mock()
|
||||
lb_common.add_vip_as_secondary_ip = mock.Mock()
|
||||
lb_common.add_vip_fw_rule = mock.Mock()
|
||||
lb_common.del_vip_as_secondary_ip = mock.Mock()
|
||||
lb_common.del_vip_fw_rule = mock.Mock()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestEdgeLbDriver, self).tearDown()
|
||||
lb_common.get_lbaas_edge_id_for_subnet = (
|
||||
self._temp_get_lbaas_edge_id_for_subnet)
|
||||
lb_common.update_pool_fw_rule = self._temp_update_pool_fw_rule
|
||||
lb_common.add_vip_as_secondary_ip = self._temp_add_vip_as_secondary_ip
|
||||
lb_common.add_vip_fw_rule = self._temp_add_vip_fw_rule
|
||||
lb_common.del_vip_as_secondary_ip = self._temp_del_vip_as_secondary_ip
|
||||
lb_common.del_vip_fw_rule = self._temp_del_vip_fw_rule
|
||||
|
||||
def _mock_edge_driver(self, attr):
|
||||
return mock.patch.object(self.edge_driver, attr)
|
||||
@ -183,8 +154,8 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
def _mock_edge_driver_vcns(self, attr):
|
||||
return mock.patch.object(self.edge_driver.vcns, attr)
|
||||
|
||||
def _mock_edge_lb_driver(self, attr):
|
||||
return mock.patch.object(self.edge_driver._lb_driver, attr)
|
||||
def _mock_edge_lbv1_driver(self, attr):
|
||||
return mock.patch.object(self.edge_driver.lbv1_driver, attr)
|
||||
|
||||
def test_create_pool(self):
|
||||
lbaas_pool = lbaas_pool_maker()
|
||||
@ -193,12 +164,11 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
'transparent': False, 'name': 'pool_' + POOL_ID,
|
||||
'algorithm': 'round-robin', 'description': ''}
|
||||
|
||||
with self._mock_edge_driver('_get_lb_edge_id') as _get_lb_edge_id,\
|
||||
self._mock_edge_lb_driver(
|
||||
with self._mock_edge_lbv1_driver(
|
||||
'create_pool_successful') as create_pool_successful, \
|
||||
self._mock_edge_driver_vcns('create_pool') as create_pool:
|
||||
|
||||
_get_lb_edge_id.return_value = EDGE_ID
|
||||
lb_common.get_lbaas_edge_id_for_subnet.return_value = EDGE_ID
|
||||
create_pool.return_value = ({'location': 'x/' + EDGE_POOL_ID},
|
||||
None)
|
||||
|
||||
@ -217,7 +187,7 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
'algorithm': 'leastconn', 'description': ''}
|
||||
|
||||
pool_mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID}
|
||||
with self._mock_edge_lb_driver('pool_successful') as pool_successful,\
|
||||
with self._mock_edge_lbv1_driver('pool_successful') as pool_successful,\
|
||||
self._mock_edge_driver_vcns('update_pool') as update_pool:
|
||||
|
||||
self.edge_driver.update_pool(
|
||||
@ -231,38 +201,13 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
pool_mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID}
|
||||
|
||||
with self._mock_edge_driver_vcns('delete_pool'),\
|
||||
self._mock_edge_lb_driver(
|
||||
self._mock_edge_lbv1_driver(
|
||||
'delete_pool_successful') as mock_delete_successful:
|
||||
|
||||
self.edge_driver.delete_pool(
|
||||
self.context, lbaas_pool, pool_mapping)
|
||||
mock_delete_successful.assert_called_with(self.context, lbaas_pool)
|
||||
|
||||
def test__add_vip_as_secondary_ip(self):
|
||||
update_if = if_maker(['10.0.0.6', '10.0.0.8'])
|
||||
|
||||
with self._mock_edge_driver_vcns('get_interfaces') as mock_get_if,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_interface') as mock_update_if:
|
||||
|
||||
mock_get_if.return_value = (None, if_list_maker(['10.0.0.6']))
|
||||
|
||||
self.edge_driver._add_vip_as_secondary_ip(EDGE_ID, '10.0.0.8')
|
||||
mock_update_if.assert_called_with(EDGE_ID, update_if)
|
||||
|
||||
def test__del_vip_as_secondary_ip(self):
|
||||
update_if = if_maker(['10.0.0.6'])
|
||||
|
||||
with self._mock_edge_driver_vcns('get_interfaces') as mock_get_if,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_interface') as mock_update_if:
|
||||
|
||||
mock_get_if.return_value = (None, if_list_maker(['10.0.0.6',
|
||||
'10.0.0.8']))
|
||||
|
||||
self.edge_driver._del_vip_as_secondary_ip(EDGE_ID, '10.0.0.8')
|
||||
mock_update_if.assert_called_with(EDGE_ID, update_if)
|
||||
|
||||
def test_create_vip(self):
|
||||
lbaas_vip = lbaas_vip_maker()
|
||||
edge_app_prof = {
|
||||
@ -277,24 +222,22 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
|
||||
pool_mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID}
|
||||
|
||||
with self._mock_edge_driver('_add_vip_as_secondary_ip'),\
|
||||
self._mock_edge_driver_vcns(
|
||||
with self._mock_edge_driver_vcns(
|
||||
'create_app_profile') as mock_create_app_profile,\
|
||||
self._mock_edge_driver_vcns('create_vip') as mock_create_vip,\
|
||||
self._mock_edge_driver(
|
||||
'_add_vip_fw_rule') as mock_add_fw_rule,\
|
||||
self._mock_edge_lb_driver(
|
||||
self._mock_edge_lbv1_driver(
|
||||
'create_vip_successful') as mock_vip_successful:
|
||||
|
||||
mock_create_app_profile.return_value = (
|
||||
{'location': 'x/' + APP_PROFILE_ID}, None)
|
||||
mock_create_vip.return_value = (
|
||||
{'location': 'x/' + EDGE_VSE_ID}, None)
|
||||
mock_add_fw_rule.return_value = EDGE_FW_RULE_ID
|
||||
lb_common.add_vip_fw_rule.return_value = EDGE_FW_RULE_ID
|
||||
|
||||
self.edge_driver.create_vip(self.context, lbaas_vip, pool_mapping)
|
||||
mock_create_app_profile.assert_called_with(EDGE_ID, edge_app_prof)
|
||||
mock_add_fw_rule.assert_called_with(EDGE_ID, VIP_ID, '10.0.0.8')
|
||||
lb_common.add_vip_fw_rule.assert_called_with(
|
||||
self.edge_driver.vcns, EDGE_ID, VIP_ID, '10.0.0.8')
|
||||
mock_create_vip.assert_called_with(EDGE_ID, edge_vip)
|
||||
mock_vip_successful.assert_called_with(
|
||||
self.context, lbaas_vip, EDGE_ID, APP_PROFILE_ID, EDGE_VSE_ID,
|
||||
@ -322,7 +265,7 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
with self._mock_edge_driver_vcns('update_vip') as mock_upd_vip,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_app_profile') as mock_upd_app_prof,\
|
||||
self._mock_edge_lb_driver(
|
||||
self._mock_edge_lbv1_driver(
|
||||
'vip_successful') as mock_vip_successful:
|
||||
|
||||
self.edge_driver.update_vip(self.context, vip_from, vip_to,
|
||||
@ -339,19 +282,17 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
'edge_app_profile_id': APP_PROFILE_ID,
|
||||
'edge_fw_rule_id': EDGE_FW_RULE_ID}
|
||||
|
||||
with self._mock_edge_driver('_del_vip_as_secondary_ip'),\
|
||||
self._mock_edge_driver_vcns(
|
||||
with self._mock_edge_driver_vcns(
|
||||
'delete_app_profile') as mock_del_app_profile,\
|
||||
self._mock_edge_driver_vcns('delete_vip') as mock_del_vip,\
|
||||
self._mock_edge_driver(
|
||||
'_del_vip_fw_rule') as mock_del_fw_rule,\
|
||||
self._mock_edge_lb_driver(
|
||||
self._mock_edge_lbv1_driver(
|
||||
'delete_vip_successful') as mock_del_successful:
|
||||
|
||||
self.edge_driver.delete_vip(self.context, lbaas_vip, vip_mapping)
|
||||
mock_del_app_profile.assert_called_with(EDGE_ID, APP_PROFILE_ID)
|
||||
mock_del_vip.assert_called_with(EDGE_ID, EDGE_VSE_ID)
|
||||
mock_del_fw_rule.assert_called_with(EDGE_ID, EDGE_FW_RULE_ID)
|
||||
lb_common.del_vip_fw_rule.assert_called_with(
|
||||
self.edge_driver.vcns, EDGE_ID, EDGE_FW_RULE_ID)
|
||||
mock_del_successful.assert_called_with(self.context, lbaas_vip)
|
||||
|
||||
def test_create_member(self):
|
||||
@ -367,12 +308,17 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
pool_mapping = {'edge_id': EDGE_ID, 'edge_pool_id': EDGE_POOL_ID}
|
||||
|
||||
with self._mock_edge_driver_vcns('update_pool'),\
|
||||
self._mock_edge_driver('_update_pool_fw_rule'),\
|
||||
self._mock_edge_driver_vcns('get_pool') as mock_get_pool,\
|
||||
self._mock_edge_lb_driver(
|
||||
self._mock_edge_driver(
|
||||
'_get_pool_member_ips') as mock_get_ips, \
|
||||
self._mock_edge_driver(
|
||||
'_get_lbaas_fw_section_id') as mock_fw_sect, \
|
||||
self._mock_edge_lbv1_driver(
|
||||
'member_successful') as mock_member_successful:
|
||||
|
||||
mock_get_pool.return_value = (None, edge_pool)
|
||||
mock_get_ips.return_value = ['10.0.0.4']
|
||||
mock_fw_sect.return_value = 10010
|
||||
self.edge_driver.create_member(self.context, lbaas_member,
|
||||
pool_mapping)
|
||||
edge_pool['member'].append(edge_member)
|
||||
@ -395,7 +341,7 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
with self._mock_edge_driver_vcns('get_pool') as mock_get_pool,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_pool') as mock_update_pool,\
|
||||
self._mock_edge_lb_driver(
|
||||
self._mock_edge_lbv1_driver(
|
||||
'member_successful') as mock_member_successful:
|
||||
|
||||
mock_get_pool.return_value = (None, edge_pool)
|
||||
@ -426,93 +372,20 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
|
||||
with self._mock_edge_driver('_get_lb_plugin') as mock_get_lb_plugin,\
|
||||
self._mock_edge_driver_vcns('get_pool') as mock_get_pool,\
|
||||
self._mock_edge_driver(
|
||||
'_get_lbaas_fw_section_id') as mock_fw_sect, \
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_pool') as mock_update_pool,\
|
||||
self._mock_edge_driver('_update_pool_fw_rule'):
|
||||
'update_pool') as mock_update_pool:
|
||||
|
||||
mock_get_pool.return_value = (None, edge_pool)
|
||||
self.edge_driver.delete_member(self.context, lbaas_member,
|
||||
pool_mapping)
|
||||
mock_fw_sect.return_value = 10010
|
||||
mock_get_lb_plugin.return_value = mock_lb_plugin
|
||||
edge_pool['member'] = []
|
||||
mock_update_pool.assert_called_with(EDGE_ID, EDGE_POOL_ID,
|
||||
edge_pool)
|
||||
|
||||
def test__update_pool_fw_rule_add(self):
|
||||
edge_fw_section = (
|
||||
'<section id="1132" name="LBaaS FW Rules"><rule><name>' + POOL_ID +
|
||||
'</name><action>allow</action><sources excluded="false"><source>'
|
||||
'<type>Ipv4Address</type><value>10.0.0.1,11.0.0.1</value></source>'
|
||||
'</sources><destinations excluded="false"><destination>'
|
||||
'<type>Ipv4Address</type><value>10.0.0.10</value></destination>'
|
||||
'</destinations></rule></section>')
|
||||
edge_fw_updated_section = (
|
||||
'<section id="1132" name="LBaaS FW Rules"><rule><name>' + POOL_ID +
|
||||
'</name><action>allow</action><sources excluded="false"><source>'
|
||||
'<type>Ipv4Address</type><value>10.0.0.1,11.0.0.1</value></source>'
|
||||
'</sources><destinations excluded="false"><destination>'
|
||||
'<type>Ipv4Address</type><value>10.0.0.10,11.0.0.10</value>'
|
||||
'</destination></destinations></rule></section>')
|
||||
|
||||
mock_lb_plugin = mock.Mock()
|
||||
|
||||
with self._mock_edge_driver('_get_lb_plugin') as mock_get_lb_plugin,\
|
||||
self._mock_edge_driver('_get_edge_ips') as mock_get_edge_ips,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'get_section') as mock_get_section,\
|
||||
self._mock_edge_driver(
|
||||
'_get_lbaas_fw_section_id') as mock_get_section_id,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_section') as mock_update_section:
|
||||
|
||||
mock_get_section_id.return_value = '1111'
|
||||
mock_get_edge_ips.return_value = ['10.0.0.1', '11.0.0.1']
|
||||
mock_get_lb_plugin.return_value = mock_lb_plugin
|
||||
mock_lb_plugin.get_members.return_value = [{'address':
|
||||
'10.0.0.10'}]
|
||||
mock_get_section.return_value = (None, edge_fw_section)
|
||||
self.edge_driver._update_pool_fw_rule(
|
||||
self.context, POOL_ID, EDGE_ID, 'add', '11.0.0.10')
|
||||
mock_update_section.assert_called_with(
|
||||
'/api/4.0/firewall/globalroot-0/config/layer3sections/1111',
|
||||
edge_fw_updated_section, None)
|
||||
|
||||
def test__update_pool_fw_rule_del(self):
|
||||
edge_fw_section = firewall_section_maker('10.0.0.10,11.0.0.10')
|
||||
edge_fw_updated_section = firewall_section_maker('10.0.0.10')
|
||||
|
||||
mock_lb_plugin = mock.Mock()
|
||||
|
||||
with self._mock_edge_driver('_get_edge_ips') as mock_get_edge_ips,\
|
||||
self._mock_edge_driver(
|
||||
'_get_lb_plugin') as mock_get_lb_plugin,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'get_section') as mock_get_section,\
|
||||
self._mock_edge_driver(
|
||||
'_get_lbaas_fw_section_id') as mock_get_section_id,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_section') as mock_update_section:
|
||||
|
||||
mock_get_section_id.return_value = '1111'
|
||||
mock_get_edge_ips.return_value = ['10.0.0.1', '11.0.0.1']
|
||||
mock_get_lb_plugin.return_value = mock_lb_plugin
|
||||
mock_lb_plugin.get_members.return_value = [
|
||||
{'address': '10.0.0.10'}, {'address': '11.0.0.10'}]
|
||||
mock_get_section.return_value = (None, edge_fw_section)
|
||||
self.edge_driver._update_pool_fw_rule(
|
||||
self.context, POOL_ID, EDGE_ID, 'del', '11.0.0.10')
|
||||
mock_update_section.assert_called_with(
|
||||
'/api/4.0/firewall/globalroot-0/config/layer3sections/1111',
|
||||
edge_fw_updated_section, None)
|
||||
|
||||
def test__get_edge_ips(self):
|
||||
get_if_list = if_list_maker(['10.0.0.6'])
|
||||
|
||||
with mock.patch.object(self.edge_driver.vcns, 'get_interfaces',
|
||||
return_value=(None, get_if_list)):
|
||||
ip_list = self.edge_driver._get_edge_ips(EDGE_ID)
|
||||
self.assertEqual(['172.24.4.2', '10.0.0.1'], ip_list)
|
||||
|
||||
def test_create_pool_health_monitor(self):
|
||||
hmon = lbaas_hmon_maker()
|
||||
edge_hm = {'maxRetries': 5, 'interval': 5, 'type': 'icmp',
|
||||
@ -528,7 +401,7 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
self._mock_edge_driver_vcns('get_pool') as mock_get_pool,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'create_health_monitor') as mock_create_mon,\
|
||||
self._mock_edge_lb_driver(
|
||||
self._mock_edge_lbv1_driver(
|
||||
'create_pool_health_monitor_successful') as (
|
||||
mock_create_successful):
|
||||
|
||||
@ -555,7 +428,7 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
|
||||
with self._mock_edge_driver_vcns(
|
||||
'update_health_monitor') as mock_update_mon,\
|
||||
self._mock_edge_lb_driver(
|
||||
self._mock_edge_lbv1_driver(
|
||||
'pool_health_monitor_successful') as mock_hmon_successful:
|
||||
|
||||
self.edge_driver.update_pool_health_monitor(
|
||||
@ -579,7 +452,7 @@ class TestEdgeLbDriver(base.BaseTestCase):
|
||||
self._mock_edge_driver_vcns('get_pool') as mock_get_pool,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'delete_health_monitor') as mock_del_mon,\
|
||||
self._mock_edge_lb_driver(
|
||||
self._mock_edge_lbv1_driver(
|
||||
'delete_pool_health_monitor_successful') as (
|
||||
mock_del_successful):
|
||||
|
||||
|
611
vmware_nsx/tests/unit/nsx_v/test_edge_loadbalancer_driver_v2.py
Normal file
611
vmware_nsx/tests/unit/nsx_v/test_edge_loadbalancer_driver_v2.py
Normal file
@ -0,0 +1,611 @@
|
||||
# Copyright 2015 VMware, Inc.
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron import context
|
||||
|
||||
import mock
|
||||
from neutron.tests import base
|
||||
from neutron_lbaas.services.loadbalancer import data_models as lb_models
|
||||
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.plugins.nsx_v.vshield import vcns_driver
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
|
||||
from vmware_nsx.services.lbaas.nsx_v.v2 import base_mgr
|
||||
|
||||
|
||||
LB_VIP = '10.0.0.10'
|
||||
LB_EDGE_ID = 'edge-x'
|
||||
LB_ID = 'xxx-xxx'
|
||||
LB_TENANT_ID = 'yyy-yyy'
|
||||
LB_VIP_FWR_ID = 'fwr-1'
|
||||
LB_BINDING = {'loadbalancer_id': LB_ID,
|
||||
'edge_id': LB_EDGE_ID,
|
||||
'edge_fw_rule_id': LB_VIP_FWR_ID,
|
||||
'vip_address': LB_VIP}
|
||||
LISTENER_ID = 'xxx-111'
|
||||
EDGE_APP_PROFILE_ID = 'appp-x'
|
||||
EDGE_APP_PROF_DEF = {'sslPassthrough': False, 'insertXForwardedFor': False,
|
||||
'serverSslEnabled': False, 'name': LISTENER_ID,
|
||||
'template': 'HTTP'}
|
||||
EDGE_VIP_ID = 'vip-aaa'
|
||||
EDGE_VIP_DEF = {'protocol': 'HTTP', 'name': 'vip_' + LISTENER_ID,
|
||||
'connectionLimit': 0, 'defaultPoolId': None,
|
||||
'ipAddress': LB_VIP, 'port': 80,
|
||||
'applicationProfileId': EDGE_APP_PROFILE_ID, 'description': ''}
|
||||
LISTENER_BINDING = {'loadbalancer_id': LB_ID,
|
||||
'listener_id': LISTENER_ID,
|
||||
'app_profile_id': EDGE_APP_PROFILE_ID,
|
||||
'vse_id': EDGE_VIP_ID}
|
||||
POOL_ID = 'ppp-qqq'
|
||||
EDGE_POOL_ID = 'pool-xx'
|
||||
EDGE_POOL_DEF = {'transparent': False, 'name': 'pool_' + POOL_ID,
|
||||
'algorithm': 'round-robin', 'description': ''}
|
||||
POOL_BINDING = {'loadbalancer_id': LB_ID,
|
||||
'listener_id': LISTENER_ID,
|
||||
'pool_id': POOL_ID,
|
||||
'edge_pool_id': EDGE_POOL_ID}
|
||||
MEMBER_ID = 'mmm-mmm'
|
||||
MEMBER_ADDRESS = '10.0.0.200'
|
||||
EDGE_MEMBER_DEF = {'monitorPort': 80, 'name': 'member-' + MEMBER_ID,
|
||||
'weight': 1, 'ipAddress': MEMBER_ADDRESS, 'port': 80,
|
||||
'condition': 'disabled'}
|
||||
POOL_FW_SECT = '10001'
|
||||
HM_ID = 'hhh-mmm'
|
||||
EDGE_HM_ID = 'hm-xx'
|
||||
EDGE_HM_DEF = {'maxRetries': 1, 'interval': 3, 'type': 'icmp', 'name': HM_ID,
|
||||
'timeout': 3}
|
||||
|
||||
HM_BINDING = {'loadbalancer_id': LB_ID,
|
||||
'listener_id': LISTENER_ID,
|
||||
'pool_id': POOL_ID,
|
||||
'hm_id': HM_ID,
|
||||
'edge_id': LB_EDGE_ID,
|
||||
'edge_mon_id': EDGE_HM_ID}
|
||||
|
||||
|
||||
class BaseTestEdgeLbaasV2(base.BaseTestCase):
|
||||
def _tested_entity(self):
|
||||
return None
|
||||
|
||||
def setUp(self):
|
||||
super(BaseTestEdgeLbaasV2, self).setUp()
|
||||
|
||||
self.context = context.get_admin_context()
|
||||
callbacks = mock.Mock()
|
||||
callbacks.plugin = mock.Mock()
|
||||
self.edge_driver = vcns_driver.VcnsDriver(callbacks)
|
||||
|
||||
self.lbv2_driver = mock.Mock()
|
||||
self.core_plugin = mock.Mock()
|
||||
base_mgr.EdgeLoadbalancerBaseManager._lbv2_driver = self.lbv2_driver
|
||||
base_mgr.EdgeLoadbalancerBaseManager._core_plugin = self.core_plugin
|
||||
self._patch_lb_plugin(self.lbv2_driver, self._tested_entity)
|
||||
|
||||
self.lb = lb_models.LoadBalancer(LB_ID, LB_TENANT_ID, 'lb-name', '',
|
||||
'some-subnet', 'port-id', LB_VIP)
|
||||
self.listener = lb_models.Listener(LISTENER_ID, LB_TENANT_ID,
|
||||
'l-name', '', None, LB_ID,
|
||||
'HTTP', protocol_port=80,
|
||||
loadbalancer=self.lb)
|
||||
self.pool = lb_models.Pool(POOL_ID, LB_TENANT_ID, 'pool-name', '',
|
||||
None, 'HTTP', 'ROUND_ROBIN',
|
||||
listener=self.listener)
|
||||
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,
|
||||
1, pool=self.pool)
|
||||
|
||||
def tearDown(self):
|
||||
self._unpatch_lb_plugin(self.lbv2_driver, self._tested_entity)
|
||||
super(BaseTestEdgeLbaasV2, self).tearDown()
|
||||
|
||||
def _patch_lb_plugin(self, lb_plugin, manager):
|
||||
self.real_manager = getattr(lb_plugin, manager)
|
||||
lb_manager = mock.patch.object(lb_plugin, manager).start()
|
||||
mock.patch.object(lb_manager, 'create').start()
|
||||
mock.patch.object(lb_manager, 'update').start()
|
||||
mock.patch.object(lb_manager, 'delete').start()
|
||||
mock.patch.object(lb_manager, 'successful_completion').start()
|
||||
|
||||
def _unpatch_lb_plugin(self, lb_plugin, manager):
|
||||
setattr(lb_plugin, manager, self.real_manager)
|
||||
|
||||
|
||||
class TestEdgeLbaasV2Loadbalancer(BaseTestEdgeLbaasV2):
|
||||
def setUp(self):
|
||||
super(TestEdgeLbaasV2Loadbalancer, self).setUp()
|
||||
|
||||
@property
|
||||
def _tested_entity(self):
|
||||
return 'load_balancer'
|
||||
|
||||
def test_create(self):
|
||||
with mock.patch.object(lb_common, 'get_lbaas_edge_id_for_subnet'
|
||||
) as mock_get_edge, \
|
||||
mock.patch.object(lb_common, 'add_vip_as_secondary_ip'
|
||||
) as mock_vip_sec_ip, \
|
||||
mock.patch.object(lb_common, 'add_vip_fw_rule'
|
||||
) as mock_add_vip_fwr, \
|
||||
mock.patch.object(nsxv_db, 'add_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_db_binding:
|
||||
mock_get_edge.return_value = LB_EDGE_ID
|
||||
mock_add_vip_fwr.return_value = LB_VIP_FWR_ID
|
||||
|
||||
self.edge_driver.loadbalancer.create(self.context, self.lb)
|
||||
|
||||
mock_vip_sec_ip.assert_called_with(self.edge_driver.vcns,
|
||||
LB_EDGE_ID,
|
||||
LB_VIP)
|
||||
mock_add_vip_fwr.assert_called_with(self.edge_driver.vcns,
|
||||
LB_EDGE_ID,
|
||||
LB_ID,
|
||||
LB_VIP)
|
||||
mock_db_binding.assert_called_with(self.context.session,
|
||||
LB_ID,
|
||||
LB_EDGE_ID,
|
||||
LB_VIP_FWR_ID,
|
||||
LB_VIP)
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.load_balancer.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
self.lb)
|
||||
|
||||
def test_update(self):
|
||||
new_lb = lb_models.LoadBalancer(LB_ID, 'yyy-yyy', 'lb-name', 'heh-huh',
|
||||
'some-subnet', 'port-id', LB_VIP)
|
||||
|
||||
self.edge_driver.loadbalancer.update(self.context, self.lb, new_lb)
|
||||
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.load_balancer.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context, new_lb)
|
||||
|
||||
def test_delete(self):
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_binding, \
|
||||
mock.patch.object(lb_common, 'del_vip_fw_rule') as mock_del_fwr, \
|
||||
mock.patch.object(lb_common, 'del_vip_as_secondary_ip'
|
||||
) as mock_vip_sec_ip, \
|
||||
mock.patch.object(nsxv_db, 'del_nsxv_lbaas_loadbalancer_binding',
|
||||
) as mock_del_binding:
|
||||
mock_get_binding.return_value = LB_BINDING
|
||||
|
||||
self.edge_driver.loadbalancer.delete(self.context, self.lb)
|
||||
|
||||
mock_del_fwr.assert_called_with(self.edge_driver.vcns,
|
||||
LB_EDGE_ID,
|
||||
LB_VIP_FWR_ID)
|
||||
mock_vip_sec_ip.assert_called_with(self.edge_driver.vcns,
|
||||
LB_EDGE_ID,
|
||||
LB_VIP)
|
||||
mock_del_binding.assert_called_with(self.context.session,
|
||||
LB_ID)
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.load_balancer.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
self.lb,
|
||||
delete=True)
|
||||
|
||||
def test_stats(self):
|
||||
pass
|
||||
|
||||
def test_refresh(self):
|
||||
pass
|
||||
|
||||
|
||||
class TestEdgeLbaasV2Listener(BaseTestEdgeLbaasV2):
|
||||
def setUp(self):
|
||||
super(TestEdgeLbaasV2Listener, self).setUp()
|
||||
|
||||
@property
|
||||
def _tested_entity(self):
|
||||
return 'listener'
|
||||
|
||||
def test_create(self):
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'create_app_profile'
|
||||
) as mock_create_app_prof, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'create_vip'
|
||||
) as mock_create_vip, \
|
||||
mock.patch.object(nsxv_db, 'add_nsxv_lbaas_listener_binding'
|
||||
) as mock_add_binding:
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
mock_create_app_prof.return_value = (
|
||||
{'location': 'x/' + EDGE_APP_PROFILE_ID}, None)
|
||||
mock_create_vip.return_value = (
|
||||
{'location': 'x/' + EDGE_VIP_ID}, None)
|
||||
|
||||
self.edge_driver.listener.create(self.context, self.listener)
|
||||
|
||||
mock_create_app_prof.assert_called_with(LB_EDGE_ID,
|
||||
EDGE_APP_PROF_DEF)
|
||||
mock_create_vip.assert_called_with(LB_EDGE_ID,
|
||||
EDGE_VIP_DEF)
|
||||
mock_add_binding.assert_called_with(
|
||||
self.context.session, LB_ID, LISTENER_ID, EDGE_APP_PROFILE_ID,
|
||||
EDGE_VIP_ID)
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.listener.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
self.listener)
|
||||
|
||||
def test_update(self):
|
||||
new_listener = lb_models.Listener(LISTENER_ID, LB_TENANT_ID,
|
||||
'l-name', '', None, LB_ID,
|
||||
'HTTP', protocol_port=8000,
|
||||
loadbalancer=self.lb)
|
||||
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_listener_binding'
|
||||
) as mock_get_listener_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'update_app_profile'
|
||||
) as mock_upd_app_prof, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'update_vip'
|
||||
) as mock_upd_vip:
|
||||
mock_get_listener_binding.return_value = LISTENER_BINDING
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
|
||||
self.edge_driver.listener.update(
|
||||
self.context, self.listener, new_listener)
|
||||
|
||||
mock_upd_app_prof.assert_called_with(LB_EDGE_ID,
|
||||
EDGE_APP_PROFILE_ID,
|
||||
EDGE_APP_PROF_DEF)
|
||||
|
||||
edge_vip_def = EDGE_VIP_DEF.copy()
|
||||
edge_vip_def['port'] = 8000
|
||||
mock_upd_vip.assert_called_with(LB_EDGE_ID, EDGE_VIP_ID,
|
||||
edge_vip_def)
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.listener.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
new_listener)
|
||||
|
||||
def test_delete(self):
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_listener_binding'
|
||||
) as mock_get_listener_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'delete_vip'
|
||||
) as mock_del_vip, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'delete_app_profile'
|
||||
) as mock_del_app_prof, \
|
||||
mock.patch.object(nsxv_db, 'del_nsxv_lbaas_listener_binding'
|
||||
) as mock_del_binding:
|
||||
mock_get_listener_binding.return_value = LISTENER_BINDING
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
|
||||
self.edge_driver.listener.delete(self.context, self.listener)
|
||||
|
||||
mock_del_vip.assert_called_with(LB_EDGE_ID, EDGE_VIP_ID)
|
||||
mock_del_app_prof.assert_called_with(LB_EDGE_ID,
|
||||
EDGE_APP_PROFILE_ID)
|
||||
mock_del_binding.assert_called_with(self.context.session,
|
||||
LB_ID, LISTENER_ID)
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.listener.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
self.listener,
|
||||
delete=True)
|
||||
|
||||
|
||||
class TestEdgeLbaasV2Pool(BaseTestEdgeLbaasV2):
|
||||
def setUp(self):
|
||||
super(TestEdgeLbaasV2Pool, self).setUp()
|
||||
|
||||
@property
|
||||
def _tested_entity(self):
|
||||
return 'pool'
|
||||
|
||||
def test_create(self):
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_listener_binding'
|
||||
) as mock_get_listener_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'create_pool'
|
||||
) as mock_create_pool, \
|
||||
mock.patch.object(nsxv_db, 'add_nsxv_lbaas_pool_binding'
|
||||
) as mock_add_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'update_vip'
|
||||
) as mock_upd_vip:
|
||||
mock_get_listener_binding.return_value = LISTENER_BINDING
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
mock_create_pool.return_value = (
|
||||
{'location': 'x/' + EDGE_POOL_ID}, None)
|
||||
|
||||
self.edge_driver.pool.create(self.context, self.pool)
|
||||
|
||||
mock_create_pool.assert_called_with(LB_EDGE_ID,
|
||||
EDGE_POOL_DEF.copy())
|
||||
mock_add_binding.assert_called_with(self.context.session,
|
||||
LB_ID, LISTENER_ID, POOL_ID,
|
||||
EDGE_POOL_ID)
|
||||
edge_vip_def = EDGE_VIP_DEF.copy()
|
||||
edge_vip_def['defaultPoolId'] = EDGE_POOL_ID
|
||||
mock_upd_vip.assert_called_with(LB_EDGE_ID, EDGE_VIP_ID,
|
||||
edge_vip_def)
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.pool.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
self.pool)
|
||||
|
||||
def test_update(self):
|
||||
new_pool = lb_models.Pool(POOL_ID, LB_TENANT_ID, 'pool-name', '',
|
||||
None, 'HTTP', 'LEAST_CONNECTIONS',
|
||||
listener=self.listener)
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_pool_binding'
|
||||
) as mock_get_pool_binding,\
|
||||
mock.patch.object(self.edge_driver.vcns, 'update_pool'
|
||||
) as mock_upd_pool:
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
mock_get_pool_binding.return_value = POOL_BINDING
|
||||
|
||||
self.edge_driver.pool.update(self.context, self.pool, new_pool)
|
||||
|
||||
edge_pool_def = EDGE_POOL_DEF.copy()
|
||||
edge_pool_def['algorithm'] = 'leastconn'
|
||||
mock_upd_pool.assert_called_with(
|
||||
LB_EDGE_ID, EDGE_POOL_ID, edge_pool_def)
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.pool.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
new_pool)
|
||||
|
||||
def test_delete(self):
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_pool_binding'
|
||||
) as mock_get_pool_binding,\
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_listener_binding'
|
||||
) as mock_get_listener_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'update_vip'
|
||||
) as mock_upd_vip, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'delete_pool'
|
||||
) as mock_del_pool, \
|
||||
mock.patch.object(nsxv_db, 'del_nsxv_lbaas_pool_binding'
|
||||
) as mock_del_binding:
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
mock_get_pool_binding.return_value = POOL_BINDING
|
||||
mock_get_listener_binding.return_value = LISTENER_BINDING
|
||||
|
||||
self.edge_driver.pool.delete(self.context, self.pool)
|
||||
|
||||
mock_upd_vip.assert_called_with(LB_EDGE_ID, EDGE_VIP_ID,
|
||||
EDGE_VIP_DEF)
|
||||
mock_del_pool.assert_called_with(LB_EDGE_ID, EDGE_POOL_ID)
|
||||
mock_del_binding.assert_called_with(
|
||||
self.context.session, LB_ID, LISTENER_ID, POOL_ID)
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.pool.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
self.pool,
|
||||
delete=True)
|
||||
|
||||
|
||||
class TestEdgeLbaasV2Member(BaseTestEdgeLbaasV2):
|
||||
def setUp(self):
|
||||
super(TestEdgeLbaasV2Member, self).setUp()
|
||||
|
||||
@property
|
||||
def _tested_entity(self):
|
||||
return 'member'
|
||||
|
||||
def test_create(self):
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_pool_binding'
|
||||
) as mock_get_pool_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'get_pool'
|
||||
) as mock_get_pool, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'update_pool'
|
||||
) as mock_update_pool, \
|
||||
mock.patch.object(self.edge_driver.member,
|
||||
'_get_lbaas_fw_section_id'
|
||||
) as mock_get_sect, \
|
||||
mock.patch.object(lb_common, 'update_pool_fw_rule'
|
||||
) as mock_upd_fw:
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
mock_get_pool_binding.return_value = POOL_BINDING
|
||||
mock_get_pool.return_value = (None, EDGE_POOL_DEF.copy())
|
||||
mock_get_sect.return_value = POOL_FW_SECT
|
||||
|
||||
self.edge_driver.member.create(self.context, self.member)
|
||||
|
||||
edge_pool_def = EDGE_POOL_DEF.copy()
|
||||
edge_pool_def['member'] = [EDGE_MEMBER_DEF]
|
||||
mock_update_pool.assert_called_with(
|
||||
LB_EDGE_ID, EDGE_POOL_ID, edge_pool_def)
|
||||
mock_upd_fw.assert_called_with(self.edge_driver.vcns, POOL_ID,
|
||||
LB_EDGE_ID, POOL_FW_SECT,
|
||||
[MEMBER_ADDRESS])
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.member.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
self.member)
|
||||
|
||||
def test_update(self):
|
||||
new_member = lb_models.Member(MEMBER_ID, LB_TENANT_ID, POOL_ID,
|
||||
MEMBER_ADDRESS, 8000, 1, True,
|
||||
pool=self.pool)
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_pool_binding'
|
||||
) as mock_get_pool_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'get_pool'
|
||||
) as mock_get_pool, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'update_pool'
|
||||
) as mock_update_pool:
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
mock_get_pool_binding.return_value = POOL_BINDING
|
||||
edge_pool_def = EDGE_POOL_DEF.copy()
|
||||
edge_pool_def['member'] = [EDGE_MEMBER_DEF]
|
||||
mock_get_pool.return_value = (None, edge_pool_def)
|
||||
|
||||
self.edge_driver.member.update(self.context, self.member,
|
||||
new_member)
|
||||
|
||||
edge_member_def = EDGE_MEMBER_DEF.copy()
|
||||
edge_member_def['port'] = 8000
|
||||
edge_member_def['monitorPort'] = 8000
|
||||
edge_member_def['condition'] = 'enabled'
|
||||
edge_pool_def['member'] = [edge_member_def]
|
||||
mock_update_pool.assert_called_with(
|
||||
LB_EDGE_ID, EDGE_POOL_ID, edge_pool_def)
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.member.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
new_member)
|
||||
|
||||
def test_delete(self):
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_pool_binding'
|
||||
) as mock_get_pool_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'get_pool'
|
||||
) as mock_get_pool, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'update_pool'
|
||||
) as mock_update_pool:
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
mock_get_pool_binding.return_value = POOL_BINDING
|
||||
edge_pool_def = EDGE_POOL_DEF.copy()
|
||||
edge_pool_def['member'] = [EDGE_MEMBER_DEF]
|
||||
mock_get_pool.return_value = (None, edge_pool_def)
|
||||
|
||||
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_successful_completion = (
|
||||
self.lbv2_driver.member.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
self.member,
|
||||
delete=True)
|
||||
|
||||
|
||||
class TestEdgeLbaasV2HealthMonitor(BaseTestEdgeLbaasV2):
|
||||
def setUp(self):
|
||||
super(TestEdgeLbaasV2HealthMonitor, self).setUp()
|
||||
|
||||
@property
|
||||
def _tested_entity(self):
|
||||
return 'health_monitor'
|
||||
|
||||
def test_create(self):
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_pool_binding'
|
||||
) as mock_get_pool_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_monitor_binding'
|
||||
) as mock_get_mon_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'create_health_monitor'
|
||||
) as mock_create_hm, \
|
||||
mock.patch.object(nsxv_db, 'add_nsxv_lbaas_monitor_binding'
|
||||
) as mock_add_hm_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'get_pool'
|
||||
) as mock_get_pool, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'update_pool'
|
||||
) as mock_update_pool:
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
mock_get_pool_binding.return_value = POOL_BINDING
|
||||
mock_get_mon_binding.return_value = None
|
||||
mock_create_hm.return_value = (
|
||||
{'location': 'x/' + EDGE_HM_ID}, None)
|
||||
mock_get_pool.return_value = (None, EDGE_POOL_DEF.copy())
|
||||
|
||||
self.edge_driver.healthmonitor.create(self.context, self.hm)
|
||||
|
||||
mock_create_hm.assert_called_with(LB_EDGE_ID, EDGE_HM_DEF)
|
||||
mock_add_hm_binding.assert_called_with(
|
||||
self.context.session, LB_ID, LISTENER_ID, POOL_ID, HM_ID,
|
||||
LB_EDGE_ID, EDGE_HM_ID)
|
||||
edge_pool_def = EDGE_POOL_DEF.copy()
|
||||
edge_pool_def['monitorId'] = [EDGE_HM_ID]
|
||||
mock_update_pool.assert_called_with(
|
||||
LB_EDGE_ID, EDGE_POOL_ID, edge_pool_def)
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.health_monitor.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
self.hm)
|
||||
|
||||
def test_update(self):
|
||||
new_hm = lb_models.HealthMonitor(HM_ID, LB_TENANT_ID, 'PING', 3, 3,
|
||||
3, pool=self.pool)
|
||||
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_pool_binding'
|
||||
) as mock_get_pool_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_monitor_binding'
|
||||
) as mock_get_mon_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'update_health_monitor'
|
||||
) as mock_upd_hm:
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
mock_get_pool_binding.return_value = POOL_BINDING
|
||||
mock_get_mon_binding.return_value = HM_BINDING
|
||||
|
||||
self.edge_driver.healthmonitor.update(
|
||||
self.context, self.hm, new_hm)
|
||||
|
||||
edge_hm_def = EDGE_HM_DEF.copy()
|
||||
edge_hm_def['maxRetries'] = 3
|
||||
mock_upd_hm.assert_called_with(LB_EDGE_ID, EDGE_HM_ID, edge_hm_def)
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.health_monitor.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
new_hm)
|
||||
|
||||
def test_delete(self):
|
||||
with mock.patch.object(nsxv_db, 'get_nsxv_lbaas_loadbalancer_binding'
|
||||
) as mock_get_lb_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_pool_binding'
|
||||
) as mock_get_pool_binding, \
|
||||
mock.patch.object(nsxv_db, 'get_nsxv_lbaas_monitor_binding'
|
||||
) as mock_get_mon_binding, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'delete_health_monitor'
|
||||
) as mock_del_hm, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'get_pool'
|
||||
) as mock_get_pool, \
|
||||
mock.patch.object(self.edge_driver.vcns, 'update_pool'
|
||||
) as mock_update_pool, \
|
||||
mock.patch.object(nsxv_db, 'del_nsxv_lbaas_monitor_binding'
|
||||
) as mock_del_binding:
|
||||
|
||||
mock_get_lb_binding.return_value = LB_BINDING
|
||||
mock_get_pool_binding.return_value = POOL_BINDING
|
||||
mock_get_mon_binding.return_value = HM_BINDING
|
||||
edge_pool_def = EDGE_POOL_DEF.copy()
|
||||
edge_pool_def['monitorId'] = [EDGE_HM_ID]
|
||||
mock_get_pool.return_value = (None, edge_pool_def)
|
||||
|
||||
self.edge_driver.healthmonitor.delete(
|
||||
self.context, self.hm)
|
||||
|
||||
mock_del_hm.assert_called_with(LB_EDGE_ID, EDGE_HM_ID)
|
||||
edge_pool_def['monitorId'] = []
|
||||
mock_update_pool.assert_called_with(
|
||||
LB_EDGE_ID, EDGE_POOL_ID, edge_pool_def)
|
||||
mock_del_binding.assert_called_with(self.context.session, LB_ID,
|
||||
LISTENER_ID, POOL_ID, HM_ID,
|
||||
LB_EDGE_ID)
|
||||
mock_successful_completion = (
|
||||
self.lbv2_driver.health_monitor.successful_completion)
|
||||
mock_successful_completion.assert_called_with(self.context,
|
||||
self.hm,
|
||||
delete=True)
|
173
vmware_nsx/tests/unit/nsx_v/test_lbaas_common.py
Normal file
173
vmware_nsx/tests/unit/nsx_v/test_lbaas_common.py
Normal file
@ -0,0 +1,173 @@
|
||||
# Copyright 2015 VMware, Inc.
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from neutron.tests import base
|
||||
|
||||
from vmware_nsx.plugins.nsx_v.vshield import vcns_driver
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
|
||||
|
||||
|
||||
EDGE_ID = 'edge-x'
|
||||
POOL_ID = 'b3dfb476-6fdf-4ddd-b6bd-e86ae78dc30b'
|
||||
|
||||
|
||||
def firewall_section_maker(if_ip_list, vip_ip_list):
|
||||
return (
|
||||
'<section id="1132" name="LBaaS FW Rules"><rule><name>' + POOL_ID +
|
||||
'</name><action>allow</action><sources excluded="false"><source>'
|
||||
'<type>Ipv4Address</type><value>' + ','.join(if_ip_list) +
|
||||
'</value></source></sources><destinations excluded="false">'
|
||||
'<destination><type>Ipv4Address</type><value>' +
|
||||
','.join(vip_ip_list) + '</value></destination></destinations></rule>'
|
||||
'</section>')
|
||||
|
||||
|
||||
def if_maker(ip_list):
|
||||
intf = {
|
||||
'index': 1, 'name': 'internal1', 'addressGroups': {
|
||||
'addressGroups': [
|
||||
{'subnetPrefixLength': '24',
|
||||
'secondaryAddresses': {
|
||||
'ipAddress': ip_list,
|
||||
'type': 'secondary_addresses'},
|
||||
'primaryAddress': '10.0.0.1',
|
||||
'subnetMask': '255.255.255.0'}]},
|
||||
'portgroupName': 'pg1234', 'label': 'vNic_1',
|
||||
'type': 'internal', 'portgroupId': 'virtualwire-31'}
|
||||
return intf
|
||||
|
||||
|
||||
def if_list_maker(ip_list):
|
||||
if_list = {
|
||||
'vnics': [
|
||||
{'index': 0, 'name': 'external', 'addressGroups': {
|
||||
'addressGroups': [
|
||||
{'subnetMask': '255.255.255.0',
|
||||
'primaryAddress': '172.24.4.2',
|
||||
'subnetPrefixLength': '24'}]},
|
||||
'portgroupName': 'VM Network', 'label': 'vNic_0',
|
||||
'type': 'uplink', 'portgroupId': 'network-13'},
|
||||
{'index': 1, 'name': 'internal1', 'addressGroups': {
|
||||
'addressGroups': [
|
||||
{'subnetPrefixLength': '24',
|
||||
'secondaryAddresses': {
|
||||
'ipAddress': ip_list,
|
||||
'type': 'secondary_addresses'},
|
||||
'primaryAddress': '10.0.0.1',
|
||||
'subnetMask': '255.255.255.0'}]},
|
||||
'portgroupName': 'pg1234',
|
||||
'label': 'vNic_1', 'type': 'internal',
|
||||
'portgroupId': 'virtualwire-31'},
|
||||
{'index': 2, 'name': 'vnic2',
|
||||
'addressGroups': {'addressGroups': []},
|
||||
'label': 'vNic_2', 'type': 'internal'},
|
||||
{'index': 3, 'name': 'vnic3',
|
||||
'addressGroups': {'addressGroups': []},
|
||||
'label': 'vNic_3', 'type': 'internal'}]}
|
||||
return if_list
|
||||
|
||||
|
||||
class TestLbaasCommon(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestLbaasCommon, self).setUp()
|
||||
callbacks = mock.Mock()
|
||||
callbacks.plugin = mock.Mock()
|
||||
self.edge_driver = vcns_driver.VcnsDriver(callbacks)
|
||||
self.edge_driver._lb_driver_prop = mock.Mock()
|
||||
|
||||
def _mock_edge_driver_vcns(self, attr):
|
||||
return mock.patch.object(self.edge_driver.vcns, attr)
|
||||
|
||||
def test_update_pool_fw_rule_add(self):
|
||||
vip_ips = ['10.0.0.1', '11.0.0.1']
|
||||
member_ips = ['10.0.0.10', '11.0.0.10']
|
||||
edge_fw_section = firewall_section_maker(vip_ips, ['10.0.0.10'])
|
||||
edge_fw_updated_section = firewall_section_maker(vip_ips, member_ips)
|
||||
|
||||
with self._mock_edge_driver_vcns(
|
||||
'get_section') as mock_get_section,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_section') as mock_update_section:
|
||||
|
||||
tmp_get_ips = lb_common.get_edge_ip_addresses
|
||||
lb_common.get_edge_ip_addresses = mock.Mock()
|
||||
lb_common.get_edge_ip_addresses.return_value = vip_ips
|
||||
|
||||
mock_get_section.return_value = (None, edge_fw_section)
|
||||
lb_common.update_pool_fw_rule(
|
||||
self.edge_driver.vcns, POOL_ID, EDGE_ID, '1111', member_ips)
|
||||
mock_update_section.assert_called_with(
|
||||
'/api/4.0/firewall/globalroot-0/config/layer3sections/1111',
|
||||
edge_fw_updated_section, None)
|
||||
lb_common.get_edge_ip_addresses = tmp_get_ips
|
||||
|
||||
def test_update_pool_fw_rule_del(self):
|
||||
vip_ips = ['10.0.0.1', '11.0.0.1']
|
||||
member_ips = ['10.0.0.10']
|
||||
edge_fw_section = firewall_section_maker(vip_ips, ['10.0.0.10',
|
||||
'11.0.0.10'])
|
||||
edge_fw_updated_section = firewall_section_maker(vip_ips, member_ips)
|
||||
|
||||
with self._mock_edge_driver_vcns('get_section') as mock_get_section, \
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_section') as mock_update_section:
|
||||
|
||||
tmp_get_ips = lb_common.get_edge_ip_addresses
|
||||
lb_common.get_edge_ip_addresses = mock.Mock()
|
||||
lb_common.get_edge_ip_addresses.return_value = vip_ips
|
||||
mock_get_section.return_value = (None, edge_fw_section)
|
||||
lb_common.update_pool_fw_rule(
|
||||
self.edge_driver.vcns, POOL_ID, EDGE_ID, '1111', member_ips)
|
||||
mock_update_section.assert_called_with(
|
||||
'/api/4.0/firewall/globalroot-0/config/layer3sections/1111',
|
||||
edge_fw_updated_section, None)
|
||||
lb_common.get_edge_ip_addresses = tmp_get_ips
|
||||
|
||||
def test_add_vip_as_secondary_ip(self):
|
||||
update_if = if_maker(['10.0.0.6', '10.0.0.8'])
|
||||
|
||||
with self._mock_edge_driver_vcns('get_interfaces') as mock_get_if,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_interface') as mock_update_if:
|
||||
|
||||
mock_get_if.return_value = (None, if_list_maker(['10.0.0.6']))
|
||||
|
||||
lb_common.add_vip_as_secondary_ip(
|
||||
self.edge_driver.vcns, EDGE_ID, '10.0.0.8')
|
||||
mock_update_if.assert_called_with(EDGE_ID, update_if)
|
||||
|
||||
def test_del_vip_as_secondary_ip(self):
|
||||
update_if = if_maker(['10.0.0.6'])
|
||||
|
||||
with self._mock_edge_driver_vcns('get_interfaces') as mock_get_if,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_interface') as mock_update_if:
|
||||
|
||||
mock_get_if.return_value = (None, if_list_maker(['10.0.0.6',
|
||||
'10.0.0.8']))
|
||||
|
||||
lb_common.del_vip_as_secondary_ip(
|
||||
self.edge_driver.vcns, EDGE_ID, '10.0.0.8')
|
||||
mock_update_if.assert_called_with(EDGE_ID, update_if)
|
||||
|
||||
def test_get_edge_ip_addresses(self):
|
||||
get_if_list = if_list_maker(['10.0.0.6'])
|
||||
|
||||
with mock.patch.object(self.edge_driver.vcns, 'get_interfaces',
|
||||
return_value=(None, get_if_list)):
|
||||
ip_list = lb_common.get_edge_ip_addresses(self.edge_driver.vcns,
|
||||
EDGE_ID)
|
||||
self.assertEqual(['172.24.4.2', '10.0.0.1'], ip_list)
|
Loading…
Reference in New Issue
Block a user