Merge "LBaaS new object model logging no-op driver"
This commit is contained in:
commit
6850e75304
@ -577,3 +577,5 @@ service_provider=VPN:openswan:neutron.services.vpn.service_drivers.ipsec.IPsecVP
|
||||
# service_provider=VPN:cisco:neutron.services.vpn.service_drivers.cisco_ipsec.CiscoCsrIPsecVPNDriver:default
|
||||
# Uncomment the line below to use Embrane heleos as Load Balancer service provider.
|
||||
# service_provider=LOADBALANCER:Embrane:neutron.services.loadbalancer.drivers.embrane.driver.EmbraneLbaas:default
|
||||
# Uncomment the following line to test the LBaaS v2 API _WITHOUT_ a real backend
|
||||
# service_provider = LOADBALANCER:LoggingNoop:neutron.services.loadbalancer.drivers.logging_noop.driver.LoggingNoopLoadBalancerDriver:default
|
||||
|
@ -18,6 +18,14 @@ import abc
|
||||
|
||||
import six
|
||||
|
||||
#
|
||||
# DEPRECATION WARNING. THIS ABSTRACT DRIVER IS FOR THE LBAAS V1 OBJECT
|
||||
# MODEL AND SHOULD NO LONGER BE USED TO CREATE DRIVERS.
|
||||
#
|
||||
# PLEASE REFER TO driver_base.py and driver_mixins.py for the newest
|
||||
# lbaas driver base classes.
|
||||
#
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class LoadBalancerAbstractDriver(object):
|
||||
|
87
neutron/services/loadbalancer/drivers/driver_base.py
Normal file
87
neutron/services/loadbalancer/drivers/driver_base.py
Normal file
@ -0,0 +1,87 @@
|
||||
# Copyright 2014 A10 Networks
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron.db.loadbalancer import loadbalancer_db as lb_db
|
||||
from neutron.services.loadbalancer.drivers import driver_mixins
|
||||
|
||||
|
||||
class NotImplementedManager(object):
|
||||
"""Helper class to make any subclass of LBAbstractDriver explode if it
|
||||
is missing any of the required object managers.
|
||||
"""
|
||||
|
||||
def create(self, context, obj):
|
||||
raise NotImplementedError()
|
||||
|
||||
def update(self, context, old_obj, obj):
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete(self, context, obj):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class LoadBalancerBaseDriver(object):
|
||||
"""LBaaSv2 object model drivers should subclass LBAbstractDriver, and
|
||||
initialize the following manager classes to create, update, and delete
|
||||
the various load balancer objects.
|
||||
"""
|
||||
|
||||
load_balancer = NotImplementedManager()
|
||||
listener = NotImplementedManager()
|
||||
pool = NotImplementedManager()
|
||||
member = NotImplementedManager()
|
||||
health_monitor = NotImplementedManager()
|
||||
|
||||
def __init__(self, plugin):
|
||||
self.plugin = plugin
|
||||
|
||||
|
||||
class BaseLoadBalancerManager(driver_mixins.BaseRefreshMixin,
|
||||
driver_mixins.BaseStatsMixin,
|
||||
driver_mixins.BaseStatusUpdateMixin,
|
||||
driver_mixins.BaseManagerMixin):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(BaseLoadBalancerManager, self).__init__(driver)
|
||||
# TODO(dougw), use lb_db.LoadBalancer when v2 lbaas
|
||||
# TODO(dougw), get rid of __init__() in StatusHelperManager, and
|
||||
# the if is not None clauses; after fixing this next line,
|
||||
# it can become a mandatory variable for that subclass.
|
||||
self.model_class = None
|
||||
|
||||
|
||||
class BaseListenerManager(driver_mixins.BaseManagerMixin):
|
||||
pass
|
||||
|
||||
|
||||
class BasePoolManager(driver_mixins.BaseStatusUpdateMixin,
|
||||
driver_mixins.BaseManagerMixin):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(BasePoolManager, self).__init__(driver)
|
||||
self.model_class = lb_db.Pool
|
||||
|
||||
|
||||
class BaseMemberManager(driver_mixins.BaseStatusUpdateMixin,
|
||||
driver_mixins.BaseManagerMixin):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(BaseMemberManager, self).__init__(driver)
|
||||
self.model_class = lb_db.Member
|
||||
|
||||
|
||||
class BaseHealthMonitorManager(
|
||||
driver_mixins.BaseHealthMonitorStatusUpdateMixin,
|
||||
driver_mixins.BaseManagerMixin):
|
||||
pass
|
85
neutron/services/loadbalancer/drivers/driver_mixins.py
Normal file
85
neutron/services/loadbalancer/drivers/driver_mixins.py
Normal file
@ -0,0 +1,85 @@
|
||||
# Copyright 2014 A10 Networks
|
||||
#
|
||||
# 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 abc
|
||||
import six
|
||||
|
||||
from neutron.plugins.common import constants
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class BaseManagerMixin(object):
|
||||
|
||||
def __init__(self, driver):
|
||||
self.driver = driver
|
||||
|
||||
@abc.abstractmethod
|
||||
def create(self, context, obj):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def update(self, context, obj_old, obj):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def delete(self, context, obj):
|
||||
pass
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class BaseRefreshMixin(object):
|
||||
|
||||
@abc.abstractmethod
|
||||
def refresh(self, context, obj):
|
||||
pass
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class BaseStatsMixin(object):
|
||||
|
||||
@abc.abstractmethod
|
||||
def stats(self, context, obj):
|
||||
pass
|
||||
|
||||
|
||||
class BaseStatusUpdateMixin(object):
|
||||
|
||||
# Status update helpers
|
||||
# Note: You must set self.model_class to an appropriate neutron model
|
||||
# in your base manager class.
|
||||
|
||||
def active(self, context, model_id):
|
||||
if self.model_class is not None:
|
||||
self.driver.plugin.update_status(context, self.model_class,
|
||||
model_id, constants.ACTIVE)
|
||||
|
||||
def failed(self, context, model_id):
|
||||
if self.model_class is not None:
|
||||
self.driver.plugin.update_status(context, self.model_class,
|
||||
model_id, constants.ERROR)
|
||||
|
||||
|
||||
class BaseHealthMonitorStatusUpdateMixin(object):
|
||||
|
||||
def active(self, context, health_monitor_id, pool_id):
|
||||
self.driver.plugin.update_pool_health_monitor(context,
|
||||
health_monitor_id,
|
||||
pool_id,
|
||||
constants.ACTIVE)
|
||||
|
||||
def failed(self, context, health_monitor_id, pool_id):
|
||||
self.driver.plugin.update_pool_health_monitor(context,
|
||||
health_monitor_id,
|
||||
pool_id,
|
||||
constants.ERROR)
|
106
neutron/services/loadbalancer/drivers/logging_noop/driver.py
Normal file
106
neutron/services/loadbalancer/drivers/logging_noop/driver.py
Normal file
@ -0,0 +1,106 @@
|
||||
# Copyright 2014, Doug Wiegley (dougwig), A10 Networks
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron.openstack.common import log as logging
|
||||
from neutron.services.loadbalancer.drivers import driver_base
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LoggingNoopLoadBalancerDriver(driver_base.LoadBalancerBaseDriver):
|
||||
|
||||
def __init__(self, plugin):
|
||||
self.plugin = plugin
|
||||
|
||||
# Each of the major LBaaS objects in the neutron database
|
||||
# need a corresponding manager/handler class.
|
||||
#
|
||||
# Put common things that are shared across the entire driver, like
|
||||
# config or a rest client handle, here.
|
||||
#
|
||||
# This function is executed when neutron-server starts.
|
||||
|
||||
self.load_balancer = LoggingNoopLoadBalancerManager(self)
|
||||
self.listener = LoggingNoopListenerManager(self)
|
||||
self.pool = LoggingNoopPoolManager(self)
|
||||
self.member = LoggingNoopMemberManager(self)
|
||||
self.health_monitor = LoggingNoopHealthMonitorManager(self)
|
||||
|
||||
|
||||
class LoggingNoopCommonManager(object):
|
||||
|
||||
def create(self, context, obj):
|
||||
LOG.debug("LB %s no-op, create %s", self.__class__.__name__, obj.id)
|
||||
self.active(context, obj.id)
|
||||
|
||||
def update(self, context, old_obj, obj):
|
||||
LOG.debug("LB %s no-op, update %s", self.__class__.__name__, obj.id)
|
||||
self.active(context, obj.id)
|
||||
|
||||
def delete(self, context, obj):
|
||||
LOG.debug("LB %s no-op, delete %s", self.__class__.__name__, obj.id)
|
||||
|
||||
|
||||
class LoggingNoopLoadBalancerManager(LoggingNoopCommonManager,
|
||||
driver_base.BaseLoadBalancerManager):
|
||||
|
||||
def refresh(self, context, lb_obj, force=False):
|
||||
# This is intended to trigger the backend to check and repair
|
||||
# the state of this load balancer and all of its dependent objects
|
||||
LOG.debug("LB pool refresh %s, force=%s", lb_obj.id, force)
|
||||
|
||||
def stats(self, context, lb_obj):
|
||||
LOG.debug("LB stats %s", lb_obj.id)
|
||||
return {
|
||||
"bytes_in": 0,
|
||||
"bytes_out": 0,
|
||||
"active_connections": 0,
|
||||
"total_connections": 0
|
||||
}
|
||||
|
||||
|
||||
class LoggingNoopListenerManager(LoggingNoopCommonManager,
|
||||
driver_base.BaseListenerManager):
|
||||
|
||||
def create(self, context, obj):
|
||||
LOG.debug("LB listener no-op, create %s", self.__class__.__name__,
|
||||
obj.id)
|
||||
|
||||
def update(self, context, old_obj, obj):
|
||||
LOG.debug("LB listener no-op, update %s", self.__class__.__name__,
|
||||
obj.id)
|
||||
|
||||
|
||||
class LoggingNoopPoolManager(LoggingNoopCommonManager,
|
||||
driver_base.BasePoolManager):
|
||||
pass
|
||||
|
||||
|
||||
class LoggingNoopMemberManager(LoggingNoopCommonManager,
|
||||
driver_base.BaseMemberManager):
|
||||
pass
|
||||
|
||||
|
||||
class LoggingNoopHealthMonitorManager(LoggingNoopCommonManager,
|
||||
driver_base.BaseHealthMonitorManager):
|
||||
|
||||
def create(self, context, obj):
|
||||
LOG.debug("LB health monitor no-op, create %s",
|
||||
self.__class__.__name__, obj.id)
|
||||
self.active(context, obj.id, obj.id)
|
||||
|
||||
def update(self, context, old_obj, obj):
|
||||
LOG.debug("LB health monitor no-op, update %s",
|
||||
self.__class__.__name__, obj.id)
|
||||
self.active(context, obj.id, obj.id)
|
@ -0,0 +1,148 @@
|
||||
# Copyright 2014, Doug Wiegley (dougwig), A10 Networks
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from neutron import context
|
||||
from neutron.services.loadbalancer.drivers.logging_noop import driver
|
||||
from neutron.tests.unit.db.loadbalancer import test_db_loadbalancer
|
||||
|
||||
log_path = 'neutron.services.loadbalancer.drivers.logging_noop.driver.LOG'
|
||||
|
||||
|
||||
class FakeModel(object):
|
||||
def __init__(self, id):
|
||||
self.id = id
|
||||
|
||||
|
||||
def patch_manager(func):
|
||||
@mock.patch(log_path)
|
||||
def wrapper(*args):
|
||||
log_mock = args[-1]
|
||||
manager_test = args[0]
|
||||
model = args[1]
|
||||
parent = manager_test.parent
|
||||
driver = parent.driver
|
||||
driver.plugin.reset_mock()
|
||||
|
||||
func(*args[:-1])
|
||||
|
||||
s = str(log_mock.mock_calls[0])
|
||||
parent.assertEqual(s[:11], "call.debug(")
|
||||
parent.assertTrue(s.index(model.id) != -1,
|
||||
msg="Model ID not found in log")
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class ManagerTest(object):
|
||||
def __init__(self, parent, manager, model):
|
||||
self.parent = parent
|
||||
self.manager = manager
|
||||
|
||||
self.create(model)
|
||||
self.update(model, model)
|
||||
self.delete(model)
|
||||
|
||||
@patch_manager
|
||||
def create(self, model):
|
||||
self.manager.create(self.parent.context, model)
|
||||
|
||||
@patch_manager
|
||||
def update(self, old_model, model):
|
||||
self.manager.update(self.parent.context, old_model, model)
|
||||
|
||||
@patch_manager
|
||||
def delete(self, model):
|
||||
self.manager.delete(self.parent.context, model)
|
||||
|
||||
|
||||
class ManagerTestWithUpdates(ManagerTest):
|
||||
def __init__(self, parent, manager, model):
|
||||
self.parent = parent
|
||||
self.manager = manager
|
||||
|
||||
self.create(model)
|
||||
self.update(model, model)
|
||||
self.delete(model)
|
||||
|
||||
@patch_manager
|
||||
def create(self, model):
|
||||
self.manager.create(self.parent.context, model)
|
||||
if self.manager.model_class is not None:
|
||||
self.parent.assertEqual(
|
||||
str(self.parent.driver.plugin.mock_calls[0])[:18],
|
||||
"call.update_status")
|
||||
|
||||
@patch_manager
|
||||
def update(self, old_model, model):
|
||||
self.manager.update(self.parent.context, old_model, model)
|
||||
if self.manager.model_class is not None:
|
||||
self.parent.assertEqual(
|
||||
str(self.parent.driver.plugin.mock_calls[0])[:18],
|
||||
"call.update_status")
|
||||
|
||||
@patch_manager
|
||||
def delete(self, model):
|
||||
self.manager.delete(self.parent.context, model)
|
||||
|
||||
|
||||
class LoadBalancerManagerTest(ManagerTestWithUpdates):
|
||||
def __init__(self, parent, manager, model):
|
||||
super(LoadBalancerManagerTest, self).__init__(parent, manager, model)
|
||||
|
||||
self.refresh(model)
|
||||
self.stats(model)
|
||||
|
||||
@patch_manager
|
||||
def refresh(self, model):
|
||||
self.manager.refresh(self.parent.context, model)
|
||||
|
||||
@patch_manager
|
||||
def stats(self, model):
|
||||
dummy_stats = {
|
||||
"bytes_in": 0,
|
||||
"bytes_out": 0,
|
||||
"active_connections": 0,
|
||||
"total_connections": 0
|
||||
}
|
||||
h = self.manager.stats(self.parent.context, model)
|
||||
self.parent.assertEqual(h, dummy_stats)
|
||||
|
||||
|
||||
class TestLoggingNoopLoadBalancerDriver(
|
||||
test_db_loadbalancer.LoadBalancerPluginDbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestLoggingNoopLoadBalancerDriver, self).setUp()
|
||||
self.context = context.get_admin_context()
|
||||
self.plugin = mock.Mock()
|
||||
self.driver = driver.LoggingNoopLoadBalancerDriver(self.plugin)
|
||||
|
||||
def test_load_balancer_ops(self):
|
||||
LoadBalancerManagerTest(self, self.driver.load_balancer,
|
||||
FakeModel("loadbalancer-001"))
|
||||
|
||||
def test_listener_ops(self):
|
||||
ManagerTest(self, self.driver.listener, FakeModel("listener-001"))
|
||||
|
||||
def test_pool_ops(self):
|
||||
ManagerTestWithUpdates(self, self.driver.pool, FakeModel("pool-001"))
|
||||
|
||||
def test_member_ops(self):
|
||||
ManagerTestWithUpdates(self, self.driver.member,
|
||||
FakeModel("member-001"))
|
||||
|
||||
def test_health_monitor_ops(self):
|
||||
ManagerTest(self, self.driver.health_monitor, FakeModel("hm-001"))
|
Loading…
x
Reference in New Issue
Block a user