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
|
# 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.
|
# 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
|
# 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
|
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)
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
class LoadBalancerAbstractDriver(object):
|
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