class OVSBridgeFixture(fixtures.Fixture):
"""Create an OVS bridge.
+ :ivar prefix: bridge name prefix
+ :type prefix: str
:ivar bridge: created bridge
:type bridge: OVSBridge
"""
+ def __init__(self, prefix=BR_PREFIX):
+ self.prefix = prefix
+
def setUp(self):
super(OVSBridgeFixture, self).setUp()
ovs = ovs_lib.BaseOVS()
- self.bridge = common_base.create_resource(BR_PREFIX, ovs.add_bridge)
+ self.bridge = common_base.create_resource(self.prefix, ovs.add_bridge)
self.addCleanup(self.bridge.destroy)
class BaseFullStackTestCase(test_base.MySQLOpportunisticTestCase):
- """Base test class for full-stack tests.
+ """Base test class for full-stack tests."""
- :param process_fixtures: a list of fixture classes (not instances).
- """
+ def __init__(self, environment=None, *args, **kwargs):
+ super(BaseFullStackTestCase, self).__init__(*args, **kwargs)
+ self.environment = (environment if environment
+ else f_fixtures.EnvironmentFixture())
def setUp(self):
super(BaseFullStackTestCase, self).setUp()
self.create_db_tables()
- self.neutron_server = self.useFixture(
- f_fixtures.NeutronServerFixture())
- self.client = self.neutron_server.client
+ if self.environment:
+ self.useFixture(self.environment)
- @property
- def test_name(self):
- """Return the name of the test currently running."""
- return self.id().split(".")[-1]
+ self.client = self.environment.neutron_server.client
def create_db_tables(self):
"""Populate the new database.
'DEFAULT': {
'host': self._generate_host(),
'state_path': self._generate_state_path(temp_dir),
+ 'lock_path': '$state_path/lock',
'bind_port': self._generate_port(),
'api_paste_config': self._generate_api_paste(),
'policy_file': self._generate_policy_json(),
'core_plugin': 'neutron.plugins.ml2.plugin.Ml2Plugin',
+ 'service_plugins': ('neutron.services.l3_router.'
+ 'l3_router_plugin.L3RouterPlugin'),
'rabbit_userid': 'stackrabbit',
- 'rabbit_password': 'secretrabbit',
+ 'rabbit_password': '127.0.0.1',
'rabbit_hosts': '127.0.0.1',
'auth_strategy': 'noauth',
'verbose': 'True',
'local_ip': '127.0.0.1',
'bridge_mappings': self._generate_bridge_mappings(),
'integration_bridge': self._generate_integration_bridge(),
+ },
+ 'securitygroup': {
+ 'firewall_driver': ('neutron.agent.linux.iptables_firewall.'
+ 'OVSHybridIptablesFirewallDriver'),
}
})
def _generate_integration_bridge(self):
return base.get_rand_name(prefix='br-int',
max_length=constants.DEVICE_NAME_MAX_LEN)
+
+
+class L3ConfigFixture(ConfigFixture):
+
+ def __init__(self, temp_dir, integration_bridge):
+ super(L3ConfigFixture, self).__init__(
+ temp_dir, base_filename='l3_agent.ini')
+
+ self.config.update({
+ 'DEFAULT': {
+ 'l3_agent_manager': ('neutron.agent.l3_agent.'
+ 'L3NATAgentWithStateReport'),
+ 'interface_driver': ('neutron.agent.linux.interface.'
+ 'OVSInterfaceDriver'),
+ 'ovs_integration_bridge': integration_bridge,
+ 'external_network_bridge': self._generate_external_bridge(),
+ 'router_delete_namespaces': 'True',
+ 'debug': 'True',
+ 'verbose': 'True',
+ }
+ })
+
+ def _generate_external_bridge(self):
+ return base.get_rand_name(prefix='br-ex',
+ max_length=constants.DEVICE_NAME_MAX_LEN)
# under the License.
from distutils import spawn
+import functools
import fixtures
from neutronclient.common import exceptions as nc_exc
from neutron.agent.linux import async_process
from neutron.agent.linux import utils
+from neutron.tests.common import net_helpers
from neutron.tests.fullstack import config_fixtures
LOG = logging.getLogger(__name__)
class ProcessFixture(fixtures.Fixture):
def __init__(self, name, exec_name, config_filenames):
- super(ProcessFixture, self).__init__()
self.name = name
self.exec_name = exec_name
self.config_filenames = config_filenames
super(ProcessFixture, self, *args, **kwargs)
+class EnvironmentFixture(fixtures.Fixture):
+
+ def setUp(self):
+ super(EnvironmentFixture, self).setUp()
+
+ self.temp_dir = self.useFixture(fixtures.TempDir()).path
+
+ self.neutron_server = self.useFixture(
+ NeutronServerFixture(self.temp_dir))
+
+ def wait_until_env_is_up(self, agents_count=0):
+ utils.wait_until_true(
+ functools.partial(self._processes_are_ready, agents_count))
+
+ def _processes_are_ready(self, agents_count):
+ try:
+ running_agents = self.neutron_server.client.list_agents()['agents']
+ LOG.warn("There are %d agents running!", len(running_agents))
+ return len(running_agents) == agents_count
+ except nc_exc.NeutronClientException:
+ LOG.warn("neutron-server isn't up yet (cannot contact REST API).")
+ return False
+
+
class NeutronServerFixture(fixtures.Fixture):
+ NEUTRON_SERVER = "neutron-server"
+
+ def __init__(self, temp_dir):
+ self.temp_dir = temp_dir
+
def setUp(self):
super(NeutronServerFixture, self).setUp()
- self.temp_dir = self.useFixture(fixtures.TempDir()).path
self.neutron_cfg_fixture = config_fixtures.NeutronConfigFixture(
self.temp_dir, cfg.CONF.database.connection)
self.useFixture(self.plugin_cfg_fixture)
self.neutron_config = self.neutron_cfg_fixture.config
+ self.plugin_config = self.plugin_cfg_fixture.config
config_filenames = [self.neutron_cfg_fixture.filename,
self.plugin_cfg_fixture.filename]
self.process_fixture = self.useFixture(ProcessFixture(
- name='neutron_server',
- exec_name='neutron-server',
- config_filenames=config_filenames,
- ))
+ name=self.NEUTRON_SERVER,
+ exec_name=self.NEUTRON_SERVER,
+ config_filenames=config_filenames))
- utils.wait_until_true(self.processes_are_ready)
+ utils.wait_until_true(self.server_is_live)
+
+ def server_is_live(self):
+ try:
+ self.client.list_networks()
+ return True
+ except nc_exc.NeutronClientException:
+ LOG.warn("neutron-server isn't up yet (cannot contact REST API).")
+ return False
@property
def client(self):
url = "http://127.0.0.1:%s" % self.neutron_config.DEFAULT.bind_port
return client.Client(auth_strategy="noauth", endpoint_url=url)
- def processes_are_ready(self):
- # ProcessFixture will ensure that the server has started, but
- # that doesn't mean that the server will be serving commands yet, nor
- # that all processes are up.
- try:
- return len(self.client.list_agents()['agents']) == 0
- except nc_exc.NeutronClientException:
- LOG.debug("Processes aren't up yet.")
- return False
+
+class OVSAgentFixture(fixtures.Fixture):
+
+ NEUTRON_OVS_AGENT = "neutron-openvswitch-agent"
+
+ def __init__(self, neutron_cfg_fixture, ml2_cfg_fixture):
+ self.neutron_cfg_fixture = neutron_cfg_fixture
+ self.plugin_cfg_fixture = ml2_cfg_fixture
+
+ self.neutron_config = self.neutron_cfg_fixture.config
+ self.plugin_config = self.plugin_cfg_fixture.config
+
+ def setUp(self):
+ super(OVSAgentFixture, self).setUp()
+
+ self.useFixture(net_helpers.OVSBridgeFixture(self._get_br_int_name()))
+ self.useFixture(net_helpers.OVSBridgeFixture(self._get_br_phys_name()))
+
+ config_filenames = [self.neutron_cfg_fixture.filename,
+ self.plugin_cfg_fixture.filename]
+
+ self.process_fixture = self.useFixture(ProcessFixture(
+ name=self.NEUTRON_OVS_AGENT,
+ exec_name=self.NEUTRON_OVS_AGENT,
+ config_filenames=config_filenames))
+
+ def _get_br_int_name(self):
+ return self.plugin_config.ovs.integration_bridge
+
+ def _get_br_phys_name(self):
+ return self.plugin_config.ovs.bridge_mappings.split(':')[1]
+
+
+class L3AgentFixture(fixtures.Fixture):
+
+ NEUTRON_L3_AGENT = "neutron-l3-agent"
+
+ def __init__(self, temp_dir, neutron_cfg_fixture, integration_bridge_name):
+ self.temp_dir = temp_dir
+ self.neutron_cfg_fixture = neutron_cfg_fixture
+ self.neutron_config = self.neutron_cfg_fixture.config
+ self.integration_bridge_name = integration_bridge_name
+
+ def setUp(self):
+ super(L3AgentFixture, self).setUp()
+
+ self.plugin_cfg_fixture = config_fixtures.L3ConfigFixture(
+ self.temp_dir, self.integration_bridge_name)
+ self.useFixture(self.plugin_cfg_fixture)
+ self.plugin_config = self.plugin_cfg_fixture.config
+
+ self.useFixture(net_helpers.OVSBridgeFixture(self._get_br_ex_name()))
+
+ config_filenames = [self.neutron_cfg_fixture.filename,
+ self.plugin_cfg_fixture.filename]
+
+ self.process_fixture = self.useFixture(ProcessFixture(
+ name=self.NEUTRON_L3_AGENT,
+ exec_name=self.NEUTRON_L3_AGENT,
+ config_filenames=config_filenames))
+
+ def _get_br_ex_name(self):
+ return self.plugin_config.DEFAULT.external_network_bridge
--- /dev/null
+# 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.
+
+from neutron.agent.l3 import agent as l3_agent
+from neutron.agent.linux import ip_lib
+from neutron.agent.linux import utils
+from neutron.openstack.common import uuidutils
+from neutron.tests.fullstack import base
+from neutron.tests.fullstack import fullstack_fixtures as f_fixtures
+
+
+class SingleNodeEnvironment(f_fixtures.EnvironmentFixture):
+ def setUp(self):
+ super(SingleNodeEnvironment, self).setUp()
+
+ neutron_config = self.neutron_server.neutron_cfg_fixture
+ ml2_config = self.neutron_server.plugin_cfg_fixture
+
+ self.ovs_agent = self.useFixture(
+ f_fixtures.OVSAgentFixture(
+ neutron_config, ml2_config))
+
+ self.l3_agent = self.useFixture(
+ f_fixtures.L3AgentFixture(
+ self.temp_dir,
+ neutron_config,
+ self.ovs_agent._get_br_int_name()))
+
+ self.wait_until_env_is_up(agents_count=2)
+
+
+class TestLegacyL3Agent(base.BaseFullStackTestCase):
+ def __init__(self, *args, **kwargs):
+ super(TestLegacyL3Agent, self).__init__(
+ SingleNodeEnvironment(), *args, **kwargs)
+
+ def _get_namespace(self, router_id):
+ return "%s%s" % (l3_agent.NS_PREFIX, router_id)
+
+ def _assert_namespace_exists(self, ns_name):
+ ip = ip_lib.IPWrapper(ns_name)
+ utils.wait_until_true(lambda: ip.netns.exists(ns_name))
+
+ def test_namespace_exists(self):
+ uuid = uuidutils.generate_uuid()
+
+ router = self.client.create_router(
+ body={'router': {'name': 'router-test',
+ 'tenant_id': uuid}})
+
+ network = self.client.create_network(
+ body={'network': {'name': 'network-test',
+ 'tenant_id': uuid}})
+
+ subnet = self.client.create_subnet(
+ body={'subnet': {'name': 'subnet-test',
+ 'tenant_id': uuid,
+ 'network_id': network['network']['id'],
+ 'cidr': '20.0.0.0/24',
+ 'gateway_ip': '20.0.0.1',
+ 'ip_version': 4,
+ 'enable_dhcp': True}})
+
+ self.client.add_interface_router(
+ router=router['router']['id'],
+ body={'subnet_id': subnet['subnet']['id']})
+
+ router_id = router['router']['id']
+ self._assert_namespace_exists(self._get_namespace(router_id))
+
+ self.client.remove_interface_router(
+ router=router['router']['id'],
+ body={'subnet_id': subnet['subnet']['id']})
+
+ self.client.delete_subnet(subnet['subnet']['id'])
+ self.client.delete_network(network['network']['id'])
+ self.client.delete_router(router['router']['id'])
+++ /dev/null
-# 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.
-
-#TODO(jschwarz): This is an example test file which demonstrates the
-# general usage of fullstack. Once we add more FullStack tests, this should
-# be deleted.
-
-from neutron.tests.fullstack import base
-
-
-class TestSanity(base.BaseFullStackTestCase):
-
- def test_sanity(self):
- self.assertEqual(self.client.list_networks(), {'networks': []})