[log]: implement logging plugin
This patch introduces the logging api definition and initial implementation of LoggingApiPlugin. The api definition code will be removed after [1] has been merged on neutron lib. [1]https://review.openstack.org/#/c/415817/ Co-Authored-By: Yushiro FURUKAWA <y.furukawa_2@jp.fujitsu.com> Partially-implements: blueprint security-group-logging Related-Bug: #1468366 Change-Id: Iace31506502de25da9dce5fcfdbfe2c726bea27f
This commit is contained in:
parent
4a316960f2
commit
913c9e78b9
@ -225,5 +225,12 @@
|
|||||||
"get_security_group_rules": "rule:admin_or_owner",
|
"get_security_group_rules": "rule:admin_or_owner",
|
||||||
"get_security_group_rule": "rule:admin_or_owner",
|
"get_security_group_rule": "rule:admin_or_owner",
|
||||||
"create_security_group_rule": "rule:admin_or_owner",
|
"create_security_group_rule": "rule:admin_or_owner",
|
||||||
"delete_security_group_rule": "rule:admin_or_owner"
|
"delete_security_group_rule": "rule:admin_or_owner",
|
||||||
|
|
||||||
|
"get_loggable_resources": "rule:admin_only",
|
||||||
|
"create_log": "rule:admin_only",
|
||||||
|
"update_log": "rule:admin_only",
|
||||||
|
"delete_log": "rule:admin_only",
|
||||||
|
"get_logs": "rule:admin_only",
|
||||||
|
"get_log": "rule:admin_only"
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from neutron.objects.logapi import logging_resource as log_object
|
||||||
from neutron.objects import network
|
from neutron.objects import network
|
||||||
from neutron.objects import ports
|
from neutron.objects import ports
|
||||||
from neutron.objects.qos import policy
|
from neutron.objects.qos import policy
|
||||||
@ -19,6 +20,7 @@ from neutron.objects import trunk
|
|||||||
|
|
||||||
|
|
||||||
# Supported types
|
# Supported types
|
||||||
|
LOGGING_RESOURCE = log_object.Log.obj_name()
|
||||||
TRUNK = trunk.Trunk.obj_name()
|
TRUNK = trunk.Trunk.obj_name()
|
||||||
QOS_POLICY = policy.QosPolicy.obj_name()
|
QOS_POLICY = policy.QosPolicy.obj_name()
|
||||||
SUBPORT = trunk.SubPort.obj_name()
|
SUBPORT = trunk.SubPort.obj_name()
|
||||||
@ -38,6 +40,7 @@ _VALID_CLS = (
|
|||||||
network.Network,
|
network.Network,
|
||||||
securitygroup.SecurityGroup,
|
securitygroup.SecurityGroup,
|
||||||
securitygroup.SecurityGroupRule,
|
securitygroup.SecurityGroupRule,
|
||||||
|
log_object.Log,
|
||||||
)
|
)
|
||||||
|
|
||||||
_TYPE_TO_CLS_MAP = {cls.obj_name(): cls for cls in _VALID_CLS}
|
_TYPE_TO_CLS_MAP = {cls.obj_name(): cls for cls in _VALID_CLS}
|
||||||
|
158
neutron/extensions/logging.py
Normal file
158
neutron/extensions/logging.py
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
import abc
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
from neutron_lib.api import converters
|
||||||
|
from neutron_lib.api import extensions as api_extensions
|
||||||
|
from neutron_lib.db import constants as db_const
|
||||||
|
from neutron_lib.services import base as service_base
|
||||||
|
import six
|
||||||
|
|
||||||
|
from neutron.api.v2 import resource_helper
|
||||||
|
from neutron.plugins.common import constants
|
||||||
|
from neutron.services.logapi.common import constants as log_const
|
||||||
|
|
||||||
|
|
||||||
|
LOG_PREFIX = "/log"
|
||||||
|
# Attribute Map
|
||||||
|
RESOURCE_ATTRIBUTE_MAP = {
|
||||||
|
'logs': {
|
||||||
|
'id': {'allow_post': False, 'allow_put': False,
|
||||||
|
'validate': {'type:uuid': None},
|
||||||
|
'is_visible': True,
|
||||||
|
'primary_key': True},
|
||||||
|
'project_id': {'allow_post': True, 'allow_put': False,
|
||||||
|
'required_by_policy': True,
|
||||||
|
'validate': {
|
||||||
|
'type:string':
|
||||||
|
db_const.PROJECT_ID_FIELD_SIZE},
|
||||||
|
'is_visible': True},
|
||||||
|
'name': {'allow_post': True, 'allow_put': True,
|
||||||
|
'validate': {'type:string': db_const.NAME_FIELD_SIZE},
|
||||||
|
'default': '', 'is_visible': True},
|
||||||
|
'resource_type': {'allow_post': True, 'allow_put': False,
|
||||||
|
'required_by_policy': True,
|
||||||
|
'validate':
|
||||||
|
{'type:string': db_const.RESOURCE_TYPE_FIELD_SIZE},
|
||||||
|
'is_visible': True},
|
||||||
|
'resource_id': {'allow_post': True, 'allow_put': False,
|
||||||
|
'validate': {'type:uuid_or_none': None},
|
||||||
|
'default': None, 'is_visible': True},
|
||||||
|
'event': {'allow_post': True, 'allow_put': False,
|
||||||
|
'validate': {'type:values': log_const.LOG_EVENTS},
|
||||||
|
'default': log_const.ALL_EVENT, 'is_visible': True},
|
||||||
|
'target_id': {'allow_post': True, 'allow_put': False,
|
||||||
|
'validate': {'type:uuid_or_none': None},
|
||||||
|
'default': None, 'is_visible': True},
|
||||||
|
'enabled': {'allow_post': True, 'allow_put': True,
|
||||||
|
'is_visible': True, 'default': True,
|
||||||
|
'convert_to': converters.convert_to_boolean},
|
||||||
|
},
|
||||||
|
|
||||||
|
'loggable_resources': {
|
||||||
|
'type': {'allow_post': False, 'allow_put': False,
|
||||||
|
'is_visible': True}},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Logging(api_extensions.ExtensionDescriptor):
|
||||||
|
"""Neutron logging api extension."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_name(cls):
|
||||||
|
return "Logging API Extension"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_alias(cls):
|
||||||
|
return "logging"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_description(cls):
|
||||||
|
return "Provides a logging API for resources such as security group"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_updated(cls):
|
||||||
|
return "2017-01-01T10:00:00-00:00"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_plugin_interface(cls):
|
||||||
|
return LoggingPluginBase
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_resources(cls):
|
||||||
|
"""Returns Ext Resources."""
|
||||||
|
plural_mappings = resource_helper.build_plural_mappings(
|
||||||
|
{}, itertools.chain(RESOURCE_ATTRIBUTE_MAP))
|
||||||
|
|
||||||
|
resources = resource_helper.build_resource_info(
|
||||||
|
plural_mappings,
|
||||||
|
RESOURCE_ATTRIBUTE_MAP,
|
||||||
|
constants.LOG_API,
|
||||||
|
translate_name=True,
|
||||||
|
allow_bulk=True)
|
||||||
|
|
||||||
|
return resources
|
||||||
|
|
||||||
|
def update_attributes_map(self, attributes, extension_attrs_map=None):
|
||||||
|
super(Logging, self).update_attributes_map(
|
||||||
|
attributes, extension_attrs_map=RESOURCE_ATTRIBUTE_MAP)
|
||||||
|
|
||||||
|
def get_extended_resources(self, version):
|
||||||
|
if version == "2.0":
|
||||||
|
return dict(list(RESOURCE_ATTRIBUTE_MAP.items()))
|
||||||
|
else:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class LoggingPluginBase(service_base.ServicePluginBase):
|
||||||
|
|
||||||
|
path_prefix = LOG_PREFIX
|
||||||
|
|
||||||
|
def get_plugin_description(self):
|
||||||
|
return "Logging API Service Plugin"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_plugin_type(cls):
|
||||||
|
return constants.LOG_API
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_logs(self, context, filters=None, fields=None, sorts=None,
|
||||||
|
limit=None, marker=None, page_reverse=False):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_log(self, context, log_id, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_log(self, context, log):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_log(self, context, log_id, log):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_log(self, context, log_id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_loggable_resources(self, context, filters=None, fields=None,
|
||||||
|
sorts=None, limit=None,
|
||||||
|
marker=None, page_reverse=False):
|
||||||
|
pass
|
@ -35,4 +35,4 @@ class SecurityEvent(obj_fields.String):
|
|||||||
|
|
||||||
|
|
||||||
class SecurityEventField(obj_fields.AutoTypedField):
|
class SecurityEventField(obj_fields.AutoTypedField):
|
||||||
AUTO_TYPE = SecurityEvent(valid_values=log_const.VALID_EVENTS)
|
AUTO_TYPE = SecurityEvent(valid_values=log_const.LOG_EVENTS)
|
||||||
|
@ -25,6 +25,7 @@ VPN = "VPN"
|
|||||||
METERING = "METERING"
|
METERING = "METERING"
|
||||||
FLAVORS = "FLAVORS"
|
FLAVORS = "FLAVORS"
|
||||||
QOS = "QOS"
|
QOS = "QOS"
|
||||||
|
LOG_API = "LOGGING"
|
||||||
|
|
||||||
# Maps extension alias to service type that
|
# Maps extension alias to service type that
|
||||||
# can be implemented by the core plugin.
|
# can be implemented by the core plugin.
|
||||||
|
@ -16,5 +16,5 @@
|
|||||||
ACCEPT_EVENT = 'ACCEPT'
|
ACCEPT_EVENT = 'ACCEPT'
|
||||||
DROP_EVENT = 'DROP'
|
DROP_EVENT = 'DROP'
|
||||||
ALL_EVENT = 'ALL'
|
ALL_EVENT = 'ALL'
|
||||||
VALID_EVENTS = [ACCEPT_EVENT, DROP_EVENT, ALL_EVENT]
|
LOG_EVENTS = [ACCEPT_EVENT, DROP_EVENT, ALL_EVENT]
|
||||||
LOGGING_PLUGIN = 'logging-plugin'
|
LOGGING_PLUGIN = 'logging-plugin'
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
# Copyright 2016 Fujitsu Limited.
|
# Copyright 2017 Fujitsu Limited.
|
||||||
#
|
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
@ -18,13 +17,9 @@ from neutron._i18n import _
|
|||||||
from neutron_lib import exceptions as n_exc
|
from neutron_lib import exceptions as n_exc
|
||||||
|
|
||||||
|
|
||||||
class ResourceLogNotFound(n_exc.NotFound):
|
class LogResourceNotFound(n_exc.NotFound):
|
||||||
message = _("Resource log %(id)s could not be found.")
|
message = _("Log resource %(log_id)s could not be found.")
|
||||||
|
|
||||||
|
|
||||||
class ParentResourceNotFound(n_exc.NotFound):
|
class InvalidLogReosurceType(n_exc.InvalidInput):
|
||||||
message = _("Parent resource %(parent_resource_id)s could not be found.")
|
message = _("Invalid log resource_type: %(resource_type)s.")
|
||||||
|
|
||||||
|
|
||||||
class ResourceNotFound(n_exc.NotFound):
|
|
||||||
message = _("Resource %(resource_id)s could not be found.")
|
|
||||||
|
93
neutron/services/logapi/logging_plugin.py
Normal file
93
neutron/services/logapi/logging_plugin.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# 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.db import api as db_api
|
||||||
|
from neutron.db import db_base_plugin_common
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
class LoggingPlugin(log_ext.LoggingPluginBase):
|
||||||
|
"""Implementation of the Neutron logging api plugin."""
|
||||||
|
|
||||||
|
supported_extension_aliases = ['logging']
|
||||||
|
|
||||||
|
__native_pagination_support = True
|
||||||
|
__native_sorting_support = True
|
||||||
|
|
||||||
|
@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 []
|
||||||
|
|
||||||
|
@db_base_plugin_common.filter_fields
|
||||||
|
@db_base_plugin_common.convert_result_to_dict
|
||||||
|
def get_logs(self, context, filters=None, fields=None, sorts=None,
|
||||||
|
limit=None, marker=None, page_reverse=False):
|
||||||
|
"""Return information for available log objects"""
|
||||||
|
filters = filters or {}
|
||||||
|
pager = base_obj.Pager(sorts, limit, page_reverse, marker)
|
||||||
|
return log_object.Log.get_objects(context, _pager=pager, **filters)
|
||||||
|
|
||||||
|
def _get_log(self, context, log_id):
|
||||||
|
"""Return the log object or raise if not found"""
|
||||||
|
log_obj = log_object.Log.get_object(context, id=log_id)
|
||||||
|
if not log_obj:
|
||||||
|
raise log_exc.LogResourceNotFound(log_id=log_id)
|
||||||
|
return log_obj
|
||||||
|
|
||||||
|
@db_base_plugin_common.filter_fields
|
||||||
|
@db_base_plugin_common.convert_result_to_dict
|
||||||
|
def get_log(self, context, log_id, fields=None):
|
||||||
|
return self._get_log(context, log_id)
|
||||||
|
|
||||||
|
@db_base_plugin_common.convert_result_to_dict
|
||||||
|
def create_log(self, context, log):
|
||||||
|
"""Create a log object"""
|
||||||
|
log_data = log['log']
|
||||||
|
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.
|
||||||
|
# We need to remove redundant keyword.
|
||||||
|
log_data.pop('tenant_id', None)
|
||||||
|
log_obj = log_object.Log(context=context, **log_data)
|
||||||
|
log_obj.create()
|
||||||
|
return log_obj
|
||||||
|
|
||||||
|
@db_base_plugin_common.convert_result_to_dict
|
||||||
|
def update_log(self, context, log_id, log):
|
||||||
|
"""Update information for the specified log object"""
|
||||||
|
log_data = log['log']
|
||||||
|
with db_api.context_manager.writer.using(context):
|
||||||
|
log_obj = log_object.Log(context, id=log_id)
|
||||||
|
log_obj.update_fields(log_data, reset_changes=True)
|
||||||
|
log_obj.update()
|
||||||
|
return log_obj
|
||||||
|
|
||||||
|
def delete_log(self, context, log_id):
|
||||||
|
"""Delete the specified log object"""
|
||||||
|
with db_api.context_manager.writer.using(context):
|
||||||
|
log_obj = self._get_log(context, log_id)
|
||||||
|
log_obj.delete()
|
||||||
|
|
||||||
|
def get_loggable_resources(self, context, filters=None, fields=None,
|
||||||
|
sorts=None, limit=None,
|
||||||
|
marker=None, page_reverse=False):
|
||||||
|
"""Get supported logging types"""
|
||||||
|
return [{'type': type_}
|
||||||
|
for type_ in self.supported_logging_types]
|
@ -225,5 +225,12 @@
|
|||||||
"get_security_group_rules": "rule:admin_or_owner",
|
"get_security_group_rules": "rule:admin_or_owner",
|
||||||
"get_security_group_rule": "rule:admin_or_owner",
|
"get_security_group_rule": "rule:admin_or_owner",
|
||||||
"create_security_group_rule": "rule:admin_or_owner",
|
"create_security_group_rule": "rule:admin_or_owner",
|
||||||
"delete_security_group_rule": "rule:admin_or_owner"
|
"delete_security_group_rule": "rule:admin_or_owner",
|
||||||
|
|
||||||
|
"get_loggable_resources": "rule:admin_only",
|
||||||
|
"create_log": "rule:admin_only",
|
||||||
|
"update_log": "rule:admin_only",
|
||||||
|
"delete_log": "rule:admin_only",
|
||||||
|
"get_logs": "rule:admin_only",
|
||||||
|
"get_log": "rule:admin_only"
|
||||||
}
|
}
|
||||||
|
@ -323,4 +323,4 @@ def get_random_ipv6_mode():
|
|||||||
|
|
||||||
|
|
||||||
def get_random_security_event():
|
def get_random_security_event():
|
||||||
return random.choice(log_const.VALID_EVENTS)
|
return random.choice(log_const.LOG_EVENTS)
|
||||||
|
0
neutron/tests/unit/services/logapi/__init__.py
Normal file
0
neutron/tests/unit/services/logapi/__init__.py
Normal file
38
neutron/tests/unit/services/logapi/base.py
Normal file
38
neutron/tests/unit/services/logapi/base.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# 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.api.rpc.callbacks.consumer import registry as cons_registry
|
||||||
|
from neutron.api.rpc.callbacks.producer import registry as prod_registry
|
||||||
|
from neutron.api.rpc.callbacks import resource_manager
|
||||||
|
from neutron.tests.unit import testlib_api
|
||||||
|
|
||||||
|
|
||||||
|
class BaseLogTestCase(testlib_api.SqlTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(BaseLogTestCase, self).setUp()
|
||||||
|
|
||||||
|
with mock.patch.object(
|
||||||
|
resource_manager.ResourceCallbacksManager, '_singleton',
|
||||||
|
new_callable=mock.PropertyMock(return_value=False)):
|
||||||
|
|
||||||
|
self.cons_mgr = resource_manager.ConsumerResourceCallbacksManager()
|
||||||
|
self.prod_mgr = resource_manager.ProducerResourceCallbacksManager()
|
||||||
|
for mgr in (self.cons_mgr, self.prod_mgr):
|
||||||
|
mgr.clear()
|
||||||
|
|
||||||
|
mock.patch.object(
|
||||||
|
cons_registry, '_get_manager', return_value=self.cons_mgr).start()
|
||||||
|
|
||||||
|
mock.patch.object(
|
||||||
|
prod_registry, '_get_manager', return_value=self.prod_mgr).start()
|
207
neutron/tests/unit/services/logapi/test_logging_plugin.py
Normal file
207
neutron/tests/unit/services/logapi/test_logging_plugin.py
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
from neutron_lib import context
|
||||||
|
from neutron_lib.plugins import directory
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
|
from neutron import manager
|
||||||
|
from neutron.objects.logapi import logging_resource as log_object
|
||||||
|
from neutron.objects import ports
|
||||||
|
from neutron.objects import securitygroup as sg_object
|
||||||
|
from neutron.plugins.common import constants
|
||||||
|
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'
|
||||||
|
|
||||||
|
|
||||||
|
class TestLoggingPlugin(base.BaseLogTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestLoggingPlugin, self).setUp()
|
||||||
|
self.setup_coreplugin(load_plugins=False)
|
||||||
|
|
||||||
|
mock.patch('neutron.objects.db.api.create_object').start()
|
||||||
|
mock.patch('neutron.objects.db.api.update_object').start()
|
||||||
|
mock.patch('neutron.objects.db.api.delete_object').start()
|
||||||
|
mock.patch('neutron.objects.db.api.get_object').start()
|
||||||
|
# We don't use real models as per mocks above. We also need to mock-out
|
||||||
|
# methods that work with real data types
|
||||||
|
mock.patch(
|
||||||
|
'neutron.objects.base.NeutronDbObject.modify_fields_from_db'
|
||||||
|
).start()
|
||||||
|
|
||||||
|
cfg.CONF.set_override("core_plugin", DB_PLUGIN_KLASS)
|
||||||
|
cfg.CONF.set_override("service_plugins",
|
||||||
|
["neutron.services.logapi.logging_plugin.LoggingPlugin"])
|
||||||
|
|
||||||
|
manager.init()
|
||||||
|
self.log_plugin = directory.get_plugin(constants.LOG_API)
|
||||||
|
self.ctxt = context.Context('fake_user', 'fake_tenant')
|
||||||
|
mock.patch.object(self.ctxt.session, 'refresh').start()
|
||||||
|
mock.patch.object(self.ctxt.session, 'expunge').start()
|
||||||
|
|
||||||
|
def test_get_logs(self):
|
||||||
|
with mock.patch.object(log_object.Log, 'get_objects')\
|
||||||
|
as get_objects_mock:
|
||||||
|
filters = {'filter': 'filter_id'}
|
||||||
|
self.log_plugin.get_logs(self.ctxt, filters=filters)
|
||||||
|
get_objects_mock.assert_called_once_with(self.ctxt,
|
||||||
|
_pager=mock.ANY, filter='filter_id')
|
||||||
|
|
||||||
|
def test_get_log_without_return_value(self):
|
||||||
|
with mock.patch.object(log_object.Log, 'get_object',
|
||||||
|
return_value=None):
|
||||||
|
self.assertRaises(
|
||||||
|
log_exc.LogResourceNotFound,
|
||||||
|
self.log_plugin.get_log,
|
||||||
|
self.ctxt,
|
||||||
|
mock.ANY,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_get_log_with_return_value(self):
|
||||||
|
log_id = uuidutils.generate_uuid()
|
||||||
|
with mock.patch.object(log_object.Log, 'get_object')\
|
||||||
|
as get_object_mock:
|
||||||
|
self.log_plugin.get_log(self.ctxt, log_id)
|
||||||
|
get_object_mock.assert_called_once_with(self.ctxt,
|
||||||
|
id=log_id)
|
||||||
|
|
||||||
|
@mock.patch('neutron.db._utils.model_query')
|
||||||
|
def test_create_log_full_options(self, query_mock):
|
||||||
|
log = {'log': {'resource_type': 'security_group',
|
||||||
|
'enabled': True,
|
||||||
|
'resource_id': uuidutils.generate_uuid(),
|
||||||
|
'target_id': uuidutils.generate_uuid()}}
|
||||||
|
sg = mock.Mock()
|
||||||
|
port = mock.Mock()
|
||||||
|
new_log = mock.Mock()
|
||||||
|
with mock.patch.object(sg_object.SecurityGroup, 'get_object',
|
||||||
|
return_value=sg):
|
||||||
|
with mock.patch.object(ports.Port, 'get_object',
|
||||||
|
return_value=port):
|
||||||
|
with mock.patch('neutron.objects.logapi.'
|
||||||
|
'logging_resource.Log',
|
||||||
|
return_value=new_log) as init_log_mock:
|
||||||
|
self.log_plugin.create_log(self.ctxt, log)
|
||||||
|
init_log_mock.assert_called_once_with(context=self.ctxt,
|
||||||
|
**log['log'])
|
||||||
|
self.assertTrue(new_log.create.called)
|
||||||
|
|
||||||
|
def test_create_log_without_sg_resource(self):
|
||||||
|
log = {'log': {'resource_type': 'security_group',
|
||||||
|
'enabled': True,
|
||||||
|
'target_id': uuidutils.generate_uuid()}}
|
||||||
|
new_log = mock.Mock()
|
||||||
|
new_log.enabled = True
|
||||||
|
port = mock.Mock()
|
||||||
|
with mock.patch.object(ports.Port, 'get_object', return_value=port):
|
||||||
|
with mock.patch('neutron.objects.logapi.logging_resource.Log',
|
||||||
|
return_value=new_log) as init_log_mock:
|
||||||
|
self.log_plugin.create_log(self.ctxt, log)
|
||||||
|
init_log_mock.assert_called_once_with(
|
||||||
|
context=self.ctxt, **log['log'])
|
||||||
|
self.assertTrue(new_log.create.called)
|
||||||
|
|
||||||
|
def test_create_log_without_parent_resource(self):
|
||||||
|
log = {'log': {'resource_type': 'security_group',
|
||||||
|
'enabled': True,
|
||||||
|
'resource_id': uuidutils.generate_uuid()}}
|
||||||
|
new_log = mock.Mock()
|
||||||
|
new_log.enabled = True
|
||||||
|
sg = mock.Mock()
|
||||||
|
with mock.patch.object(sg_object.SecurityGroup, 'get_object',
|
||||||
|
return_value=sg):
|
||||||
|
with mock.patch('neutron.objects.logapi.logging_resource.Log',
|
||||||
|
return_value=new_log) as init_log_mock:
|
||||||
|
self.log_plugin.create_log(self.ctxt, log)
|
||||||
|
init_log_mock.assert_called_once_with(context=self.ctxt,
|
||||||
|
**log['log'])
|
||||||
|
self.assertTrue(new_log.create.called)
|
||||||
|
|
||||||
|
def test_create_log_without_target(self):
|
||||||
|
log = {'log': {'resource_type': 'security_group',
|
||||||
|
'enabled': True, }}
|
||||||
|
new_log = mock.Mock()
|
||||||
|
new_log.enabled = True
|
||||||
|
with mock.patch('neutron.objects.logapi.'
|
||||||
|
'logging_resource.Log',
|
||||||
|
return_value=new_log) as init_log_mock:
|
||||||
|
self.log_plugin.create_log(self.ctxt, log)
|
||||||
|
init_log_mock.assert_called_once_with(context=self.ctxt,
|
||||||
|
**log['log'])
|
||||||
|
self.assertTrue(new_log.create.called)
|
||||||
|
|
||||||
|
def test_create_log_disabled(self):
|
||||||
|
log_data = {'log': {'resource_type': 'security_group',
|
||||||
|
'enabled': False}}
|
||||||
|
new_log = mock.Mock()
|
||||||
|
new_log.enabled = False
|
||||||
|
with mock.patch('neutron.objects.logapi.'
|
||||||
|
'logging_resource.Log',
|
||||||
|
return_value=new_log) as init_log_mock:
|
||||||
|
self.log_plugin.create_log(self.ctxt, log_data)
|
||||||
|
init_log_mock.assert_called_once_with(
|
||||||
|
context=self.ctxt, **log_data['log'])
|
||||||
|
self.assertTrue(new_log.create.called)
|
||||||
|
|
||||||
|
def test_update_log(self):
|
||||||
|
log_data = {'log': {'enabled': True}}
|
||||||
|
new_log = mock.Mock()
|
||||||
|
new_log.id = uuidutils.generate_uuid()
|
||||||
|
with mock.patch('neutron.objects.logapi.'
|
||||||
|
'logging_resource.Log',
|
||||||
|
return_value=new_log) as update_log_mock:
|
||||||
|
self.log_plugin.update_log(self.ctxt, new_log.id, log_data)
|
||||||
|
update_log_mock.assert_called_once_with(self.ctxt,
|
||||||
|
id=new_log.id)
|
||||||
|
new_log.update_fields.assert_called_once_with(log_data['log'],
|
||||||
|
reset_changes=True)
|
||||||
|
self.assertTrue(new_log.update.called)
|
||||||
|
|
||||||
|
def test_update_log_none_enabled(self):
|
||||||
|
log_data = {'log': {}}
|
||||||
|
new_log = mock.Mock()
|
||||||
|
new_log.id = uuidutils.generate_uuid()
|
||||||
|
with mock.patch('neutron.objects.logapi.'
|
||||||
|
'logging_resource.Log',
|
||||||
|
return_value=new_log) as update_log_mock:
|
||||||
|
self.log_plugin.update_log(self.ctxt, new_log.id, log_data)
|
||||||
|
update_log_mock.assert_called_once_with(self.ctxt,
|
||||||
|
id=new_log.id)
|
||||||
|
new_log.update_fields.assert_called_once_with(log_data['log'],
|
||||||
|
reset_changes=True)
|
||||||
|
self.assertTrue(new_log.update.called)
|
||||||
|
|
||||||
|
def test_delete_log(self):
|
||||||
|
delete_log = mock.Mock()
|
||||||
|
delete_log.id = uuidutils.generate_uuid()
|
||||||
|
with mock.patch.object(log_object.Log, 'get_object',
|
||||||
|
return_value=delete_log) as delete_log_mock:
|
||||||
|
self.log_plugin.delete_log(self.ctxt, delete_log.id)
|
||||||
|
delete_log_mock.assert_called_once_with(self.ctxt,
|
||||||
|
id=delete_log.id)
|
||||||
|
self.assertTrue(delete_log.delete.called)
|
||||||
|
|
||||||
|
def test_delete_nonexistent_log(self):
|
||||||
|
with mock.patch.object(log_object.Log, 'get_object',
|
||||||
|
return_value=None):
|
||||||
|
self.assertRaises(
|
||||||
|
log_exc.LogResourceNotFound,
|
||||||
|
self.log_plugin.delete_log,
|
||||||
|
self.ctxt,
|
||||||
|
mock.ANY)
|
@ -82,6 +82,7 @@ neutron.service_plugins =
|
|||||||
timestamp = neutron.services.timestamp.timestamp_plugin:TimeStampPlugin
|
timestamp = neutron.services.timestamp.timestamp_plugin:TimeStampPlugin
|
||||||
trunk = neutron.services.trunk.plugin:TrunkPlugin
|
trunk = neutron.services.trunk.plugin:TrunkPlugin
|
||||||
loki = neutron.services.loki.loki_plugin:LokiPlugin
|
loki = neutron.services.loki.loki_plugin:LokiPlugin
|
||||||
|
logapi = neutron.services.logapi.logging_plugin:LoggingPlugin
|
||||||
neutron.ml2.type_drivers =
|
neutron.ml2.type_drivers =
|
||||||
flat = neutron.plugins.ml2.drivers.type_flat:FlatTypeDriver
|
flat = neutron.plugins.ml2.drivers.type_flat:FlatTypeDriver
|
||||||
local = neutron.plugins.ml2.drivers.type_local:LocalTypeDriver
|
local = neutron.plugins.ml2.drivers.type_local:LocalTypeDriver
|
||||||
|
Loading…
x
Reference in New Issue
Block a user