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:
German Eichberger 2017-01-10 14:04:57 -05:00 committed by Michael Johnson
parent e890821ba0
commit 0c76484a50
6 changed files with 2278 additions and 513 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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'

View File

@ -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 =