[log]: functional test for logging api
This patch performs functional test for logging api. The implementation is based on the logging api for security group spec[1] [1] https://specs.openstack.org/openstack/neutron-specs/specs/pike/logging-API-for-security-group-rules.html Change-Id: I157bdffe29b184c9e31166586f94eac7fa00188e Partially-implements: blueprint security-group-logging Related-Bug: #1468366
This commit is contained in:
parent
7bd8b37e38
commit
dc5293bba6
|
@ -77,7 +77,7 @@ def _add_rule(sg_rules, base, port_range_min=None, port_range_max=None):
|
|||
|
||||
|
||||
class BaseFirewallTestCase(base.BaseSudoTestCase):
|
||||
FAKE_SECURITY_GROUP_ID = 'fake_sg_id'
|
||||
FAKE_SECURITY_GROUP_ID = uuidutils.generate_uuid()
|
||||
MAC_SPOOFED = "fa:16:3e:9a:2f:48"
|
||||
scenarios_iptables = testscenarios.multiply_scenarios(
|
||||
[('IptablesFirewallDriver', {'initialize': 'initialize_iptables',
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
# 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 re
|
||||
|
||||
import mock
|
||||
from neutron_lib import constants
|
||||
from neutron_lib import context as neutron_context
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import testscenarios
|
||||
|
||||
from neutron.agent import firewall
|
||||
from neutron.objects.logapi import logging_resource as log_object
|
||||
from neutron.plugins.ml2.drivers.openvswitch.agent import (
|
||||
ovs_agent_extension_api as ovs_ext_api)
|
||||
from neutron.plugins.ml2.drivers.openvswitch.agent.common import (
|
||||
constants as ovs_consts)
|
||||
from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.ovs_ofctl import (
|
||||
ovs_bridge)
|
||||
from neutron.services.logapi.drivers.openvswitch import (
|
||||
ovs_firewall_log as ovs_fw_log)
|
||||
from neutron.tests.functional.agent import test_firewall
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
load_tests = testscenarios.load_tests_apply_scenarios
|
||||
|
||||
FAKE_LOG_ID = 'a2d72369-4246-4f19-bd3c-af51ec8d70cd'
|
||||
FAKE_PROJECT_ID = 'fake_project'
|
||||
|
||||
log_object_dict = {
|
||||
'id': FAKE_LOG_ID,
|
||||
'resource_type': 'security_group',
|
||||
'project_id': FAKE_PROJECT_ID,
|
||||
'event': 'ALL'
|
||||
}
|
||||
FAKE_LOG_OBJECT = log_object.Log(**log_object_dict)
|
||||
|
||||
|
||||
class LoggingExtensionTestFramework(test_firewall.BaseFirewallTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(LoggingExtensionTestFramework, self).setUp()
|
||||
cfg.CONF.set_override('extensions', ['log'], group='agent')
|
||||
self.context = neutron_context.get_admin_context_without_session()
|
||||
self._set_resource_rpc_mock()
|
||||
if self.firewall_name != 'openvswitch':
|
||||
self.skipTest("Logging extension doesn't support firewall driver"
|
||||
" %s at that time " % self.firewall_name)
|
||||
self.log_driver = self.initialize_ovs_fw_log()
|
||||
|
||||
def initialize_ovs_fw_log(self):
|
||||
int_br = ovs_ext_api.OVSCookieBridge(ovs_bridge.OVSAgentBridge(
|
||||
self.tester.bridge.br_name))
|
||||
mock.patch('ryu.base.app_manager.AppManager.get_instance').start()
|
||||
mock.patch('neutron.agent.ovsdb.api.API.transaction').start()
|
||||
log_driver = ovs_fw_log.OVSFirewallLoggingDriver(int_br)
|
||||
log_driver.initialize(self.resource_rpc)
|
||||
return log_driver
|
||||
|
||||
def _set_resource_rpc_mock(self):
|
||||
self.log_info = []
|
||||
|
||||
def _get_sg_info_mock(context, **kwargs):
|
||||
return self.log_info
|
||||
|
||||
self.resource_rpc = mock.patch(
|
||||
'neutron.services.logapi.rpc.agent.LoggingApiStub').start()
|
||||
self.resource_rpc.get_sg_log_info_for_log_resources.side_effect = (
|
||||
_get_sg_info_mock)
|
||||
|
||||
def _set_ports_log(self, sg_rules):
|
||||
fake_sg_log_info = [
|
||||
{
|
||||
'id': FAKE_LOG_ID,
|
||||
'ports_log': [
|
||||
{'port_id': self.src_port_desc['device'],
|
||||
'security_group_rules': sg_rules}],
|
||||
'event': 'ALL',
|
||||
'project_id': FAKE_PROJECT_ID
|
||||
}]
|
||||
self.log_info = fake_sg_log_info
|
||||
|
||||
|
||||
class TestLoggingExtension(LoggingExtensionTestFramework):
|
||||
|
||||
ip_cidr = '192.168.0.1/24'
|
||||
|
||||
def _is_log_flow_set(self, table):
|
||||
flows = self.log_driver.int_br.br.dump_flows_for_table(table)
|
||||
pattern = re.compile(
|
||||
r"^.* table=%s.* actions=CONTROLLER:65535" % table
|
||||
)
|
||||
for flow in flows.splitlines():
|
||||
if pattern.match(flow.strip()):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _assert_logging_flows_set(self):
|
||||
self.assertTrue(self._is_log_flow_set(
|
||||
table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE))
|
||||
self.assertTrue(self._is_log_flow_set(
|
||||
table=ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE))
|
||||
self.assertTrue(self._is_log_flow_set(
|
||||
table=ovs_consts.DROPPED_TRAFFIC_TABLE))
|
||||
|
||||
def _assert_logging_flows_not_set(self):
|
||||
self.assertFalse(self._is_log_flow_set(
|
||||
table=ovs_consts.ACCEPTED_EGRESS_TRAFFIC_TABLE))
|
||||
self.assertFalse(self._is_log_flow_set(
|
||||
table=ovs_consts.ACCEPTED_INGRESS_TRAFFIC_TABLE))
|
||||
self.assertFalse(self._is_log_flow_set(
|
||||
table=ovs_consts.DROPPED_TRAFFIC_TABLE))
|
||||
|
||||
def test_log_lifecycle(self):
|
||||
sg_rules = [{'ethertype': constants.IPv4,
|
||||
'direction': firewall.INGRESS_DIRECTION,
|
||||
'protocol': constants.PROTO_NAME_ICMP,
|
||||
'security_group_id': self.FAKE_SECURITY_GROUP_ID},
|
||||
{'ethertype': constants.IPv4,
|
||||
'direction': firewall.EGRESS_DIRECTION,
|
||||
'security_group_id': self.FAKE_SECURITY_GROUP_ID},
|
||||
{'ethertype': constants.IPv6,
|
||||
'protocol': constants.PROTO_NAME_TCP,
|
||||
'port_range_min': 22,
|
||||
'port_range_max': 22,
|
||||
'remote_group_id': 2,
|
||||
'direction': firewall.EGRESS_DIRECTION,
|
||||
'security_group_id': self.FAKE_SECURITY_GROUP_ID},
|
||||
]
|
||||
self.firewall.update_security_group_rules(
|
||||
self.FAKE_SECURITY_GROUP_ID, sg_rules)
|
||||
self.firewall.update_port_filter(self.src_port_desc)
|
||||
self._set_ports_log(sg_rules)
|
||||
|
||||
# start log
|
||||
self.log_driver.start_logging(
|
||||
self.context, log_resources=[FAKE_LOG_OBJECT])
|
||||
self._assert_logging_flows_set()
|
||||
|
||||
# stop log
|
||||
self.log_driver.stop_logging(
|
||||
self.context, log_resources=[FAKE_LOG_OBJECT])
|
||||
self._assert_logging_flows_not_set()
|
Loading…
Reference in New Issue