Merge "Add convenience parameters to create_network."
diff --git a/neutron_tempest_plugin/api/base.py b/neutron_tempest_plugin/api/base.py
index 7a575f9..ae01d56 100644
--- a/neutron_tempest_plugin/api/base.py
+++ b/neutron_tempest_plugin/api/base.py
@@ -127,6 +127,7 @@
cls.projects = []
cls.log_objects = []
cls.reserved_subnet_cidrs = set()
+ cls.keypairs = []
@classmethod
def resource_cleanup(cls):
@@ -223,6 +224,9 @@
cls._try_delete_resource(cls.admin_client.delete_log,
log_object['id'])
+ for keypair in cls.keypairs:
+ cls._try_delete_resource(cls.delete_keypair, keypair)
+
super(BaseNetworkTest, cls).resource_cleanup()
@classmethod
@@ -659,6 +663,23 @@
cls.security_groups.append(body['security_group'])
return body['security_group']
+ @classmethod
+ def create_keypair(cls, client=None, name=None, **kwargs):
+ client = client or cls.os_primary.keypairs_client
+ name = name or data_utils.rand_name('keypair-test')
+ keypair = client.create_keypair(name=name, **kwargs)['keypair']
+
+ # save client for later cleanup
+ keypair['client'] = client
+ cls.keypairs.append(keypair)
+ return keypair
+
+ @classmethod
+ def delete_keypair(cls, keypair, client=None):
+ client = (client or keypair.get('client') or
+ cls.os_primary.keypairs_client)
+ client.delete_keypair(keypair_name=keypair['name'])
+
class BaseAdminNetworkTest(BaseNetworkTest):
diff --git a/neutron_tempest_plugin/scenario/base.py b/neutron_tempest_plugin/scenario/base.py
index b76a81a..10cdaf1 100644
--- a/neutron_tempest_plugin/scenario/base.py
+++ b/neutron_tempest_plugin/scenario/base.py
@@ -15,6 +15,8 @@
import subprocess
import netaddr
+from neutron_lib.api import validators
+from neutron_lib import constants as neutron_lib_constants
from oslo_log import log
from tempest.common.utils import net_utils
from tempest.common import waiters
@@ -33,20 +35,6 @@
class BaseTempestTestCase(base_api.BaseNetworkTest):
- @classmethod
- def resource_setup(cls):
- super(BaseTempestTestCase, cls).resource_setup()
-
- cls.keypairs = []
-
- @classmethod
- def resource_cleanup(cls):
- for keypair in cls.keypairs:
- client = keypair['client']
- client.delete_keypair(
- keypair_name=keypair['keypair']['name'])
-
- super(BaseTempestTestCase, cls).resource_cleanup()
def create_server(self, flavor_ref, image_ref, key_name, networks,
**kwargs):
@@ -105,17 +93,6 @@
return server
@classmethod
- def create_keypair(cls, client=None):
- client = client or cls.os_primary.keypairs_client
- name = data_utils.rand_name('keypair-test')
- body = client.create_keypair(name=name)
- body.update(client=client)
- if client is cls.os_primary.keypairs_client:
- cls.keypairs.append(body)
-
- return body['keypair']
-
- @classmethod
def create_secgroup_rules(cls, rule_list, secgroup_id=None,
client=None):
client = client or cls.os_primary.network_client
@@ -190,7 +167,8 @@
self.floating_ips.append(fip)
return fip
- def setup_network_and_server(self, router=None, **kwargs):
+ def setup_network_and_server(
+ self, router=None, server_name=None, **kwargs):
"""Create network resources and a server.
Creating a network, subnet, router, keypair, security group
@@ -212,12 +190,18 @@
self.keypair = self.create_keypair()
self.create_loginable_secgroup_rule(
secgroup_id=secgroup['security_group']['id'])
- self.server = self.create_server(
- flavor_ref=CONF.compute.flavor_ref,
- image_ref=CONF.compute.image_ref,
- key_name=self.keypair['name'],
- networks=[{'uuid': self.network['id']}],
- security_groups=[{'name': secgroup['security_group']['name']}])
+
+ server_kwargs = {
+ 'flavor_ref': CONF.compute.flavor_ref,
+ 'image_ref': CONF.compute.image_ref,
+ 'key_name': self.keypair['name'],
+ 'networks': [{'uuid': self.network['id']}],
+ 'security_groups': [{'name': secgroup['security_group']['name']}],
+ }
+ if server_name is not None:
+ server_kwargs['name'] = server_name
+
+ self.server = self.create_server(**server_kwargs)
self.wait_for_server_active(self.server['server'])
self.port = self.client.list_ports(network_id=self.network['id'],
device_id=self.server[
@@ -252,7 +236,8 @@
"for the console log", server['id'])
def _check_remote_connectivity(self, source, dest, should_succeed=True,
- nic=None, mtu=None, fragmentation=True):
+ nic=None, mtu=None, fragmentation=True,
+ timeout=None):
"""check ping server via source ssh connection
:param source: RemoteClient: an ssh connection from which to ping
@@ -267,15 +252,21 @@
def ping_host(source, host, count=CONF.validation.ping_count,
size=CONF.validation.ping_size, nic=None, mtu=None,
fragmentation=True):
- addr = netaddr.IPAddress(host)
- cmd = 'ping6' if addr.version == 6 else 'ping'
+ IP_VERSION_4 = neutron_lib_constants.IP_VERSION_4
+ IP_VERSION_6 = neutron_lib_constants.IP_VERSION_6
+
+ # Use 'ping6' for IPv6 addresses, 'ping' for IPv4 and hostnames
+ ip_version = (
+ IP_VERSION_6 if netaddr.valid_ipv6(host) else IP_VERSION_4)
+ cmd = (
+ 'ping6' if ip_version == IP_VERSION_6 else 'ping')
if nic:
cmd = 'sudo {cmd} -I {nic}'.format(cmd=cmd, nic=nic)
if mtu:
if not fragmentation:
cmd += ' -M do'
size = str(net_utils.get_ping_payload_size(
- mtu=mtu, ip_version=addr.version))
+ mtu=mtu, ip_version=ip_version))
cmd += ' -c{0} -w{0} -s{1} {2}'.format(count, size, host)
return source.exec_command(cmd)
@@ -289,22 +280,24 @@
'from: %s.', dest, source.host)
return not should_succeed
LOG.debug('ping result: %s', result)
- # Assert that the return traffic was from the correct
- # source address.
- from_source = 'from %s' % dest
- self.assertIn(from_source, result)
+
+ if validators.validate_ip_address(dest) is None:
+ # Assert that the return traffic was from the correct
+ # source address.
+ from_source = 'from %s' % dest
+ self.assertIn(from_source, result)
return should_succeed
- return test_utils.call_until_true(ping_remote,
- CONF.validation.ping_timeout,
- 1)
+ return test_utils.call_until_true(
+ ping_remote, timeout or CONF.validation.ping_timeout, 1)
def check_remote_connectivity(self, source, dest, should_succeed=True,
nic=None, mtu=None, fragmentation=True,
- servers=None):
+ servers=None, timeout=None):
try:
self.assertTrue(self._check_remote_connectivity(
- source, dest, should_succeed, nic, mtu, fragmentation))
+ source, dest, should_succeed, nic, mtu, fragmentation,
+ timeout=timeout))
except lib_exc.SSHTimeout as ssh_e:
LOG.debug(ssh_e)
self._log_console_output(servers)
diff --git a/neutron_tempest_plugin/scenario/test_internal_dns.py b/neutron_tempest_plugin/scenario/test_internal_dns.py
new file mode 100644
index 0000000..dd89727
--- /dev/null
+++ b/neutron_tempest_plugin/scenario/test_internal_dns.py
@@ -0,0 +1,73 @@
+# Copyright 2018 Red Hat, Inc.
+# 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 tempest.common import utils
+from tempest.lib import decorators
+
+from neutron_tempest_plugin.common import ssh
+from neutron_tempest_plugin import config
+from neutron_tempest_plugin.scenario import base
+
+CONF = config.CONF
+
+
+class InternalDNSTest(base.BaseTempestTestCase):
+
+ @utils.requires_ext(extension="dns-integration", service="network")
+ @decorators.idempotent_id('988347de-07af-471a-abfa-65aea9f452a6')
+ def test_dns_name(self):
+ """Test the ability to ping a VM's hostname from another VM.
+
+ 1) Create two VMs on the same network, giving each a name
+ 2) SSH in to the first VM:
+ 2.1) ping the other VM's internal IP
+ 2.2) ping the otheR VM's hostname
+ """
+
+ self.setup_network_and_server(server_name='luke')
+ self.create_pingable_secgroup_rule(
+ secgroup_id=self.security_groups[-1]['id'])
+ self.check_connectivity(self.fip['floating_ip_address'],
+ CONF.validation.image_ssh_user,
+ self.keypair['private_key'])
+
+ leia = self.create_server(
+ flavor_ref=CONF.compute.flavor_ref,
+ image_ref=CONF.compute.image_ref,
+ key_name=self.keypair['name'],
+ networks=[{'uuid': self.network['id']}],
+ security_groups=[
+ {'name': self.security_groups[-1]['name']}],
+ name='leia')
+ self.wait_for_server_active(leia['server'])
+
+ ssh_client = ssh.Client(
+ self.fip['floating_ip_address'],
+ CONF.validation.image_ssh_user,
+ pkey=self.keypair['private_key'])
+
+ self.assertIn('luke', ssh_client.exec_command('hostname'))
+
+ leia_port = self.client.list_ports(
+ network_id=self.network['id'],
+ device_id=leia['server']['id'])['ports'][0]
+
+ # Ping with a higher timeout because spawning 2 VMs in some
+ # environment can put significant load on the deployment, resulting
+ # in very long boot times.
+ self.check_remote_connectivity(
+ ssh_client, leia_port['fixed_ips'][0]['ip_address'],
+ timeout=CONF.validation.ping_timeout * 10)
+ self.check_remote_connectivity(ssh_client, 'leia')
diff --git a/tox.ini b/tox.ini
index bba0a64..5eb8b10 100644
--- a/tox.ini
+++ b/tox.ini
@@ -16,6 +16,7 @@
commands = stestr run --slowest {posargs}
[testenv:pep8]
+basepython = python3
commands =
sh ./tools/misc-sanity-checks.sh
flake8
@@ -23,9 +24,11 @@
sh
[testenv:venv]
+basepython = python3
commands = {posargs}
[testenv:cover]
+basepython = python3
setenv =
{[testenv]setenv}
PYTHON=coverage run --source neutron_tempest_plugin --parallel-mode
@@ -36,13 +39,16 @@
coverage xml -o cover/coverage.xml
[testenv:docs]
+basepython = python3
commands = python setup.py build_sphinx
[testenv:releasenotes]
+basepython = python3
commands =
sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
[testenv:debug]
+basepython = python3
commands = oslo_debug_helper -t neutron_tempest_plugin/ {posargs}
[flake8]