425 lines
16 KiB
Python
425 lines
16 KiB
Python
# Copyright 2015 Red Hat, Inc.
|
|
#
|
|
# 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 os
|
|
import shutil
|
|
import tempfile
|
|
|
|
from neutron_lib import constants
|
|
|
|
from neutron.common import constants as c_const
|
|
from neutron.common import utils
|
|
from neutron.plugins.ml2.extensions import qos as qos_ext
|
|
from neutron.tests import base
|
|
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"
|
|
MINIMUM_BANDWIDTH_INGRESS_KBPS = 1000
|
|
MINIMUM_BANDWIDTH_EGRESS_KBPS = 1000
|
|
|
|
|
|
class ConfigFixture(config_fixtures.ConfigFileFixture):
|
|
"""A fixture that holds an actual Neutron configuration.
|
|
|
|
Note that 'self.config' is intended to only be updated once, during
|
|
the constructor, so if this fixture is re-used (setUp is called twice),
|
|
then the dynamic configuration values won't change. The correct usage
|
|
is initializing a new instance of the class.
|
|
"""
|
|
def __init__(self, env_desc, host_desc, temp_dir, base_filename):
|
|
super(ConfigFixture, self).__init__(
|
|
base_filename, config_fixtures.ConfigDict(), temp_dir)
|
|
self.env_desc = env_desc
|
|
self.host_desc = host_desc
|
|
|
|
def _generate_namespace_suffix(self):
|
|
return utils.get_rand_name(prefix='test')
|
|
|
|
|
|
class NeutronConfigFixture(ConfigFixture):
|
|
|
|
def __init__(self, env_desc, host_desc, temp_dir,
|
|
connection, rabbitmq_environment):
|
|
super(NeutronConfigFixture, self).__init__(
|
|
env_desc, host_desc, temp_dir, base_filename='neutron.conf')
|
|
|
|
self.config.update({
|
|
'DEFAULT': {
|
|
'host': self._generate_host(),
|
|
'state_path': self._generate_state_path(self.temp_dir),
|
|
'api_paste_config': self._generate_api_paste(),
|
|
'core_plugin': 'ml2',
|
|
'service_plugins': env_desc.service_plugins,
|
|
'auth_strategy': 'noauth',
|
|
'debug': 'True',
|
|
'global_physnet_mtu': str(env_desc.global_mtu),
|
|
'agent_down_time': str(env_desc.agent_down_time),
|
|
'transport_url':
|
|
'rabbit://%(user)s:%(password)s@%(host)s:5672/%(vhost)s' %
|
|
{'user': rabbitmq_environment.user,
|
|
'password': rabbitmq_environment.password,
|
|
'host': rabbitmq_environment.host,
|
|
'vhost': rabbitmq_environment.vhost},
|
|
'api_workers': '2',
|
|
},
|
|
'database': {
|
|
'connection': connection,
|
|
},
|
|
'oslo_concurrency': {
|
|
'lock_path': '$state_path/lock',
|
|
},
|
|
'agent': {
|
|
'report_interval': str(env_desc.agent_down_time / 2.0),
|
|
'log_agent_heartbeats': 'True',
|
|
},
|
|
})
|
|
policy_file = self._generate_policy_json()
|
|
if policy_file:
|
|
self.config['oslo_policy'] = {'policy_file': policy_file}
|
|
|
|
# Set root_helper/root_helper_daemon only when env var is set
|
|
root_helper = os.environ.get('OS_ROOTWRAP_CMD')
|
|
if root_helper:
|
|
self.config['agent']['root_helper'] = root_helper
|
|
root_helper_daemon = os.environ.get('OS_ROOTWRAP_DAEMON_CMD')
|
|
if root_helper_daemon:
|
|
self.config['agent']['root_helper_daemon'] = root_helper_daemon
|
|
if env_desc.router_scheduler:
|
|
self.config['DEFAULT']['router_scheduler_driver'] = (
|
|
env_desc.router_scheduler)
|
|
|
|
def _setUp(self):
|
|
self.config['DEFAULT'].update({
|
|
'bind_port': self.useFixture(
|
|
port.ExclusivePort(constants.PROTO_NAME_TCP)).port
|
|
})
|
|
super(NeutronConfigFixture, self)._setUp()
|
|
|
|
def _generate_host(self):
|
|
return utils.get_rand_name(prefix='host-')
|
|
|
|
def _generate_state_path(self, temp_dir):
|
|
# Assume that temp_dir will be removed by the caller
|
|
self.state_path = tempfile.mkdtemp(prefix='state_path', dir=temp_dir)
|
|
return self.state_path
|
|
|
|
def _generate_api_paste(self):
|
|
return c_helpers.find_sample_file('api-paste.ini')
|
|
|
|
def _generate_policy_json(self):
|
|
return c_helpers.find_sample_file('policy.json')
|
|
|
|
def get_host(self):
|
|
return self.config['DEFAULT']['host']
|
|
|
|
|
|
class ML2ConfigFixture(ConfigFixture):
|
|
|
|
def __init__(self, env_desc, host_desc, temp_dir, tenant_network_types):
|
|
super(ML2ConfigFixture, self).__init__(
|
|
env_desc, host_desc, temp_dir, base_filename='ml2_conf.ini')
|
|
|
|
mechanism_drivers = self.env_desc.mech_drivers
|
|
if self.env_desc.l2_pop:
|
|
mechanism_drivers += ',l2population'
|
|
|
|
self.config.update({
|
|
'ml2': {
|
|
'tenant_network_types': tenant_network_types,
|
|
'mechanism_drivers': mechanism_drivers,
|
|
},
|
|
'ml2_type_vlan': {
|
|
'network_vlan_ranges': PHYSICAL_NETWORK_NAME + ':1000:2999',
|
|
},
|
|
'ml2_type_gre': {
|
|
'tunnel_id_ranges': '1:1000',
|
|
},
|
|
'ml2_type_vxlan': {
|
|
'vni_ranges': '1001:2000',
|
|
},
|
|
})
|
|
|
|
extension_drivers = {'port_security'}
|
|
if env_desc.qos:
|
|
extension_drivers.add(qos_ext.QOS_EXT_DRIVER_ALIAS)
|
|
if env_desc.ml2_extension_drivers:
|
|
extension_drivers.update(env_desc.ml2_extension_drivers)
|
|
self.config['ml2']['extension_drivers'] = ','.join(extension_drivers)
|
|
|
|
|
|
class OVSConfigFixture(ConfigFixture):
|
|
|
|
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')
|
|
|
|
self.tunneling_enabled = self.env_desc.tunneling_enabled
|
|
ext_dev = utils.get_rand_device_name(prefix='br-eth')
|
|
self.config.update({
|
|
'ovs': {
|
|
'local_ip': local_ip,
|
|
'integration_bridge': self._generate_integration_bridge(),
|
|
'of_interface': host_desc.of_interface,
|
|
'bridge_mappings': '%s:%s' % (PHYSICAL_NETWORK_NAME, ext_dev),
|
|
'of_inactivity_probe': '0',
|
|
},
|
|
'securitygroup': {
|
|
'firewall_driver': host_desc.firewall_driver,
|
|
},
|
|
'agent': {
|
|
'l2_population': str(self.env_desc.l2_pop),
|
|
'arp_responder': str(self.env_desc.arp_responder),
|
|
'debug_iptables_rules': str(env_desc.debug_iptables),
|
|
'use_helper_for_ns_read': 'False',
|
|
}
|
|
})
|
|
|
|
if self.tunneling_enabled:
|
|
self.config['agent'].update({
|
|
'tunnel_types': self.env_desc.network_type})
|
|
self.config['ovs'].update({
|
|
'tunnel_bridge': self._generate_tunnel_bridge(),
|
|
'int_peer_patch_port': self._generate_int_peer(),
|
|
'tun_peer_patch_port': self._generate_tun_peer()})
|
|
else:
|
|
if env_desc.report_bandwidths:
|
|
self.config['ovs'][c_const.RP_BANDWIDTHS] = \
|
|
'%s:%s:%s' % (ext_dev, MINIMUM_BANDWIDTH_EGRESS_KBPS,
|
|
MINIMUM_BANDWIDTH_INGRESS_KBPS)
|
|
|
|
if env_desc.qos:
|
|
self.config['agent']['extensions'] = 'qos'
|
|
if env_desc.log:
|
|
self.config['agent']['extensions'] = 'log'
|
|
test_name = kwargs.get("test_name")
|
|
test_name = base.sanitize_log_path(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':
|
|
self.config['ovs'].update({
|
|
'of_listen_port': self.useFixture(
|
|
port.ExclusivePort(constants.PROTO_NAME_TCP)).port
|
|
})
|
|
super(OVSConfigFixture, self)._setUp()
|
|
|
|
def _generate_integration_bridge(self):
|
|
return utils.get_rand_device_name(prefix='br-int')
|
|
|
|
def _generate_tunnel_bridge(self):
|
|
return utils.get_rand_device_name(prefix='br-tun')
|
|
|
|
def _generate_int_peer(self):
|
|
return utils.get_rand_device_name(prefix='patch-tun')
|
|
|
|
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 = os.path.join(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
|
|
|
|
def get_br_phys_name(self):
|
|
return self.config.ovs.bridge_mappings.split(':')[1]
|
|
|
|
def get_br_tun_name(self):
|
|
return self.config.ovs.tunnel_bridge
|
|
|
|
|
|
class SRIOVConfigFixture(ConfigFixture):
|
|
def __init__(self, env_desc, host_desc, temp_dir, local_ip):
|
|
super(SRIOVConfigFixture, self).__init__(
|
|
env_desc, host_desc, temp_dir,
|
|
base_filename='sriov_agent.ini')
|
|
|
|
device1 = utils.get_rand_device_name(prefix='ens5')
|
|
device2 = utils.get_rand_device_name(prefix='ens6')
|
|
phys_dev_mapping = '%s:%s,%s:%s' % (PHYSICAL_NETWORK_NAME, device1,
|
|
PHYSICAL_NETWORK_NAME, device2)
|
|
rp_bandwidths = '%s:%s:%s,%s:%s:%s' % (device1,
|
|
MINIMUM_BANDWIDTH_EGRESS_KBPS,
|
|
MINIMUM_BANDWIDTH_INGRESS_KBPS,
|
|
device2,
|
|
MINIMUM_BANDWIDTH_EGRESS_KBPS,
|
|
MINIMUM_BANDWIDTH_INGRESS_KBPS)
|
|
self.config.update({
|
|
'sriov_nic': {
|
|
'physical_device_mappings': phys_dev_mapping,
|
|
'resource_provider_bandwidths': rp_bandwidths,
|
|
}
|
|
})
|
|
|
|
def _setUp(self):
|
|
super(SRIOVConfigFixture, self)._setUp()
|
|
|
|
|
|
class LinuxBridgeConfigFixture(ConfigFixture):
|
|
|
|
def __init__(self, env_desc, host_desc, temp_dir, local_ip,
|
|
physical_device_name):
|
|
super(LinuxBridgeConfigFixture, self).__init__(
|
|
env_desc, host_desc, temp_dir,
|
|
base_filename="linuxbridge_agent.ini"
|
|
)
|
|
self.config.update({
|
|
'VXLAN': {
|
|
'enable_vxlan': str(self.env_desc.tunneling_enabled),
|
|
'local_ip': local_ip,
|
|
'l2_population': str(self.env_desc.l2_pop),
|
|
},
|
|
'securitygroup': {
|
|
'firewall_driver': host_desc.firewall_driver,
|
|
},
|
|
'AGENT': {
|
|
'debug_iptables_rules': str(env_desc.debug_iptables),
|
|
'use_helper_for_ns_read': 'False',
|
|
}
|
|
})
|
|
if env_desc.qos:
|
|
self.config.update({
|
|
'AGENT': {
|
|
'extensions': 'qos'
|
|
}
|
|
})
|
|
if self.env_desc.tunneling_enabled:
|
|
self.config.update({
|
|
'LINUX_BRIDGE': {
|
|
'bridge_mappings': self._generate_bridge_mappings(
|
|
physical_device_name
|
|
)
|
|
}
|
|
})
|
|
else:
|
|
self.config.update({
|
|
'LINUX_BRIDGE': {
|
|
'physical_interface_mappings':
|
|
self._generate_bridge_mappings(
|
|
physical_device_name
|
|
)
|
|
}
|
|
})
|
|
|
|
def _generate_bridge_mappings(self, device_name):
|
|
return '%s:%s' % (PHYSICAL_NETWORK_NAME, device_name)
|
|
|
|
|
|
class L3ConfigFixture(ConfigFixture):
|
|
|
|
def __init__(self, env_desc, host_desc, temp_dir, integration_bridge=None):
|
|
super(L3ConfigFixture, self).__init__(
|
|
env_desc, host_desc, temp_dir, base_filename='l3_agent.ini')
|
|
if host_desc.l2_agent_type == constants.AGENT_TYPE_OVS:
|
|
self._prepare_config_with_ovs_agent(integration_bridge)
|
|
elif host_desc.l2_agent_type == constants.AGENT_TYPE_LINUXBRIDGE:
|
|
self._prepare_config_with_linuxbridge_agent()
|
|
if host_desc.l3_agent_mode:
|
|
self.config['DEFAULT'].update({
|
|
'agent_mode': host_desc.l3_agent_mode})
|
|
self.config['DEFAULT'].update({
|
|
'debug': 'True',
|
|
'test_namespace_suffix': self._generate_namespace_suffix(),
|
|
})
|
|
self.config.update({
|
|
'agent': {'use_helper_for_ns_read': 'False'}
|
|
})
|
|
if host_desc.availability_zone:
|
|
self.config['agent'].update({
|
|
'availability_zone': host_desc.availability_zone
|
|
})
|
|
|
|
def _prepare_config_with_ovs_agent(self, integration_bridge):
|
|
self.config.update({
|
|
'DEFAULT': {
|
|
'interface_driver': ('neutron.agent.linux.interface.'
|
|
'OVSInterfaceDriver'),
|
|
'ovs_integration_bridge': integration_bridge,
|
|
}
|
|
})
|
|
|
|
def _prepare_config_with_linuxbridge_agent(self):
|
|
self.config.update({
|
|
'DEFAULT': {
|
|
'interface_driver': ('neutron.agent.linux.interface.'
|
|
'BridgeInterfaceDriver'),
|
|
}
|
|
})
|
|
|
|
|
|
class DhcpConfigFixture(ConfigFixture):
|
|
|
|
def __init__(self, env_desc, host_desc, temp_dir, integration_bridge=None):
|
|
super(DhcpConfigFixture, self).__init__(
|
|
env_desc, host_desc, temp_dir, base_filename='dhcp_agent.ini')
|
|
|
|
if host_desc.l2_agent_type == constants.AGENT_TYPE_OVS:
|
|
self._prepare_config_with_ovs_agent(integration_bridge)
|
|
elif host_desc.l2_agent_type == constants.AGENT_TYPE_LINUXBRIDGE:
|
|
self._prepare_config_with_linuxbridge_agent()
|
|
self.config['DEFAULT'].update({
|
|
'debug': 'True',
|
|
'dhcp_confs': self._generate_dhcp_path(),
|
|
'test_namespace_suffix': self._generate_namespace_suffix()
|
|
})
|
|
self.config.update({
|
|
'AGENT': {'use_helper_for_ns_read': 'False'}
|
|
})
|
|
if host_desc.availability_zone:
|
|
self.config['AGENT'].update({
|
|
'availability_zone': host_desc.availability_zone
|
|
})
|
|
|
|
def _setUp(self):
|
|
super(DhcpConfigFixture, self)._setUp()
|
|
self.addCleanup(self._clean_dhcp_path)
|
|
|
|
def _prepare_config_with_ovs_agent(self, integration_bridge):
|
|
self.config.update({
|
|
'DEFAULT': {
|
|
'interface_driver': 'openvswitch',
|
|
'ovs_integration_bridge': integration_bridge,
|
|
}
|
|
})
|
|
|
|
def _prepare_config_with_linuxbridge_agent(self):
|
|
self.config.update({
|
|
'DEFAULT': {
|
|
'interface_driver': 'linuxbridge',
|
|
}
|
|
})
|
|
|
|
def _generate_dhcp_path(self):
|
|
# NOTE(slaweq): dhcp_conf path needs to be directory with read
|
|
# permission for everyone, otherwise dnsmasq process will not be able
|
|
# to read his configs
|
|
self.dhcp_path = tempfile.mkdtemp(prefix="dhcp_configs_", dir="/tmp/")
|
|
os.chmod(self.dhcp_path, 0o755)
|
|
return self.dhcp_path
|
|
|
|
def _clean_dhcp_path(self):
|
|
shutil.rmtree(self.dhcp_path, ignore_errors=True)
|