Add fullstack test for logging
Since Queens, the security group logging has been merged. But there is no fullstack test for this feature. So this patch add fullstack test to avoid regression as https://review.openstack.org/#/c/587681 Co-Authored-By: Yushiro FURUKAWA <y.furukawa_2@jp.fujitsu.com> Change-Id: Id9bbedc96e399338ea568556bdb17923392512b4 Partially-implements: blueprint security-group-logging
This commit is contained in:
parent
9feb5db61c
commit
0649112113
|
@ -301,3 +301,16 @@ class ClientFixture(fixtures.Fixture):
|
|||
spec.update(kwargs)
|
||||
|
||||
return self._create_resource(resource_type, spec)
|
||||
|
||||
def create_network_log(self, tenant_id, resource_type,
|
||||
enabled=True, **kwargs):
|
||||
|
||||
spec = {'project_id': tenant_id,
|
||||
'resource_type': resource_type,
|
||||
'enabled': enabled}
|
||||
spec.update(kwargs)
|
||||
|
||||
net_log = self.client.create_network_log({'log': spec})
|
||||
self.addCleanup(
|
||||
_safe_method(self.client.delete_network_log), net_log['log']['id'])
|
||||
return net_log
|
||||
|
|
|
@ -23,6 +23,7 @@ from neutron.plugins.ml2.extensions import qos as qos_ext
|
|||
from neutron.tests.common import config_fixtures
|
||||
from neutron.tests.common.exclusive_resources import port
|
||||
from neutron.tests.common import helpers as c_helpers
|
||||
from neutron.tests.fullstack import base as fullstack_base
|
||||
|
||||
PHYSICAL_NETWORK_NAME = "physnet1"
|
||||
|
||||
|
@ -154,7 +155,7 @@ class ML2ConfigFixture(ConfigFixture):
|
|||
|
||||
class OVSConfigFixture(ConfigFixture):
|
||||
|
||||
def __init__(self, env_desc, host_desc, temp_dir, local_ip):
|
||||
def __init__(self, env_desc, host_desc, temp_dir, local_ip, **kwargs):
|
||||
super(OVSConfigFixture, self).__init__(
|
||||
env_desc, host_desc, temp_dir,
|
||||
base_filename='openvswitch_agent.ini')
|
||||
|
@ -189,6 +190,14 @@ class OVSConfigFixture(ConfigFixture):
|
|||
|
||||
if env_desc.qos:
|
||||
self.config['agent']['extensions'] = 'qos'
|
||||
if env_desc.log:
|
||||
self.config['agent']['extensions'] = 'log'
|
||||
test_name = kwargs.get("test_name")
|
||||
self.config.update({
|
||||
'network_log': {
|
||||
'local_output_log_base':
|
||||
self._generate_temp_log_file(test_name)}
|
||||
})
|
||||
|
||||
def _setUp(self):
|
||||
if self.config['ovs']['of_interface'] == 'native':
|
||||
|
@ -214,6 +223,13 @@ class OVSConfigFixture(ConfigFixture):
|
|||
def _generate_tun_peer(self):
|
||||
return utils.get_rand_device_name(prefix='patch-int')
|
||||
|
||||
def _generate_temp_log_file(self, test_name):
|
||||
log_dir_path = fullstack_base.DEFAULT_LOG_DIR + '/' + test_name
|
||||
if not os.path.exists(log_dir_path):
|
||||
os.mkdir(log_dir_path, 0o755)
|
||||
return '%s/%s.log' % (log_dir_path,
|
||||
utils.get_rand_name(prefix="test-sg-"))
|
||||
|
||||
def get_br_int_name(self):
|
||||
return self.config.ovs.integration_bridge
|
||||
|
||||
|
|
|
@ -39,10 +39,11 @@ class EnvironmentDescription(object):
|
|||
service_plugins='router', arp_responder=False,
|
||||
agent_down_time=75, router_scheduler=None,
|
||||
global_mtu=common_const.DEFAULT_NETWORK_MTU,
|
||||
debug_iptables=False):
|
||||
debug_iptables=False, log=False):
|
||||
self.network_type = network_type
|
||||
self.l2_pop = l2_pop
|
||||
self.qos = qos
|
||||
self.log = log
|
||||
self.network_range = None
|
||||
self.mech_drivers = mech_drivers
|
||||
self.arp_responder = arp_responder
|
||||
|
@ -53,6 +54,8 @@ class EnvironmentDescription(object):
|
|||
self.debug_iptables = debug_iptables
|
||||
if self.qos:
|
||||
self.service_plugins += ',qos'
|
||||
if self.log:
|
||||
self.service_plugins += ',log'
|
||||
|
||||
@property
|
||||
def tunneling_enabled(self):
|
||||
|
@ -134,7 +137,7 @@ class Host(fixtures.Fixture):
|
|||
def setup_host_with_ovs_agent(self):
|
||||
agent_cfg_fixture = config.OVSConfigFixture(
|
||||
self.env_desc, self.host_desc, self.neutron_config.temp_dir,
|
||||
self.local_ip)
|
||||
self.local_ip, test_name=self.test_name)
|
||||
self.useFixture(agent_cfg_fixture)
|
||||
|
||||
if self.env_desc.tunneling_enabled:
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
# Copyright 2018 Fujitsu Limited
|
||||
#
|
||||
# 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
|
||||
|
||||
from neutron_lib import constants
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from neutron.common import utils
|
||||
from neutron.plugins.ml2.drivers.openvswitch.agent.common import (
|
||||
constants as ovs_const)
|
||||
from neutron.tests.common import net_helpers
|
||||
from neutron.tests.fullstack import base
|
||||
from neutron.tests.fullstack.resources import environment
|
||||
from neutron.tests.fullstack.resources import machine
|
||||
from neutron.tests.unit import testlib_api
|
||||
|
||||
load_tests = testlib_api.module_load_tests
|
||||
|
||||
|
||||
class BaseLoggingTestCase(base.BaseFullStackTestCase):
|
||||
of_interface = None
|
||||
number_of_hosts = 1
|
||||
|
||||
def setUp(self):
|
||||
host_desc = [
|
||||
environment.HostDescription(
|
||||
of_interface=self.of_interface,
|
||||
l2_agent_type=constants.AGENT_TYPE_OVS,
|
||||
firewall_driver='openvswitch',
|
||||
dhcp_agent=True) for _ in range(self.number_of_hosts)]
|
||||
env_desc = environment.EnvironmentDescription(
|
||||
mech_drivers='openvswitch', log=True)
|
||||
env = environment.Environment(env_desc, host_desc)
|
||||
super(BaseLoggingTestCase, self).setUp(env)
|
||||
|
||||
self.tenant_id = uuidutils.generate_uuid()
|
||||
self.network = self.safe_client.create_network(
|
||||
self.tenant_id, 'network-test')
|
||||
self.subnet = self.safe_client.create_subnet(
|
||||
self.tenant_id, self.network['id'],
|
||||
cidr='10.0.0.0/24',
|
||||
gateway_ip='10.0.0.1',
|
||||
name='subnet-test')
|
||||
|
||||
def assert_no_connection(self, *args, **kwargs):
|
||||
netcat = net_helpers.NetcatTester(*args, **kwargs)
|
||||
try:
|
||||
utils.wait_until_true(netcat.test_no_connectivity)
|
||||
finally:
|
||||
netcat.stop_processes()
|
||||
|
||||
def _wait_for_log_rules_applied(self, vm, table, actions):
|
||||
|
||||
def _is_log_flow_set(table, actions):
|
||||
flows = vm.bridge.dump_flows_for_table(table)
|
||||
flows_list = flows.splitlines()
|
||||
pattern = re.compile(
|
||||
r"^.* table=%s.* actions=%s" % (table, actions))
|
||||
for flow in flows_list:
|
||||
if pattern.match(flow.strip()):
|
||||
return True
|
||||
return False
|
||||
utils.wait_until_true(lambda: _is_log_flow_set(table, actions))
|
||||
|
||||
def _check_log(self, log_id, action, regex_str=None):
|
||||
|
||||
config = self.environment.hosts[0].ovs_agent.agent_config
|
||||
|
||||
def _is_log_event(log_id, action, regex_str):
|
||||
regex_p = re.compile(
|
||||
r"^.*action=%s.* log_resource_ids=\[[^\]]*%s" % (
|
||||
action, log_id) + ".*" + regex_str if regex_str else "")
|
||||
|
||||
with open(config.network_log.local_output_log_base) as f:
|
||||
for line in f.readlines():
|
||||
if regex_p.match(line):
|
||||
return True
|
||||
return False
|
||||
|
||||
utils.wait_until_true(lambda: _is_log_event(log_id, action, regex_str))
|
||||
|
||||
|
||||
class TestLogging(BaseLoggingTestCase):
|
||||
|
||||
scenarios = [
|
||||
('ovs-openflow-native', {
|
||||
'of_interface': 'native'})]
|
||||
|
||||
def _create_network_log(self, resource_type,
|
||||
resource_id=None, target_id=None):
|
||||
return self.safe_client.create_network_log(
|
||||
tenant_id=self.tenant_id,
|
||||
name='test-log',
|
||||
resource_type=resource_type,
|
||||
resource_id=resource_id,
|
||||
target_id=target_id)
|
||||
|
||||
def _prepare_vms(self):
|
||||
|
||||
sgs = [self.safe_client.create_security_group(self.tenant_id)
|
||||
for i in range(2)]
|
||||
|
||||
port1 = self.safe_client.create_port(
|
||||
self.tenant_id, self.network['id'],
|
||||
self.environment.hosts[0].hostname,
|
||||
security_groups=[sgs[0]['id']])
|
||||
|
||||
port2 = self.safe_client.create_port(
|
||||
self.tenant_id, self.network['id'],
|
||||
self.environment.hosts[0].hostname,
|
||||
security_groups=[sgs[1]['id']])
|
||||
|
||||
# insert security-group-rules allow icmp
|
||||
self.safe_client.create_security_group_rule(
|
||||
self.tenant_id, sgs[0]['id'],
|
||||
direction=constants.INGRESS_DIRECTION,
|
||||
ethertype=constants.IPv4,
|
||||
protocol=constants.PROTO_NAME_ICMP)
|
||||
|
||||
# insert security-group-rules allow icmp
|
||||
self.safe_client.create_security_group_rule(
|
||||
self.tenant_id, sgs[1]['id'],
|
||||
direction=constants.INGRESS_DIRECTION,
|
||||
ethertype=constants.IPv4,
|
||||
protocol=constants.PROTO_NAME_ICMP)
|
||||
|
||||
vm1 = self.useFixture(
|
||||
machine.FakeFullstackMachine(
|
||||
self.environment.hosts[0],
|
||||
self.network['id'],
|
||||
self.tenant_id,
|
||||
self.safe_client,
|
||||
neutron_port=port1))
|
||||
|
||||
vm2 = self.useFixture(
|
||||
machine.FakeFullstackMachine(
|
||||
self.environment.hosts[0],
|
||||
self.network['id'],
|
||||
self.tenant_id,
|
||||
self.safe_client,
|
||||
neutron_port=port2))
|
||||
return machine.FakeFullstackMachinesList([vm1, vm2])
|
||||
|
||||
def test_logging(self):
|
||||
vms = self._prepare_vms()
|
||||
|
||||
vms.block_until_all_boot()
|
||||
|
||||
sg_log = self._create_network_log(resource_type='security_group')
|
||||
log_id = sg_log['log']['id']
|
||||
for vm in vms:
|
||||
self._wait_for_log_rules_applied(
|
||||
vm, ovs_const.ACCEPTED_EGRESS_TRAFFIC_TABLE,
|
||||
actions=r"resubmit\(,%d\),CONTROLLER:65535" % (
|
||||
ovs_const.ACCEPTED_EGRESS_TRAFFIC_NORMAL_TABLE))
|
||||
self._wait_for_log_rules_applied(
|
||||
vm, ovs_const.ACCEPTED_INGRESS_TRAFFIC_TABLE,
|
||||
actions="CONTROLLER:65535")
|
||||
self._wait_for_log_rules_applied(
|
||||
vm, ovs_const.DROPPED_TRAFFIC_TABLE,
|
||||
actions="CONTROLLER:65535")
|
||||
|
||||
# ping all vm
|
||||
vms.ping_all()
|
||||
|
||||
# check log accept packets for icmp
|
||||
self._check_log(log_id=log_id, action='ACCEPT')
|
||||
|
||||
# Try to connect from VM1 to VM2 via ssh
|
||||
self.assert_no_connection(
|
||||
vms[0].namespace, vms[1].namespace, vms[1].ip, 22,
|
||||
net_helpers.NetcatTester.TCP)
|
||||
|
||||
# Try to ssh from VM2 to VM1 via ssh
|
||||
self.assert_no_connection(
|
||||
vms[1].namespace, vms[0].namespace, vms[0].ip, 22,
|
||||
net_helpers.NetcatTester.TCP)
|
||||
|
||||
# check log drop packets for ssh
|
||||
self._check_log(log_id=log_id, action='DROP', regex_str="dst_port=22")
|
Loading…
Reference in New Issue