Octavia Proxy Plugin
This plugin proxies LBaaS V2 API requests to Octavia. Fixes test errors... Closes-Bug: #1596660 Change-Id: If1e1348e4734b5b9b839241453059f628d9c4948
This commit is contained in:
parent
e890821ba0
commit
0c76484a50
|
@ -0,0 +1,366 @@
|
|||
# Copyright 2017, Rackspace US, 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.
|
||||
|
||||
import functools
|
||||
|
||||
from neutron.db import servicetype_db as st_db
|
||||
from neutron.services import provider_configuration as pconf
|
||||
from neutron_lib import exceptions as lib_exc
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils
|
||||
import requests
|
||||
|
||||
from neutron_lbaas.extensions import loadbalancerv2
|
||||
from neutron_lbaas.services.loadbalancer import constants
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
VERSION = 'v2.0'
|
||||
OCTAVIA_PROXY_CLIENT = (
|
||||
"LBaaS V2 Octavia Proxy/{version} "
|
||||
"(https://wiki.openstack.org/wiki/Octavia)").format(version=VERSION)
|
||||
FILTER = ['vip_address', 'vip_network_id', 'flavor_id',
|
||||
'provider', 'redirect_pool_id']
|
||||
|
||||
LOADBALANCER = 'loadbalancer'
|
||||
LISTENER = 'listener'
|
||||
POOL = 'pool'
|
||||
L7POLICY = 'l7policy'
|
||||
L7POLICY_RULE = 'rule'
|
||||
MEMBER = 'member'
|
||||
HEALTH_MONITOR = 'healthmonitor'
|
||||
STATUS = 'statuses'
|
||||
GRAPH = 'graph'
|
||||
|
||||
OPTS = [
|
||||
cfg.StrOpt(
|
||||
'base_url',
|
||||
default='http://127.0.0.1:9876',
|
||||
help=_('URL of Octavia controller root'),
|
||||
),
|
||||
]
|
||||
|
||||
cfg.CONF.register_opts(OPTS, 'octavia')
|
||||
|
||||
|
||||
def add_provider_configuration(type_manager, service_type):
|
||||
type_manager.add_provider_configuration(
|
||||
service_type,
|
||||
pconf.ProviderConfiguration('neutron_lbaas_proxy'))
|
||||
|
||||
|
||||
class LoadBalancerProxyPluginv2(loadbalancerv2.LoadBalancerPluginBaseV2):
|
||||
"""Implementation of the Neutron Loadbalancer Proxy Plugin.
|
||||
|
||||
This class proxies all requests/reponses to Octavia
|
||||
"""
|
||||
|
||||
supported_extension_aliases = ["lbaasv2",
|
||||
"shared_pools",
|
||||
"l7",
|
||||
"lbaas_agent_schedulerv2",
|
||||
"service-type",
|
||||
"lb-graph",
|
||||
"lb_network_vip",
|
||||
"hm_max_retries_down"]
|
||||
path_prefix = loadbalancerv2.LOADBALANCERV2_PREFIX
|
||||
|
||||
def __init__(self):
|
||||
self.service_type_manager = st_db.ServiceTypeManager.get_instance()
|
||||
add_provider_configuration(
|
||||
self.service_type_manager, constants.LOADBALANCERV2)
|
||||
self.get = functools.partial(self.request, 'GET')
|
||||
self.post = functools.partial(self.request, 'POST')
|
||||
self.put = functools.partial(self.request, 'PUT')
|
||||
self.delete = functools.partial(self.request, 'DELETE')
|
||||
self.base_url = '{}/{}/lbaas'.format(cfg.CONF.octavia.base_url,
|
||||
VERSION)
|
||||
|
||||
def get_plugin_type(self):
|
||||
return constants.LOADBALANCERV2
|
||||
|
||||
def get_plugin_description(self):
|
||||
return "Neutron LoadBalancer Proxy Plugin"
|
||||
|
||||
def request(self, method, url, token=None, args=None, headers=None,
|
||||
accepted_codes=[200, 201, 202, 204]):
|
||||
params = {}
|
||||
if args:
|
||||
# extract filter and fields
|
||||
if 'filters' in args:
|
||||
params = args.pop('filters')
|
||||
if 'fields' in args:
|
||||
params['fields'] = args.pop('fields')
|
||||
args = jsonutils.dumps(args)
|
||||
if not headers:
|
||||
headers = {
|
||||
'Content-type': 'application/json',
|
||||
'X-Auth-Token': token
|
||||
}
|
||||
headers['User-Agent'] = OCTAVIA_PROXY_CLIENT
|
||||
|
||||
url = '{}/{}'.format(self.base_url, str(url))
|
||||
LOG.debug("url = %s", url)
|
||||
LOG.debug("args = %s", args)
|
||||
LOG.debug("params = %s", str(params))
|
||||
r = requests.request(method, url, data=args, params=params,
|
||||
headers=headers)
|
||||
LOG.debug("Octavia Response Code: {0}".format(r.status_code))
|
||||
LOG.debug("Octavia Response Body: {0}".format(r.content))
|
||||
LOG.debug("Octavia Response Headers: {0}".format(r.headers))
|
||||
|
||||
if r.status_code in accepted_codes:
|
||||
if method != 'DELETE':
|
||||
return r.json()
|
||||
elif r.status_code == 413:
|
||||
e = lib_exc.OverQuota()
|
||||
e.msg = str(r.content)
|
||||
raise e
|
||||
elif r.status_code == 409:
|
||||
e = lib_exc.Conflict()
|
||||
e.msg = str(r.content)
|
||||
raise e
|
||||
elif r.status_code == 401:
|
||||
e = lib_exc.NotAuthorized()
|
||||
e.msg = str(r.content)
|
||||
raise e
|
||||
elif r.status_code == 404:
|
||||
e = lib_exc.NotFound()
|
||||
e.msg = str(r.content)
|
||||
raise e
|
||||
elif r.status_code == 400:
|
||||
e = lib_exc.BadRequest(resource="", msg="")
|
||||
e.msg = str(r.content)
|
||||
raise e
|
||||
else:
|
||||
raise loadbalancerv2.DriverError(msg=str(r.content))
|
||||
|
||||
def _filter(self, keys, map):
|
||||
"""Filter the args map
|
||||
|
||||
keys: The keys to filter out
|
||||
map: the args in a map
|
||||
|
||||
NOTE: This returns a deep copy - leaving the original alone
|
||||
"""
|
||||
|
||||
res = {}
|
||||
for k in map:
|
||||
if k not in keys:
|
||||
if map[k]:
|
||||
res[k] = map[k]
|
||||
if 'tenant_id' in res:
|
||||
res['project_id'] = res.pop('tenant_id')
|
||||
return res
|
||||
|
||||
def pluralize(self, name):
|
||||
if name.endswith('y'):
|
||||
return name[:-1] + "ies"
|
||||
elif not name.endswith('s'):
|
||||
return "{}s".format(name)
|
||||
return name
|
||||
|
||||
def _path(self, resource, sub_resource, resource_id):
|
||||
url = resource
|
||||
if sub_resource:
|
||||
url = "{}/{}/{}".format(self.pluralize(resource),
|
||||
resource_id, sub_resource)
|
||||
return self.pluralize(url)
|
||||
|
||||
def _create_resource(self, resource, context, res, sub_resource=None,
|
||||
resource_id=None):
|
||||
# clean up the map
|
||||
resource_ = resource if not sub_resource else sub_resource
|
||||
r = self._filter(FILTER, res[resource_])
|
||||
r = self.post(self._path(resource, sub_resource, resource_id),
|
||||
context.auth_token, {resource_: r})
|
||||
return r[resource_]
|
||||
|
||||
def _get_resources(self, resource, context, filters=None, fields=None,
|
||||
sub_resource=None, resource_id=None):
|
||||
# not sure how to test that or if we even support sorting/filtering?
|
||||
resource_ = resource if not sub_resource else sub_resource
|
||||
args = {}
|
||||
if filters:
|
||||
if 'tenant_id' in filters:
|
||||
filters['project_id'] = filters.pop('tenant_id')
|
||||
args['filters'] = filters
|
||||
if fields:
|
||||
args['fields'] = fields
|
||||
res = self.get(self._path(resource, sub_resource, resource_id),
|
||||
context.auth_token, args)
|
||||
return res[self.pluralize(resource_)]
|
||||
|
||||
def _get_resource(self, resource, context, id, fields=None,
|
||||
sub_resource=None, resource_id=None):
|
||||
# not sure how to test that or if we even support sorting/filtering?
|
||||
args = {}
|
||||
if fields:
|
||||
args['fields'] = fields
|
||||
resource_ = resource if not sub_resource else sub_resource
|
||||
res = self.get('{}/{}'.format(
|
||||
self._path(resource, sub_resource, resource_id), id),
|
||||
context.auth_token, args)
|
||||
return res[resource_]
|
||||
|
||||
def _update_resource(self, resource, context, id, res,
|
||||
sub_resource=None, resource_id=None):
|
||||
# clean up the map
|
||||
resource_ = resource if not sub_resource else sub_resource
|
||||
r = self._filter(FILTER, res[resource_])
|
||||
res = self.put('{}/{}'.format(self._path(
|
||||
resource, sub_resource, resource_id), id),
|
||||
context.auth_token,
|
||||
{resource_: r})
|
||||
return res[resource_]
|
||||
|
||||
def _delete_resource(self, resource, context, id,
|
||||
sub_resource=None, resource_id=None):
|
||||
self.delete('{}/{}'.format(self._path(
|
||||
resource, sub_resource, resource_id), id),
|
||||
context.auth_token)
|
||||
|
||||
def create_loadbalancer(self, context, loadbalancer):
|
||||
return self._create_resource(LOADBALANCER, context, loadbalancer)
|
||||
|
||||
def get_loadbalancers(self, context, filters=None, fields=None):
|
||||
return self._get_resources(LOADBALANCER, context, filters, fields)
|
||||
|
||||
def get_loadbalancer(self, context, id, fields=None):
|
||||
return self._get_resource(LOADBALANCER, context, id, fields)
|
||||
|
||||
def update_loadbalancer(self, context, id, loadbalancer):
|
||||
return self._update_resource(LOADBALANCER, context, id, loadbalancer)
|
||||
|
||||
def delete_loadbalancer(self, context, id):
|
||||
self._delete_resource(LOADBALANCER, context, id)
|
||||
|
||||
def create_listener(self, context, listener):
|
||||
return self._create_resource(LISTENER, context, listener)
|
||||
|
||||
def get_listener(self, context, id, fields=None):
|
||||
return self._get_resource(LISTENER, context, id, fields)
|
||||
|
||||
def get_listeners(self, context, filters=None, fields=None):
|
||||
return self._get_resources(LISTENER, context, filters, fields)
|
||||
|
||||
def update_listener(self, context, id, listener):
|
||||
return self._update_resource(LISTENER, context, id, listener)
|
||||
|
||||
def delete_listener(self, context, id):
|
||||
return self._delete_resource(LISTENER, context, id)
|
||||
|
||||
def get_pools(self, context, filters=None, fields=None):
|
||||
return self._get_resources(POOL, context, filters, fields)
|
||||
|
||||
def get_pool(self, context, id, fields=None):
|
||||
return self._get_resource(POOL, context, id, fields)
|
||||
|
||||
def create_pool(self, context, pool):
|
||||
return self._create_resource(POOL, context, pool)
|
||||
|
||||
def update_pool(self, context, id, pool):
|
||||
return self._update_resource(POOL, context, id, pool)
|
||||
|
||||
def delete_pool(self, context, id):
|
||||
return self._delete_resource(POOL, context, id)
|
||||
|
||||
def stats(self, context, loadbalancer_id):
|
||||
pass
|
||||
|
||||
def get_pool_members(self, context, pool_id,
|
||||
filters=None,
|
||||
fields=None):
|
||||
return self._get_resources(POOL, context, filters, fields,
|
||||
MEMBER, pool_id)
|
||||
|
||||
def get_pool_member(self, context, id, pool_id,
|
||||
fields=None):
|
||||
return self._get_resource(POOL, context, id, fields,
|
||||
MEMBER, pool_id)
|
||||
|
||||
def create_pool_member(self, context, pool_id, member):
|
||||
return self._create_resource(POOL, context, member, MEMBER, pool_id)
|
||||
|
||||
def update_pool_member(self, context, id, pool_id, member):
|
||||
return self._update_resource(POOL, context, id, member,
|
||||
MEMBER, pool_id)
|
||||
|
||||
def delete_pool_member(self, context, id, pool_id):
|
||||
return self._delete_resource(POOL, context, id, MEMBER, pool_id)
|
||||
|
||||
def get_healthmonitors(self, context, filters=None, fields=None):
|
||||
return self._get_resources(HEALTH_MONITOR, context, filters, fields)
|
||||
|
||||
def get_healthmonitor(self, context, id, fields=None):
|
||||
return self._get_resource(HEALTH_MONITOR, context, id, fields)
|
||||
|
||||
def create_healthmonitor(self, context, healthmonitor):
|
||||
return self._create_resource(HEALTH_MONITOR, context, healthmonitor)
|
||||
|
||||
def update_healthmonitor(self, context, id, healthmonitor):
|
||||
return self._update_resource(HEALTH_MONITOR, context,
|
||||
id, healthmonitor)
|
||||
|
||||
def delete_healthmonitor(self, context, id):
|
||||
return self._delete_resource(HEALTH_MONITOR, context, id)
|
||||
|
||||
def get_members(self, context, filters=None, fields=None):
|
||||
pass
|
||||
|
||||
def get_member(self, context, id, fields=None):
|
||||
pass
|
||||
|
||||
def statuses(self, context, loadbalancer_id):
|
||||
return self._get_resources(LOADBALANCER, context, sub_resource=STATUS,
|
||||
resource_id=loadbalancer_id)
|
||||
|
||||
def get_l7policies(self, context, filters=None, fields=None):
|
||||
return self._get_resources(L7POLICY, context, filters, fields)
|
||||
|
||||
def get_l7policy(self, context, id, fields=None):
|
||||
return self._get_resource(L7POLICY, context, id, fields)
|
||||
|
||||
def create_l7policy(self, context, l7policy):
|
||||
return self._create_resource(L7POLICY, context, l7policy)
|
||||
|
||||
def update_l7policy(self, context, id, l7policy):
|
||||
return self._update_resource(L7POLICY, context, id, l7policy)
|
||||
|
||||
def delete_l7policy(self, context, id):
|
||||
return self._delete_resource(L7POLICY, context, id)
|
||||
|
||||
def get_l7policy_rules(self, context, l7policy_id,
|
||||
filters=None, fields=None):
|
||||
return self._get_resources(L7POLICY, context, filters, fields,
|
||||
L7POLICY_RULE, l7policy_id)
|
||||
|
||||
def get_l7policy_rule(self, context, id, l7policy_id, fields=None):
|
||||
return self._get_resource(L7POLICY, context, id, fields,
|
||||
L7POLICY_RULE, l7policy_id)
|
||||
|
||||
def create_l7policy_rule(self, context, rule, l7policy_id):
|
||||
return self._create_resource(L7POLICY, context, rule, L7POLICY_RULE,
|
||||
l7policy_id)
|
||||
|
||||
def update_l7policy_rule(self, context, id, rule, l7policy_id):
|
||||
return self._update_resource(L7POLICY, context, id, rule,
|
||||
L7POLICY_RULE, l7policy_id)
|
||||
|
||||
def delete_l7policy_rule(self, context, id, l7policy_id):
|
||||
return self._delete_resource(L7POLICY, context, id, L7POLICY_RULE,
|
||||
l7policy_id)
|
||||
|
||||
def create_graph(self, context, graph):
|
||||
return self._create_resource(GRAPH, context, graph)
|
|
@ -13,14 +13,15 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import contextlib
|
||||
import copy
|
||||
|
||||
import mock
|
||||
import six
|
||||
import testtools
|
||||
import webob.exc
|
||||
|
||||
from neutron.api import extensions
|
||||
from neutron.common import config
|
||||
import neutron.db.l3_db # noqa
|
||||
from neutron.tests.unit.db import test_db_base_plugin_v2
|
||||
from neutron_lib import constants as n_constants
|
||||
from neutron_lib import context
|
||||
from neutron_lib import exceptions as n_exc
|
||||
|
@ -28,26 +29,20 @@ from neutron_lib.plugins import constants
|
|||
from neutron_lib.plugins import directory
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
import six
|
||||
import testtools
|
||||
import webob.exc
|
||||
|
||||
from neutron_lbaas._i18n import _
|
||||
from neutron_lbaas.common.cert_manager import cert_manager
|
||||
from neutron_lbaas.common import exceptions
|
||||
from neutron_lbaas.db.loadbalancer import loadbalancer_dbv2
|
||||
from neutron_lbaas.db.loadbalancer import models
|
||||
from neutron_lbaas.drivers.logging_noop import driver as noop_driver
|
||||
import neutron_lbaas.extensions
|
||||
from neutron_lbaas.extensions import healthmonitor_max_retries_down
|
||||
from neutron_lbaas.extensions import l7
|
||||
from neutron_lbaas.extensions import lb_graph
|
||||
from neutron_lbaas.extensions import lb_network_vip
|
||||
from neutron_lbaas.extensions import loadbalancerv2
|
||||
from neutron_lbaas.extensions import sharedpools
|
||||
from neutron_lbaas.services.loadbalancer import constants as lb_const
|
||||
from neutron_lbaas.services.loadbalancer import plugin as loadbalancer_plugin
|
||||
from neutron_lbaas.tests import base
|
||||
from neutron_lbaas.tests.unit.db.loadbalancer import util
|
||||
|
||||
|
||||
DB_CORE_PLUGIN_CLASS = 'neutron.db.db_base_plugin_v2.NeutronDbPluginV2'
|
||||
|
@ -63,507 +58,8 @@ extensions_path = ':'.join(neutron_lbaas.extensions.__path__)
|
|||
_subnet_id = "0c798ed8-33ba-11e2-8b28-000c291c4d14"
|
||||
|
||||
|
||||
class LbaasTestMixin(object):
|
||||
resource_keys = list(loadbalancerv2.RESOURCE_ATTRIBUTE_MAP.keys())
|
||||
resource_keys.extend(l7.RESOURCE_ATTRIBUTE_MAP.keys())
|
||||
resource_keys.extend(lb_graph.RESOURCE_ATTRIBUTE_MAP.keys())
|
||||
resource_keys.extend(lb_network_vip.EXTENDED_ATTRIBUTES_2_0.keys())
|
||||
resource_keys.extend(healthmonitor_max_retries_down.
|
||||
EXTENDED_ATTRIBUTES_2_0.keys())
|
||||
resource_prefix_map = dict(
|
||||
(k, loadbalancerv2.LOADBALANCERV2_PREFIX)
|
||||
for k in resource_keys)
|
||||
|
||||
def _get_loadbalancer_optional_args(self):
|
||||
return ('description', 'vip_address', 'admin_state_up', 'name',
|
||||
'listeners', 'vip_network_id', 'vip_subnet_id')
|
||||
|
||||
def _create_loadbalancer(self, fmt, subnet_id,
|
||||
expected_res_status=None, **kwargs):
|
||||
data = {'loadbalancer': {'vip_subnet_id': subnet_id,
|
||||
'tenant_id': self._tenant_id}}
|
||||
args = self._get_loadbalancer_optional_args()
|
||||
for arg in args:
|
||||
if arg in kwargs:
|
||||
if kwargs[arg] is not None:
|
||||
data['loadbalancer'][arg] = kwargs[arg]
|
||||
else:
|
||||
data['loadbalancer'].pop(arg, None)
|
||||
|
||||
lb_req = self.new_create_request('loadbalancers', data, fmt)
|
||||
lb_res = lb_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(expected_res_status, lb_res.status_int)
|
||||
|
||||
return lb_res
|
||||
|
||||
def _create_graph(self, fmt, subnet_id, expected_res_status=None,
|
||||
**kwargs):
|
||||
data = {'vip_subnet_id': subnet_id, 'tenant_id': self._tenant_id}
|
||||
args = self._get_loadbalancer_optional_args()
|
||||
for arg in args:
|
||||
if arg in kwargs and kwargs[arg] is not None:
|
||||
data[arg] = kwargs[arg]
|
||||
|
||||
data = {'graph': {'loadbalancer': data, 'tenant_id': self._tenant_id}}
|
||||
lb_req = self.new_create_request('graphs', data, fmt)
|
||||
lb_res = lb_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(expected_res_status, lb_res.status_int)
|
||||
|
||||
return lb_res
|
||||
|
||||
def _get_listener_optional_args(self):
|
||||
return ('name', 'description', 'default_pool_id', 'loadbalancer_id',
|
||||
'connection_limit', 'admin_state_up',
|
||||
'default_tls_container_ref', 'sni_container_refs')
|
||||
|
||||
def _create_listener(self, fmt, protocol, protocol_port,
|
||||
loadbalancer_id=None, default_pool_id=None,
|
||||
expected_res_status=None, **kwargs):
|
||||
data = {'listener': {'protocol': protocol,
|
||||
'protocol_port': protocol_port,
|
||||
'tenant_id': self._tenant_id}}
|
||||
if loadbalancer_id:
|
||||
data['listener']['loadbalancer_id'] = loadbalancer_id
|
||||
if default_pool_id:
|
||||
data['listener']['default_pool_id'] = default_pool_id
|
||||
|
||||
args = self._get_listener_optional_args()
|
||||
for arg in args:
|
||||
if arg in kwargs and kwargs[arg] is not None:
|
||||
data['listener'][arg] = kwargs[arg]
|
||||
|
||||
listener_req = self.new_create_request('listeners', data, fmt)
|
||||
listener_res = listener_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(expected_res_status, listener_res.status_int)
|
||||
|
||||
return listener_res
|
||||
|
||||
def _get_pool_optional_args(self):
|
||||
return 'name', 'description', 'admin_state_up', 'session_persistence'
|
||||
|
||||
def _create_pool(self, fmt, protocol, lb_algorithm, listener_id=None,
|
||||
loadbalancer_id=None, expected_res_status=None, **kwargs):
|
||||
data = {'pool': {'protocol': protocol,
|
||||
'lb_algorithm': lb_algorithm,
|
||||
'tenant_id': self._tenant_id}}
|
||||
if listener_id:
|
||||
data['pool']['listener_id'] = listener_id
|
||||
if loadbalancer_id:
|
||||
data['pool']['loadbalancer_id'] = loadbalancer_id
|
||||
|
||||
args = self._get_pool_optional_args()
|
||||
for arg in args:
|
||||
if arg in kwargs and kwargs[arg] is not None:
|
||||
data['pool'][arg] = kwargs[arg]
|
||||
|
||||
pool_req = self.new_create_request('pools', data, fmt)
|
||||
pool_res = pool_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(expected_res_status, pool_res.status_int)
|
||||
|
||||
return pool_res
|
||||
|
||||
def _get_member_optional_args(self):
|
||||
return 'weight', 'admin_state_up', 'name'
|
||||
|
||||
def _create_member(self, fmt, pool_id, address, protocol_port, subnet_id,
|
||||
expected_res_status=None, **kwargs):
|
||||
data = {'member': {'address': address,
|
||||
'protocol_port': protocol_port,
|
||||
'subnet_id': subnet_id,
|
||||
'tenant_id': self._tenant_id}}
|
||||
|
||||
args = self._get_member_optional_args()
|
||||
for arg in args:
|
||||
if arg in kwargs and kwargs[arg] is not None:
|
||||
data['member'][arg] = kwargs[arg]
|
||||
member_req = self.new_create_request('pools',
|
||||
data,
|
||||
fmt=fmt,
|
||||
id=pool_id,
|
||||
subresource='members')
|
||||
member_res = member_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(expected_res_status, member_res.status_int)
|
||||
|
||||
return member_res
|
||||
|
||||
def _get_healthmonitor_optional_args(self):
|
||||
return ('weight', 'admin_state_up', 'expected_codes', 'url_path',
|
||||
'http_method', 'name', 'max_retries_down')
|
||||
|
||||
def _create_healthmonitor(self, fmt, pool_id, type, delay, timeout,
|
||||
max_retries, expected_res_status=None, **kwargs):
|
||||
data = {'healthmonitor': {'type': type,
|
||||
'delay': delay,
|
||||
'timeout': timeout,
|
||||
'max_retries': max_retries,
|
||||
'pool_id': pool_id,
|
||||
'tenant_id': self._tenant_id}}
|
||||
|
||||
args = self._get_healthmonitor_optional_args()
|
||||
for arg in args:
|
||||
if arg in kwargs and kwargs[arg] is not None:
|
||||
data['healthmonitor'][arg] = kwargs[arg]
|
||||
|
||||
hm_req = self.new_create_request('healthmonitors', data, fmt=fmt)
|
||||
hm_res = hm_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(expected_res_status, hm_res.status_int)
|
||||
|
||||
return hm_res
|
||||
|
||||
def _add_optional_args(self, optional_args, data, **kwargs):
|
||||
for arg in optional_args:
|
||||
if arg in kwargs and kwargs[arg] is not None:
|
||||
data[arg] = kwargs[arg]
|
||||
|
||||
def _get_l7policy_optional_args(self):
|
||||
return ('name', 'description', 'redirect_pool_id',
|
||||
'redirect_url', 'admin_state_up', 'position')
|
||||
|
||||
def _create_l7policy(self, fmt, listener_id, action,
|
||||
expected_res_status=None, **kwargs):
|
||||
data = {'l7policy': {'listener_id': listener_id,
|
||||
'action': action,
|
||||
'tenant_id': self._tenant_id}}
|
||||
|
||||
optional_args = self._get_l7policy_optional_args()
|
||||
self._add_optional_args(optional_args, data['l7policy'], **kwargs)
|
||||
|
||||
l7policy_req = self.new_create_request('l7policies', data, fmt)
|
||||
l7policy_res = l7policy_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(l7policy_res.status_int, expected_res_status)
|
||||
|
||||
return l7policy_res
|
||||
|
||||
def _get_l7rule_optional_args(self):
|
||||
return ('invert', 'key', 'admin_state_up')
|
||||
|
||||
def _create_l7policy_rule(self, fmt, l7policy_id, type, compare_type,
|
||||
value, expected_res_status=None, **kwargs):
|
||||
data = {'rule': {'type': type,
|
||||
'compare_type': compare_type,
|
||||
'value': value,
|
||||
'tenant_id': self._tenant_id}}
|
||||
|
||||
optional_args = self._get_l7rule_optional_args()
|
||||
self._add_optional_args(optional_args, data['rule'], **kwargs)
|
||||
|
||||
rule_req = self.new_create_request('l7policies', data, fmt,
|
||||
id=l7policy_id,
|
||||
subresource='rules')
|
||||
rule_res = rule_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(rule_res.status_int, expected_res_status)
|
||||
|
||||
return rule_res
|
||||
|
||||
@contextlib.contextmanager
|
||||
def loadbalancer(self, fmt=None, subnet=None, no_delete=False, **kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
|
||||
with test_db_base_plugin_v2.optional_ctx(
|
||||
subnet, self.subnet) as tmp_subnet:
|
||||
|
||||
res = self._create_loadbalancer(fmt,
|
||||
tmp_subnet['subnet']['id'],
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
exc = webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") %
|
||||
res.status_int
|
||||
)
|
||||
exc.code = res.status_int
|
||||
exc.status_code = res.status_int
|
||||
raise exc
|
||||
lb = self.deserialize(fmt or self.fmt, res)
|
||||
yield lb
|
||||
if not no_delete:
|
||||
self._delete('loadbalancers', lb['loadbalancer']['id'])
|
||||
|
||||
@contextlib.contextmanager
|
||||
def graph(self, fmt=None, subnet=None, no_delete=False, **kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
|
||||
with test_db_base_plugin_v2.optional_ctx(
|
||||
subnet, self.subnet) as tmp_subnet:
|
||||
|
||||
res = self._create_graph(fmt, tmp_subnet['subnet']['id'],
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
exc = webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") %
|
||||
res.status_int
|
||||
)
|
||||
exc.code = res.status_int
|
||||
exc.status_code = res.status_int
|
||||
raise exc
|
||||
graph = self.deserialize(fmt or self.fmt, res)
|
||||
yield graph
|
||||
if not no_delete:
|
||||
# delete loadbalancer children if this was a loadbalancer
|
||||
# graph create call
|
||||
lb = graph['graph']['loadbalancer']
|
||||
for listener in lb.get('listeners', []):
|
||||
pool = listener.get('default_pool')
|
||||
if pool:
|
||||
hm = pool.get('healthmonitor')
|
||||
if hm:
|
||||
self._delete('healthmonitors', hm['id'])
|
||||
members = pool.get('members', [])
|
||||
for member in members:
|
||||
self._delete('pools', pool['id'],
|
||||
subresource='members',
|
||||
sub_id=member['id'])
|
||||
self._delete('pools', pool['id'])
|
||||
policies = listener.get('l7policies', [])
|
||||
for policy in policies:
|
||||
r_pool = policy.get('redirect_pool')
|
||||
if r_pool:
|
||||
r_hm = r_pool.get('healthmonitor')
|
||||
if r_hm:
|
||||
self._delete('healthmonitors', r_hm['id'])
|
||||
r_members = r_pool.get('members', [])
|
||||
for r_member in r_members:
|
||||
self._delete('pools', r_pool['id'],
|
||||
subresource='members',
|
||||
sub_id=r_member['id'])
|
||||
self._delete('pools', r_pool['id'])
|
||||
self._delete('l7policies', policy['id'])
|
||||
self._delete('listeners', listener['id'])
|
||||
self._delete('loadbalancers', lb['id'])
|
||||
|
||||
@contextlib.contextmanager
|
||||
def listener(self, fmt=None, protocol='HTTP', loadbalancer_id=None,
|
||||
protocol_port=80, default_pool_id=None, no_delete=False,
|
||||
**kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
|
||||
if loadbalancer_id and default_pool_id:
|
||||
res = self._create_listener(fmt, protocol, protocol_port,
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
default_pool_id=default_pool_id,
|
||||
**kwargs)
|
||||
elif loadbalancer_id:
|
||||
res = self._create_listener(fmt, protocol, protocol_port,
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
**kwargs)
|
||||
else:
|
||||
res = self._create_listener(fmt, protocol, protocol_port,
|
||||
default_pool_id=default_pool_id,
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") % res.status_int
|
||||
)
|
||||
|
||||
listener = self.deserialize(fmt or self.fmt, res)
|
||||
yield listener
|
||||
if not no_delete:
|
||||
self._delete('listeners', listener['listener']['id'])
|
||||
|
||||
@contextlib.contextmanager
|
||||
def pool(self, fmt=None, protocol='HTTP', lb_algorithm='ROUND_ROBIN',
|
||||
no_delete=False, listener_id=None,
|
||||
loadbalancer_id=None, **kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
|
||||
if listener_id and loadbalancer_id:
|
||||
res = self._create_pool(fmt,
|
||||
protocol=protocol,
|
||||
lb_algorithm=lb_algorithm,
|
||||
listener_id=listener_id,
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
**kwargs)
|
||||
elif listener_id:
|
||||
res = self._create_pool(fmt,
|
||||
protocol=protocol,
|
||||
lb_algorithm=lb_algorithm,
|
||||
listener_id=listener_id,
|
||||
**kwargs)
|
||||
else:
|
||||
res = self._create_pool(fmt,
|
||||
protocol=protocol,
|
||||
lb_algorithm=lb_algorithm,
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") % res.status_int
|
||||
)
|
||||
|
||||
pool = self.deserialize(fmt or self.fmt, res)
|
||||
yield pool
|
||||
if not no_delete:
|
||||
self._delete('pools', pool['pool']['id'])
|
||||
|
||||
@contextlib.contextmanager
|
||||
def member(self, fmt=None, pool_id='pool1id', address='127.0.0.1',
|
||||
protocol_port=80, subnet=None, no_delete=False,
|
||||
**kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
subnet = subnet or self.test_subnet
|
||||
with test_db_base_plugin_v2.optional_ctx(
|
||||
subnet, self.subnet) as tmp_subnet:
|
||||
|
||||
res = self._create_member(fmt,
|
||||
pool_id=pool_id,
|
||||
address=address,
|
||||
protocol_port=protocol_port,
|
||||
subnet_id=tmp_subnet['subnet']['id'],
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") % res.status_int
|
||||
)
|
||||
|
||||
member = self.deserialize(fmt or self.fmt, res)
|
||||
yield member
|
||||
if not no_delete:
|
||||
self._delete('pools', id=pool_id, subresource='members',
|
||||
sub_id=member['member']['id'])
|
||||
|
||||
@contextlib.contextmanager
|
||||
def healthmonitor(self, fmt=None, pool_id='pool1id', type='TCP', delay=1,
|
||||
timeout=1, max_retries=2, no_delete=False, **kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
|
||||
res = self._create_healthmonitor(fmt,
|
||||
pool_id=pool_id,
|
||||
type=type,
|
||||
delay=delay,
|
||||
timeout=timeout,
|
||||
max_retries=max_retries,
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") % res.status_int
|
||||
)
|
||||
|
||||
healthmonitor = self.deserialize(fmt or self.fmt, res)
|
||||
yield healthmonitor
|
||||
if not no_delete:
|
||||
del_req = self.new_delete_request(
|
||||
'healthmonitors', fmt=fmt,
|
||||
id=healthmonitor['healthmonitor']['id'])
|
||||
del_res = del_req.get_response(self.ext_api)
|
||||
self.assertEqual(webob.exc.HTTPNoContent.code, del_res.status_int)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def l7policy(self, listener_id, fmt=None,
|
||||
action=lb_const.L7_POLICY_ACTION_REJECT,
|
||||
no_delete=False, **kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
|
||||
res = self._create_l7policy(fmt,
|
||||
listener_id=listener_id,
|
||||
action=action,
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") % res.status_int
|
||||
)
|
||||
|
||||
l7policy = self.deserialize(fmt or self.fmt, res)
|
||||
yield l7policy
|
||||
if not no_delete:
|
||||
self.plugin.db.update_status(context.get_admin_context(),
|
||||
models.L7Policy,
|
||||
l7policy['l7policy']['id'],
|
||||
n_constants.ACTIVE)
|
||||
del_req = self.new_delete_request(
|
||||
'l7policies',
|
||||
fmt=fmt,
|
||||
id=l7policy['l7policy']['id'])
|
||||
del_res = del_req.get_response(self.ext_api)
|
||||
self.assertEqual(del_res.status_int,
|
||||
webob.exc.HTTPNoContent.code)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def l7policy_rule(self, l7policy_id, fmt=None, value='value1',
|
||||
type=lb_const.L7_RULE_TYPE_HOST_NAME,
|
||||
compare_type=lb_const.L7_RULE_COMPARE_TYPE_EQUAL_TO,
|
||||
no_delete=False, **kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
res = self._create_l7policy_rule(fmt,
|
||||
l7policy_id=l7policy_id,
|
||||
type=type,
|
||||
compare_type=compare_type,
|
||||
value=value,
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") % res.status_int
|
||||
)
|
||||
|
||||
rule = self.deserialize(fmt or self.fmt, res)
|
||||
yield rule
|
||||
if not no_delete:
|
||||
self.plugin.db.update_status(context.get_admin_context(),
|
||||
models.L7Rule,
|
||||
rule['rule']['id'],
|
||||
n_constants.ACTIVE)
|
||||
del_req = self.new_delete_request(
|
||||
'l7policies',
|
||||
fmt=fmt,
|
||||
id=l7policy_id,
|
||||
subresource='rules',
|
||||
sub_id=rule['rule']['id'])
|
||||
del_res = del_req.get_response(self.ext_api)
|
||||
self.assertEqual(del_res.status_int,
|
||||
webob.exc.HTTPNoContent.code)
|
||||
|
||||
|
||||
class ExtendedPluginAwareExtensionManager(object):
|
||||
def __init__(self, extension_aliases):
|
||||
self.extension_aliases = extension_aliases
|
||||
|
||||
def get_resources(self):
|
||||
extensions_list = []
|
||||
if 'shared_pools' in self.extension_aliases:
|
||||
extensions_list.append(sharedpools)
|
||||
if 'l7' in self.extension_aliases:
|
||||
extensions_list.append(l7)
|
||||
if 'lb-graph' in self.extension_aliases:
|
||||
extensions_list.append(lb_graph)
|
||||
if 'lb_network_vip' in self.extension_aliases:
|
||||
extensions_list.append(lb_network_vip)
|
||||
if 'hm_max_retries_down' in self.extension_aliases:
|
||||
extensions_list.append(healthmonitor_max_retries_down)
|
||||
for extension in extensions_list:
|
||||
if 'RESOURCE_ATTRIBUTE_MAP' in extension.__dict__:
|
||||
loadbalancerv2.RESOURCE_ATTRIBUTE_MAP.update(
|
||||
extension.RESOURCE_ATTRIBUTE_MAP)
|
||||
if 'SUB_RESOURCE_ATTRIBUTE_MAP' in extension.__dict__:
|
||||
loadbalancerv2.SUB_RESOURCE_ATTRIBUTE_MAP.update(
|
||||
extension.SUB_RESOURCE_ATTRIBUTE_MAP)
|
||||
if 'EXTENDED_ATTRIBUTES_2_0' in extension.__dict__:
|
||||
for key in loadbalancerv2.RESOURCE_ATTRIBUTE_MAP.keys():
|
||||
loadbalancerv2.RESOURCE_ATTRIBUTE_MAP[key].update(
|
||||
extension.EXTENDED_ATTRIBUTES_2_0.get(key, {}))
|
||||
return loadbalancerv2.Loadbalancerv2.get_resources()
|
||||
|
||||
def get_actions(self):
|
||||
return []
|
||||
|
||||
def get_request_extensions(self):
|
||||
return []
|
||||
|
||||
|
||||
class LbaasPluginDbTestCase(LbaasTestMixin, base.NeutronDbPluginV2TestCase):
|
||||
class LbaasPluginDbTestCase(util.LbaasTestMixin,
|
||||
base.NeutronDbPluginV2TestCase):
|
||||
def setUp(self, core_plugin=None, lb_plugin=None, lbaas_provider=None,
|
||||
ext_mgr=None):
|
||||
service_plugins = {'lb_plugin_name': DB_LB_PLUGIN_CLASS}
|
||||
|
@ -595,7 +91,7 @@ class LbaasPluginDbTestCase(LbaasTestMixin, base.NeutronDbPluginV2TestCase):
|
|||
# finding algorithm below will find the loadbalancerv2
|
||||
# extension and fail to initizlize the main API router with
|
||||
# extensions' resources
|
||||
ext_mgr = ExtendedPluginAwareExtensionManager(
|
||||
ext_mgr = util.ExtendedPluginAwareExtensionManager(
|
||||
LBPlugin.supported_extension_aliases)
|
||||
|
||||
app = config.load_paste_app('extensions_test_app')
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,529 @@
|
|||
# Copyright 2017, Rackspace US, 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.
|
||||
|
||||
import contextlib
|
||||
|
||||
from neutron.tests.unit.db import test_db_base_plugin_v2
|
||||
from neutron_lib import constants
|
||||
from neutron_lib import context
|
||||
import webob.exc
|
||||
|
||||
from neutron_lbaas._i18n import _
|
||||
from neutron_lbaas.db.loadbalancer import models
|
||||
from neutron_lbaas.extensions import healthmonitor_max_retries_down
|
||||
from neutron_lbaas.extensions import l7
|
||||
from neutron_lbaas.extensions import lb_graph
|
||||
from neutron_lbaas.extensions import lb_network_vip
|
||||
from neutron_lbaas.extensions import loadbalancerv2
|
||||
from neutron_lbaas.extensions import sharedpools
|
||||
from neutron_lbaas.services.loadbalancer import constants as lb_const
|
||||
|
||||
|
||||
class ExtendedPluginAwareExtensionManager(object):
|
||||
def __init__(self, extension_aliases):
|
||||
self.extension_aliases = extension_aliases
|
||||
|
||||
def get_resources(self):
|
||||
extensions_list = []
|
||||
if 'shared_pools' in self.extension_aliases:
|
||||
extensions_list.append(sharedpools)
|
||||
if 'l7' in self.extension_aliases:
|
||||
extensions_list.append(l7)
|
||||
if 'lb-graph' in self.extension_aliases:
|
||||
extensions_list.append(lb_graph)
|
||||
if 'lb_network_vip' in self.extension_aliases:
|
||||
extensions_list.append(lb_network_vip)
|
||||
if 'hm_max_retries_down' in self.extension_aliases:
|
||||
extensions_list.append(healthmonitor_max_retries_down)
|
||||
for extension in extensions_list:
|
||||
if 'RESOURCE_ATTRIBUTE_MAP' in extension.__dict__:
|
||||
loadbalancerv2.RESOURCE_ATTRIBUTE_MAP.update(
|
||||
extension.RESOURCE_ATTRIBUTE_MAP)
|
||||
if 'SUB_RESOURCE_ATTRIBUTE_MAP' in extension.__dict__:
|
||||
loadbalancerv2.SUB_RESOURCE_ATTRIBUTE_MAP.update(
|
||||
extension.SUB_RESOURCE_ATTRIBUTE_MAP)
|
||||
if 'EXTENDED_ATTRIBUTES_2_0' in extension.__dict__:
|
||||
for key in loadbalancerv2.RESOURCE_ATTRIBUTE_MAP.keys():
|
||||
loadbalancerv2.RESOURCE_ATTRIBUTE_MAP[key].update(
|
||||
extension.EXTENDED_ATTRIBUTES_2_0.get(key, {}))
|
||||
return loadbalancerv2.Loadbalancerv2.get_resources()
|
||||
|
||||
def get_actions(self):
|
||||
return []
|
||||
|
||||
def get_request_extensions(self):
|
||||
return []
|
||||
|
||||
|
||||
class LbaasTestMixin(object):
|
||||
resource_keys = list(loadbalancerv2.RESOURCE_ATTRIBUTE_MAP.keys())
|
||||
resource_keys.extend(l7.RESOURCE_ATTRIBUTE_MAP.keys())
|
||||
resource_keys.extend(lb_graph.RESOURCE_ATTRIBUTE_MAP.keys())
|
||||
resource_keys.extend(lb_network_vip.EXTENDED_ATTRIBUTES_2_0.keys())
|
||||
resource_keys.extend(healthmonitor_max_retries_down.
|
||||
EXTENDED_ATTRIBUTES_2_0.keys())
|
||||
resource_prefix_map = dict(
|
||||
(k, loadbalancerv2.LOADBALANCERV2_PREFIX)
|
||||
for k in resource_keys)
|
||||
|
||||
def _get_loadbalancer_optional_args(self):
|
||||
return ('description', 'vip_address', 'admin_state_up', 'name',
|
||||
'listeners', 'vip_network_id', 'vip_subnet_id')
|
||||
|
||||
def _create_loadbalancer(self, fmt, subnet_id,
|
||||
expected_res_status=None, **kwargs):
|
||||
data = {'loadbalancer': {'vip_subnet_id': subnet_id,
|
||||
'tenant_id': self._tenant_id}}
|
||||
args = self._get_loadbalancer_optional_args()
|
||||
for arg in args:
|
||||
if arg in kwargs:
|
||||
if kwargs[arg] is not None:
|
||||
data['loadbalancer'][arg] = kwargs[arg]
|
||||
else:
|
||||
data['loadbalancer'].pop(arg, None)
|
||||
|
||||
lb_req = self.new_create_request('loadbalancers', data, fmt)
|
||||
lb_res = lb_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(expected_res_status, lb_res.status_int)
|
||||
|
||||
return lb_res
|
||||
|
||||
def _create_graph(self, fmt, subnet_id, expected_res_status=None,
|
||||
**kwargs):
|
||||
data = {'vip_subnet_id': subnet_id, 'tenant_id': self._tenant_id}
|
||||
args = self._get_loadbalancer_optional_args()
|
||||
for arg in args:
|
||||
if arg in kwargs and kwargs[arg] is not None:
|
||||
data[arg] = kwargs[arg]
|
||||
|
||||
data = {'graph': {'loadbalancer': data, 'tenant_id': self._tenant_id}}
|
||||
lb_req = self.new_create_request('graphs', data, fmt)
|
||||
lb_res = lb_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(expected_res_status, lb_res.status_int)
|
||||
|
||||
return lb_res
|
||||
|
||||
def _get_listener_optional_args(self):
|
||||
return ('name', 'description', 'default_pool_id', 'loadbalancer_id',
|
||||
'connection_limit', 'admin_state_up',
|
||||
'default_tls_container_ref', 'sni_container_refs')
|
||||
|
||||
def _create_listener(self, fmt, protocol, protocol_port,
|
||||
loadbalancer_id=None, default_pool_id=None,
|
||||
expected_res_status=None, **kwargs):
|
||||
data = {'listener': {'protocol': protocol,
|
||||
'protocol_port': protocol_port,
|
||||
'tenant_id': self._tenant_id}}
|
||||
if loadbalancer_id:
|
||||
data['listener']['loadbalancer_id'] = loadbalancer_id
|
||||
if default_pool_id:
|
||||
data['listener']['default_pool_id'] = default_pool_id
|
||||
|
||||
args = self._get_listener_optional_args()
|
||||
for arg in args:
|
||||
if arg in kwargs and kwargs[arg] is not None:
|
||||
data['listener'][arg] = kwargs[arg]
|
||||
|
||||
listener_req = self.new_create_request('listeners', data, fmt)
|
||||
listener_res = listener_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(expected_res_status, listener_res.status_int)
|
||||
|
||||
return listener_res
|
||||
|
||||
def _get_pool_optional_args(self):
|
||||
return 'name', 'description', 'admin_state_up', 'session_persistence'
|
||||
|
||||
def _create_pool(self, fmt, protocol, lb_algorithm, listener_id=None,
|
||||
loadbalancer_id=None, expected_res_status=None, **kwargs):
|
||||
data = {'pool': {'protocol': protocol,
|
||||
'lb_algorithm': lb_algorithm,
|
||||
'tenant_id': self._tenant_id}}
|
||||
if listener_id:
|
||||
data['pool']['listener_id'] = listener_id
|
||||
if loadbalancer_id:
|
||||
data['pool']['loadbalancer_id'] = loadbalancer_id
|
||||
|
||||
args = self._get_pool_optional_args()
|
||||
for arg in args:
|
||||
if arg in kwargs and kwargs[arg] is not None:
|
||||
data['pool'][arg] = kwargs[arg]
|
||||
|
||||
pool_req = self.new_create_request('pools', data, fmt)
|
||||
pool_res = pool_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(expected_res_status, pool_res.status_int)
|
||||
|
||||
return pool_res
|
||||
|
||||
def _get_member_optional_args(self):
|
||||
return 'weight', 'admin_state_up', 'name'
|
||||
|
||||
def _create_member(self, fmt, pool_id, address, protocol_port, subnet_id,
|
||||
expected_res_status=None, **kwargs):
|
||||
data = {'member': {'address': address,
|
||||
'protocol_port': protocol_port,
|
||||
'subnet_id': subnet_id,
|
||||
'tenant_id': self._tenant_id}}
|
||||
|
||||
args = self._get_member_optional_args()
|
||||
for arg in args:
|
||||
if arg in kwargs and kwargs[arg] is not None:
|
||||
data['member'][arg] = kwargs[arg]
|
||||
member_req = self.new_create_request('pools',
|
||||
data,
|
||||
fmt=fmt,
|
||||
id=pool_id,
|
||||
subresource='members')
|
||||
member_res = member_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(expected_res_status, member_res.status_int)
|
||||
|
||||
return member_res
|
||||
|
||||
def _get_healthmonitor_optional_args(self):
|
||||
return ('weight', 'admin_state_up', 'expected_codes', 'url_path',
|
||||
'http_method', 'name', 'max_retries_down')
|
||||
|
||||
def _create_healthmonitor(self, fmt, pool_id, type, delay, timeout,
|
||||
max_retries, expected_res_status=None, **kwargs):
|
||||
data = {'healthmonitor': {'type': type,
|
||||
'delay': delay,
|
||||
'timeout': timeout,
|
||||
'max_retries': max_retries,
|
||||
'pool_id': pool_id,
|
||||
'tenant_id': self._tenant_id}}
|
||||
|
||||
args = self._get_healthmonitor_optional_args()
|
||||
for arg in args:
|
||||
if arg in kwargs and kwargs[arg] is not None:
|
||||
data['healthmonitor'][arg] = kwargs[arg]
|
||||
|
||||
hm_req = self.new_create_request('healthmonitors', data, fmt=fmt)
|
||||
hm_res = hm_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(expected_res_status, hm_res.status_int)
|
||||
|
||||
return hm_res
|
||||
|
||||
def _add_optional_args(self, optional_args, data, **kwargs):
|
||||
for arg in optional_args:
|
||||
if arg in kwargs and kwargs[arg] is not None:
|
||||
data[arg] = kwargs[arg]
|
||||
|
||||
def _get_l7policy_optional_args(self):
|
||||
return ('name', 'description', 'redirect_pool_id',
|
||||
'redirect_url', 'admin_state_up', 'position')
|
||||
|
||||
def _create_l7policy(self, fmt, listener_id, action,
|
||||
expected_res_status=None, **kwargs):
|
||||
data = {'l7policy': {'listener_id': listener_id,
|
||||
'action': action,
|
||||
'tenant_id': self._tenant_id}}
|
||||
|
||||
optional_args = self._get_l7policy_optional_args()
|
||||
self._add_optional_args(optional_args, data['l7policy'], **kwargs)
|
||||
|
||||
l7policy_req = self.new_create_request('l7policies', data, fmt)
|
||||
l7policy_res = l7policy_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(l7policy_res.status_int, expected_res_status)
|
||||
|
||||
return l7policy_res
|
||||
|
||||
def _get_l7rule_optional_args(self):
|
||||
return ('invert', 'key', 'admin_state_up')
|
||||
|
||||
def _create_l7policy_rule(self, fmt, l7policy_id, type, compare_type,
|
||||
value, expected_res_status=None, **kwargs):
|
||||
data = {'rule': {'type': type,
|
||||
'compare_type': compare_type,
|
||||
'value': value,
|
||||
'tenant_id': self._tenant_id}}
|
||||
|
||||
optional_args = self._get_l7rule_optional_args()
|
||||
self._add_optional_args(optional_args, data['rule'], **kwargs)
|
||||
|
||||
rule_req = self.new_create_request('l7policies', data, fmt,
|
||||
id=l7policy_id,
|
||||
subresource='rules')
|
||||
rule_res = rule_req.get_response(self.ext_api)
|
||||
if expected_res_status:
|
||||
self.assertEqual(rule_res.status_int, expected_res_status)
|
||||
|
||||
return rule_res
|
||||
|
||||
@contextlib.contextmanager
|
||||
def loadbalancer(self, fmt=None, subnet=None, no_delete=False, **kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
|
||||
with test_db_base_plugin_v2.optional_ctx(
|
||||
subnet, self.subnet) as tmp_subnet:
|
||||
|
||||
res = self._create_loadbalancer(fmt,
|
||||
tmp_subnet['subnet']['id'],
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
exc = webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") %
|
||||
res.status_int)
|
||||
exc.code = res.status_int
|
||||
exc.status_code = res.status_int
|
||||
raise exc
|
||||
lb = self.deserialize(fmt or self.fmt, res)
|
||||
yield lb
|
||||
if not no_delete:
|
||||
self._delete('loadbalancers', lb['loadbalancer']['id'])
|
||||
|
||||
@contextlib.contextmanager
|
||||
def graph(self, fmt=None, subnet=None, no_delete=False, **kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
|
||||
with test_db_base_plugin_v2.optional_ctx(
|
||||
subnet, self.subnet) as tmp_subnet:
|
||||
|
||||
res = self._create_graph(fmt, tmp_subnet['subnet']['id'],
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
exc = webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") %
|
||||
res.status_int
|
||||
)
|
||||
exc.code = res.status_int
|
||||
exc.status_code = res.status_int
|
||||
raise exc
|
||||
graph = self.deserialize(fmt or self.fmt, res)
|
||||
yield graph
|
||||
if not no_delete:
|
||||
# delete loadbalancer children if this was a loadbalancer
|
||||
# graph create call
|
||||
lb = graph['graph']['loadbalancer']
|
||||
for listener in lb.get('listeners', []):
|
||||
pool = listener.get('default_pool')
|
||||
if pool:
|
||||
hm = pool.get('healthmonitor')
|
||||
if hm:
|
||||
self._delete('healthmonitors', hm['id'])
|
||||
members = pool.get('members', [])
|
||||
for member in members:
|
||||
self._delete('pools', pool['id'],
|
||||
subresource='members',
|
||||
sub_id=member['id'])
|
||||
self._delete('pools', pool['id'])
|
||||
policies = listener.get('l7policies', [])
|
||||
for policy in policies:
|
||||
r_pool = policy.get('redirect_pool')
|
||||
if r_pool:
|
||||
r_hm = r_pool.get('healthmonitor')
|
||||
if r_hm:
|
||||
self._delete('healthmonitors', r_hm['id'])
|
||||
r_members = r_pool.get('members', [])
|
||||
for r_member in r_members:
|
||||
self._delete('pools', r_pool['id'],
|
||||
subresource='members',
|
||||
sub_id=r_member['id'])
|
||||
self._delete('pools', r_pool['id'])
|
||||
self._delete('l7policies', policy['id'])
|
||||
self._delete('listeners', listener['id'])
|
||||
self._delete('loadbalancers', lb['id'])
|
||||
|
||||
@contextlib.contextmanager
|
||||
def listener(self, fmt=None, protocol='HTTP', loadbalancer_id=None,
|
||||
protocol_port=80, default_pool_id=None, no_delete=False,
|
||||
**kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
|
||||
if loadbalancer_id and default_pool_id:
|
||||
res = self._create_listener(fmt, protocol, protocol_port,
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
default_pool_id=default_pool_id,
|
||||
**kwargs)
|
||||
elif loadbalancer_id:
|
||||
res = self._create_listener(fmt, protocol, protocol_port,
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
**kwargs)
|
||||
else:
|
||||
res = self._create_listener(fmt, protocol, protocol_port,
|
||||
default_pool_id=default_pool_id,
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") % res.status_int
|
||||
)
|
||||
|
||||
listener = self.deserialize(fmt or self.fmt, res)
|
||||
yield listener
|
||||
if not no_delete:
|
||||
self._delete('listeners', listener['listener']['id'])
|
||||
|
||||
@contextlib.contextmanager
|
||||
def pool(self, fmt=None, protocol='HTTP', lb_algorithm='ROUND_ROBIN',
|
||||
no_delete=False, listener_id=None,
|
||||
loadbalancer_id=None, **kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
|
||||
if listener_id and loadbalancer_id:
|
||||
res = self._create_pool(fmt,
|
||||
protocol=protocol,
|
||||
lb_algorithm=lb_algorithm,
|
||||
listener_id=listener_id,
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
**kwargs)
|
||||
elif listener_id:
|
||||
res = self._create_pool(fmt,
|
||||
protocol=protocol,
|
||||
lb_algorithm=lb_algorithm,
|
||||
listener_id=listener_id,
|
||||
**kwargs)
|
||||
else:
|
||||
res = self._create_pool(fmt,
|
||||
protocol=protocol,
|
||||
lb_algorithm=lb_algorithm,
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") % res.status_int
|
||||
)
|
||||
|
||||
pool = self.deserialize(fmt or self.fmt, res)
|
||||
yield pool
|
||||
if not no_delete:
|
||||
self._delete('pools', pool['pool']['id'])
|
||||
|
||||
@contextlib.contextmanager
|
||||
def member(self, fmt=None, pool_id='pool1id', address='127.0.0.1',
|
||||
protocol_port=80, subnet=None, no_delete=False,
|
||||
**kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
subnet = subnet or self.test_subnet
|
||||
with test_db_base_plugin_v2.optional_ctx(
|
||||
subnet, self.subnet) as tmp_subnet:
|
||||
|
||||
res = self._create_member(fmt,
|
||||
pool_id=pool_id,
|
||||
address=address,
|
||||
protocol_port=protocol_port,
|
||||
subnet_id=tmp_subnet['subnet']['id'],
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") % res.status_int
|
||||
)
|
||||
|
||||
member = self.deserialize(fmt or self.fmt, res)
|
||||
yield member
|
||||
if not no_delete:
|
||||
self._delete('pools', id=pool_id, subresource='members',
|
||||
sub_id=member['member']['id'])
|
||||
|
||||
@contextlib.contextmanager
|
||||
def healthmonitor(self, fmt=None, pool_id='pool1id', type='TCP', delay=1,
|
||||
timeout=1, max_retries=2, no_delete=False, **kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
|
||||
res = self._create_healthmonitor(fmt,
|
||||
pool_id=pool_id,
|
||||
type=type,
|
||||
delay=delay,
|
||||
timeout=timeout,
|
||||
max_retries=max_retries,
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") % res.status_int
|
||||
)
|
||||
|
||||
healthmonitor = self.deserialize(fmt or self.fmt, res)
|
||||
yield healthmonitor
|
||||
if not no_delete:
|
||||
del_req = self.new_delete_request(
|
||||
'healthmonitors', fmt=fmt,
|
||||
id=healthmonitor['healthmonitor']['id'])
|
||||
del_res = del_req.get_response(self.ext_api)
|
||||
self.assertEqual(webob.exc.HTTPNoContent.code, del_res.status_int)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def l7policy(self, listener_id, fmt=None,
|
||||
action=lb_const.L7_POLICY_ACTION_REJECT,
|
||||
no_delete=False, **kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
|
||||
res = self._create_l7policy(fmt,
|
||||
listener_id=listener_id,
|
||||
action=action,
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") % res.status_int
|
||||
)
|
||||
|
||||
l7policy = self.deserialize(fmt or self.fmt, res)
|
||||
yield l7policy
|
||||
if not no_delete:
|
||||
self.plugin.db.update_status(context.get_admin_context(),
|
||||
models.L7Policy,
|
||||
l7policy['l7policy']['id'],
|
||||
constants.ACTIVE)
|
||||
del_req = self.new_delete_request(
|
||||
'l7policies',
|
||||
fmt=fmt,
|
||||
id=l7policy['l7policy']['id'])
|
||||
del_res = del_req.get_response(self.ext_api)
|
||||
self.assertEqual(del_res.status_int,
|
||||
webob.exc.HTTPNoContent.code)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def l7policy_rule(self, l7policy_id, fmt=None, value='value1',
|
||||
type=lb_const.L7_RULE_TYPE_HOST_NAME,
|
||||
compare_type=lb_const.L7_RULE_COMPARE_TYPE_EQUAL_TO,
|
||||
no_delete=False, **kwargs):
|
||||
if not fmt:
|
||||
fmt = self.fmt
|
||||
res = self._create_l7policy_rule(fmt,
|
||||
l7policy_id=l7policy_id,
|
||||
type=type,
|
||||
compare_type=compare_type,
|
||||
value=value,
|
||||
**kwargs)
|
||||
if res.status_int >= webob.exc.HTTPClientError.code:
|
||||
raise webob.exc.HTTPClientError(
|
||||
explanation=_("Unexpected error code: %s") % res.status_int
|
||||
)
|
||||
|
||||
rule = self.deserialize(fmt or self.fmt, res)
|
||||
yield rule
|
||||
if not no_delete:
|
||||
self.plugin.db.update_status(context.get_admin_context(),
|
||||
models.L7Rule,
|
||||
rule['rule']['id'],
|
||||
constants.ACTIVE)
|
||||
del_req = self.new_delete_request(
|
||||
'l7policies',
|
||||
fmt=fmt,
|
||||
id=l7policy_id,
|
||||
subresource='rules',
|
||||
sub_id=rule['rule']['id'])
|
||||
del_res = del_req.get_response(self.ext_api)
|
||||
self.assertEqual(del_res.status_int,
|
||||
webob.exc.HTTPNoContent.code)
|
|
@ -38,6 +38,7 @@ from neutron_lbaas.extensions import lbaas_agentschedulerv2
|
|||
from neutron_lbaas.services.loadbalancer import constants as lb_const
|
||||
from neutron_lbaas.tests import base
|
||||
from neutron_lbaas.tests.unit.db.loadbalancer import test_db_loadbalancerv2
|
||||
from neutron_lbaas.tests.unit.db.loadbalancer import util
|
||||
|
||||
LBAAS_HOSTA = 'hosta'
|
||||
extensions_path = ':'.join(neutron.tests.unit.extensions.__path__)
|
||||
|
@ -65,7 +66,7 @@ class AgentSchedulerTestMixIn(test_agentschedulers_db.AgentSchedulerTestMixIn):
|
|||
|
||||
class LBaaSAgentSchedulerTestCase(test_agent.AgentDBTestMixIn,
|
||||
AgentSchedulerTestMixIn,
|
||||
test_db_loadbalancerv2.LbaasTestMixin,
|
||||
util.LbaasTestMixin,
|
||||
base.NeutronDbPluginV2TestCase):
|
||||
fmt = 'json'
|
||||
plugin_str = 'neutron.plugins.ml2.plugin.Ml2Plugin'
|
||||
|
|
|
@ -36,6 +36,7 @@ loadbalancer_schedulers =
|
|||
neutron_lbaas.agent_scheduler.ChanceScheduler = neutron_lbaas.agent_scheduler:ChanceScheduler
|
||||
neutron.service_plugins =
|
||||
lbaasv2 = neutron_lbaas.services.loadbalancer.plugin:LoadBalancerPluginv2
|
||||
lbaasv2-proxy = neutron_lbaas.services.loadbalancer.proxy_plugin:LoadBalancerProxyPluginv2
|
||||
neutron.db.alembic_migrations =
|
||||
neutron-lbaas = neutron_lbaas.db.migration:alembic_migrations
|
||||
neutron_lbaas.cert_manager.backend =
|
||||
|
|
Loading…
Reference in New Issue