[log]: add driver manager to LoggingPlugin
This patch adds driver manger to LoggingPlugin to manage logging drivers are enabled belong ML2 dirvers. Co-Authored-By: Yushiro FURUKAWA <y.furukawa_2@jp.fujitsu.com> Change-Id: I5a0f896c9ec7f670b662f16825feccbc07db19dd Partially-implements: blueprint security-group-logging Related-Bug: #1468366
This commit is contained in:
parent
12d6a3ea4c
commit
39a9ed4c50
@ -21,5 +21,5 @@ class LogResourceNotFound(n_exc.NotFound):
|
||||
message = _("Log resource %(log_id)s could not be found.")
|
||||
|
||||
|
||||
class InvalidLogReosurceType(n_exc.InvalidInput):
|
||||
class InvalidLogResourceType(n_exc.InvalidInput):
|
||||
message = _("Invalid log resource_type: %(resource_type)s.")
|
||||
|
0
neutron/services/logapi/drivers/__init__.py
Normal file
0
neutron/services/logapi/drivers/__init__.py
Normal file
79
neutron/services/logapi/drivers/base.py
Normal file
79
neutron/services/logapi/drivers/base.py
Normal file
@ -0,0 +1,79 @@
|
||||
# Copyright (c) 2017 Fujitsu Limited
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.callbacks import events
|
||||
from neutron_lib.callbacks import registry
|
||||
from oslo_log import log as logging
|
||||
|
||||
from neutron.services.logapi.common import constants as log_const
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@registry.has_registry_receivers
|
||||
class DriverBase(object):
|
||||
|
||||
def __init__(self, name, vif_types, vnic_types,
|
||||
supported_logging_types, requires_rpc=False):
|
||||
"""Instantiate a log driver.
|
||||
|
||||
:param name: driver name.
|
||||
:param vif_types: list of interfaces (VIFs) supported.
|
||||
:param vnic_types: list of vnic types supported.
|
||||
:param supported_logging_types: list of supported logging types.
|
||||
:param requires_rpc: indicates if this driver expects rpc sever
|
||||
to notify or callback
|
||||
"""
|
||||
|
||||
self.name = name
|
||||
self.vif_types = vif_types
|
||||
self.vnic_types = vnic_types
|
||||
self.supported_logging_types = supported_logging_types
|
||||
self.requires_rpc = requires_rpc
|
||||
|
||||
# The log driver should advertise itself as supported driver by calling
|
||||
# register_driver() on the LoggingServiceDriverManager. Therefore,
|
||||
# logging plugin can discover which resources types are supported by
|
||||
# the log driver.
|
||||
@registry.receives(log_const.LOGGING_PLUGIN, [events.AFTER_INIT])
|
||||
def _register(self, resource, event, trigger, **kwargs):
|
||||
if self.is_loaded:
|
||||
# trigger is the LoggingServiceDriverManager
|
||||
trigger.register_driver(self)
|
||||
|
||||
def is_loaded(self):
|
||||
"""True if the driver is active for the Neutron Server.
|
||||
|
||||
Implement this method to determine if your driver is actively
|
||||
configured for this Neutron Server deployment.
|
||||
"""
|
||||
return True
|
||||
|
||||
def is_vif_type_compatible(self, vif_type):
|
||||
"""True if the driver is compatible with the VIF type."""
|
||||
return vif_type in self.vif_types
|
||||
|
||||
def is_vnic_compatible(self, vnic_type):
|
||||
"""True if the driver is compatible with the specific VNIC type."""
|
||||
return vnic_type in self.vnic_types
|
||||
|
||||
def is_logging_type_supported(self, log_type):
|
||||
supported = log_type in self.supported_logging_types
|
||||
if not supported:
|
||||
LOG.debug("logging type %(log_type)s is not supported by "
|
||||
"%(driver_name)s",
|
||||
{'log_type': log_type,
|
||||
'driver_name': self.name})
|
||||
return supported
|
53
neutron/services/logapi/drivers/manager.py
Normal file
53
neutron/services/logapi/drivers/manager.py
Normal file
@ -0,0 +1,53 @@
|
||||
# Copyright (c) 2017 Fujitsu Limited
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.callbacks import events
|
||||
from neutron_lib.callbacks import registry
|
||||
from oslo_log import log as logging
|
||||
|
||||
from neutron.services.logapi.common import constants as log_const
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LoggingServiceDriverManager(object):
|
||||
|
||||
def __init__(self):
|
||||
self._drivers = set()
|
||||
registry.notify(log_const.LOGGING_PLUGIN, events.AFTER_INIT, self)
|
||||
|
||||
@property
|
||||
def drivers(self):
|
||||
return self._drivers
|
||||
|
||||
def register_driver(self, driver):
|
||||
"""Register driver with logging plugin.
|
||||
|
||||
This method is called from drivers on INIT event.
|
||||
"""
|
||||
self._drivers.add(driver)
|
||||
|
||||
@property
|
||||
def supported_logging_types(self):
|
||||
if not self._drivers:
|
||||
return set()
|
||||
|
||||
log_types = set()
|
||||
|
||||
for driver in self._drivers:
|
||||
log_types |= set(driver.supported_logging_types)
|
||||
LOG.debug("Supported logging types (logging types supported "
|
||||
"by at least one loaded log_driver): %s", log_types)
|
||||
return log_types
|
@ -19,6 +19,7 @@ from neutron.extensions import logging as log_ext
|
||||
from neutron.objects import base as base_obj
|
||||
from neutron.objects.logapi import logging_resource as log_object
|
||||
from neutron.services.logapi.common import exceptions as log_exc
|
||||
from neutron.services.logapi.drivers import manager as driver_mgr
|
||||
|
||||
|
||||
class LoggingPlugin(log_ext.LoggingPluginBase):
|
||||
@ -29,11 +30,14 @@ class LoggingPlugin(log_ext.LoggingPluginBase):
|
||||
__native_pagination_support = True
|
||||
__native_sorting_support = True
|
||||
|
||||
def __init__(self):
|
||||
super(LoggingPlugin, self).__init__()
|
||||
self.driver_manager = driver_mgr.LoggingServiceDriverManager()
|
||||
|
||||
@property
|
||||
def supported_logging_types(self):
|
||||
# Todo(annp): supported_logging_types will dynamic load from
|
||||
# log_drivers. So return value for this function is a temporary.
|
||||
return []
|
||||
# supported_logging_types are be dynamically loaded from log_drivers
|
||||
return self.driver_manager.supported_logging_types
|
||||
|
||||
@db_base_plugin_common.filter_fields
|
||||
@db_base_plugin_common.convert_result_to_dict
|
||||
@ -60,6 +64,10 @@ class LoggingPlugin(log_ext.LoggingPluginBase):
|
||||
def create_log(self, context, log):
|
||||
"""Create a log object"""
|
||||
log_data = log['log']
|
||||
resource_type = log_data['resource_type']
|
||||
if resource_type not in self.supported_logging_types:
|
||||
raise log_exc.InvalidLogResourceType(
|
||||
resource_type=resource_type)
|
||||
with db_api.context_manager.writer.using(context):
|
||||
# body 'log' contains both tenant_id and project_id
|
||||
# but only latter needs to be used to create Log object.
|
||||
|
58
neutron/tests/unit/services/logapi/drivers/test_base.py
Normal file
58
neutron/tests/unit/services/logapi/drivers/test_base.py
Normal file
@ -0,0 +1,58 @@
|
||||
# Copyright (C) 2017 Fujitsu Limited
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.api.definitions import portbindings
|
||||
|
||||
from neutron.services.logapi.drivers import base as log_base_driver
|
||||
from neutron.tests import base
|
||||
|
||||
SUPPORTED_LOGGING_TYPES = ['security_group']
|
||||
|
||||
|
||||
class FakeDriver(log_base_driver.DriverBase):
|
||||
|
||||
@staticmethod
|
||||
def create():
|
||||
return FakeDriver(
|
||||
name='fake_driver',
|
||||
vif_types=[portbindings.VIF_TYPE_OVS],
|
||||
vnic_types=[portbindings.VNIC_NORMAL],
|
||||
supported_logging_types=SUPPORTED_LOGGING_TYPES,
|
||||
requires_rpc=False
|
||||
)
|
||||
|
||||
|
||||
class TestDriverBase(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestDriverBase, self).setUp()
|
||||
self.driver = FakeDriver.create()
|
||||
|
||||
def test_is_vif_type_compatible(self):
|
||||
self.assertFalse(
|
||||
self.driver.is_vif_type_compatible(portbindings.VIF_TYPE_OTHER))
|
||||
self.assertTrue(
|
||||
self.driver.is_vif_type_compatible(portbindings.VIF_TYPE_OVS))
|
||||
|
||||
def test_is_vnic_compatible(self):
|
||||
self.assertFalse(
|
||||
self.driver.is_vnic_compatible(portbindings.VNIC_BAREMETAL))
|
||||
self.assertTrue(
|
||||
self.driver.is_vnic_compatible(portbindings.VNIC_NORMAL))
|
||||
|
||||
def test_is_logging_type_supported(self):
|
||||
self.assertTrue(
|
||||
self.driver.is_logging_type_supported('security_group'))
|
||||
self.assertFalse(self.driver.is_logging_type_supported('firewall'))
|
79
neutron/tests/unit/services/logapi/drivers/test_manager.py
Normal file
79
neutron/tests/unit/services/logapi/drivers/test_manager.py
Normal file
@ -0,0 +1,79 @@
|
||||
# Copyright (c) 2017 Fujitsu Limited
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron.services.logapi.drivers import base as log_driver_base
|
||||
from neutron.services.logapi.drivers import manager as driver_mgr
|
||||
from neutron.tests.unit.services.logapi import base
|
||||
|
||||
|
||||
class TestLogDriversManagerBase(base.BaseLogTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestLogDriversManagerBase, self).setUp()
|
||||
self.config_parse()
|
||||
self.setup_coreplugin(load_plugins=False)
|
||||
|
||||
@staticmethod
|
||||
def _create_manager_with_drivers(drivers_details):
|
||||
for name, driver_details in drivers_details.items():
|
||||
|
||||
class LogDriver(log_driver_base.DriverBase):
|
||||
@property
|
||||
def is_loaded(self):
|
||||
return driver_details['is_loaded']
|
||||
|
||||
LogDriver(name,
|
||||
driver_details.get('vif_types', []),
|
||||
driver_details.get('vnic_types', []),
|
||||
driver_details.get('supported_logging_types', []))
|
||||
|
||||
return driver_mgr.LoggingServiceDriverManager()
|
||||
|
||||
|
||||
class TestLogDriversManagerMulti(TestLogDriversManagerBase):
|
||||
"""Test calls happen to all drivers"""
|
||||
def test_driver_manager_empty_with_no_drivers(self):
|
||||
driver_manager = self._create_manager_with_drivers({})
|
||||
self.assertEqual(0, len(driver_manager.drivers))
|
||||
|
||||
def test_driver_manager_empty_with_no_loaded_drivers(self):
|
||||
driver_manager = self._create_manager_with_drivers(
|
||||
{'driver-A': {'is_loaded': False}})
|
||||
self.assertEqual(0, len(driver_manager.drivers))
|
||||
|
||||
def test_driver_manager_with_one_loaded_driver(self):
|
||||
driver_manager = self._create_manager_with_drivers(
|
||||
{'driver-A': {'is_loaded': True}})
|
||||
self.assertEqual(1, len(driver_manager.drivers))
|
||||
|
||||
def test_driver_manager_with_two_loaded_drivers(self):
|
||||
driver_manager = self._create_manager_with_drivers(
|
||||
{'driver-A': {'is_loaded': True},
|
||||
'driver-B': {'is_loaded': True}})
|
||||
self.assertEqual(2, len(driver_manager.drivers))
|
||||
|
||||
|
||||
class TestLogDriversManagerLoggingTypes(TestLogDriversManagerBase):
|
||||
"""Test supported logging types"""
|
||||
def test_available_logging_types(self):
|
||||
driver_manager = self._create_manager_with_drivers(
|
||||
{'driver-A': {'is_loaded': True,
|
||||
'supported_logging_types': ['security_group']},
|
||||
'driver-B': {'is_loaded': True,
|
||||
'supported_logging_types':
|
||||
['security_group', 'firewall']}
|
||||
})
|
||||
self.assertEqual(set(['security_group', 'firewall']),
|
||||
driver_manager.supported_logging_types)
|
@ -28,6 +28,7 @@ from neutron.services.logapi.common import exceptions as log_exc
|
||||
from neutron.tests.unit.services.logapi import base
|
||||
|
||||
DB_PLUGIN_KLASS = 'neutron.db.db_base_plugin_v2.NeutronDbPluginV2'
|
||||
SUPPORTED_LOGGING_TYPES = ['security_group']
|
||||
|
||||
|
||||
class TestLoggingPlugin(base.BaseLogTestCase):
|
||||
@ -51,6 +52,12 @@ class TestLoggingPlugin(base.BaseLogTestCase):
|
||||
|
||||
manager.init()
|
||||
self.log_plugin = directory.get_plugin(constants.LOG_API)
|
||||
self.log_plugin.driver_manager = mock.Mock()
|
||||
log_types = mock.PropertyMock(return_value=SUPPORTED_LOGGING_TYPES)
|
||||
self.log_plugin.driver_manager.supported_logging_types = \
|
||||
mock.patch('neutron.services.logapi.drivers.manager.'
|
||||
'LoggingServiceDriverManager.supported_logging_types',
|
||||
new_callable=log_types).start()
|
||||
self.ctxt = context.Context('fake_user', 'fake_tenant')
|
||||
mock.patch.object(self.ctxt.session, 'refresh').start()
|
||||
mock.patch.object(self.ctxt.session, 'expunge').start()
|
||||
@ -159,6 +166,15 @@ class TestLoggingPlugin(base.BaseLogTestCase):
|
||||
context=self.ctxt, **log_data['log'])
|
||||
self.assertTrue(new_log.create.called)
|
||||
|
||||
def test_create_log_with_unsupported_logging_type(self):
|
||||
log = {'log': {'resource_type': 'fake_type',
|
||||
'enabled': True}}
|
||||
self.assertRaises(
|
||||
log_exc.InvalidLogResourceType,
|
||||
self.log_plugin.create_log,
|
||||
self.ctxt,
|
||||
log)
|
||||
|
||||
def test_update_log(self):
|
||||
log_data = {'log': {'enabled': True}}
|
||||
new_log = mock.Mock()
|
||||
|
Loading…
x
Reference in New Issue
Block a user