summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/tempest.conf.sample74
-rwxr-xr-xtempest/cmd/javelin.py17
-rwxr-xr-xtempest/cmd/verify_tempest_config.py10
-rw-r--r--tempest/common/utils/linux/remote_client.py5
-rw-r--r--tempest/config.py74
-rw-r--r--tempest/scenario/manager.py9
-rw-r--r--tempest/scenario/test_network_basic_ops.py14
-rw-r--r--tempest/tests/common/utils/linux/test_remote_client.py12
8 files changed, 161 insertions, 54 deletions
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 175f0d965..1010ba531 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -253,10 +253,6 @@
# image. (string value)
#image_alt_ssh_user = root
-# Password used to authenticate to an instance using the alternate
-# image. (string value)
-#image_alt_ssh_password = password
-
# Time in seconds between build status checks. (integer value)
#build_interval = 1
@@ -269,16 +265,16 @@
#run_ssh = false
# Auth method used for authenticate to the instance. Valid choices
-# are: keypair, configured, adminpass. keypair: start the servers with
-# an ssh keypair. configured: use the configured user and password.
-# adminpass: use the injected adminPass. disabled: avoid using ssh
-# when it is an option. (string value)
+# are: keypair, configured, adminpass and disabled. Keypair: start the
+# servers with a ssh keypair. Configured: use the configured user and
+# password. Adminpass: use the injected adminPass. Disabled: avoid
+# using ssh when it is an option. (string value)
#ssh_auth_method = keypair
# How to connect to the instance? fixed: using the first ip belongs
-# the fixed network floating: creating and using a floating ip (string
-# value)
-#ssh_connect_method = fixed
+# the fixed network floating: creating and using a floating ip.
+# (string value)
+#ssh_connect_method = floating
# User name used to authenticate to an instance. (string value)
#ssh_user = root
@@ -286,6 +282,14 @@
# Timeout in seconds to wait for ping to succeed. (integer value)
#ping_timeout = 120
+# The packet size for ping packets originating from remote linux hosts
+# (integer value)
+#ping_size = 56
+
+# The number of ping packets originating from remote linux hosts
+# (integer value)
+#ping_count = 1
+
# Timeout in seconds to wait for authentication to succeed. (integer
# value)
#ssh_timeout = 300
@@ -301,7 +305,8 @@
# Name of the fixed network that is visible to all test tenants. If
# multiple networks are available for a tenant this is the network
# which will be used for creating servers if tempest does not create a
-# network or a network is not specified elsewhere (string value)
+# network or a network is not specified elsewhere. It may be used for
+# ssh validation only if floating IPs are disabled. (string value)
#fixed_network_name = <None>
# Network used for SSH connections. Ignored if
@@ -326,10 +331,6 @@
# Allowed values: public, admin, internal, publicURL, adminURL, internalURL
#endpoint_type = publicURL
-# Path to a private key file for SSH access to remote hosts (string
-# value)
-#path_to_private_key = <None>
-
# Expected device name when a volume is attached to an instance
# (string value)
#volume_device_name = vdb
@@ -746,14 +747,19 @@
# The mask bits for tenant ipv6 subnets (integer value)
#tenant_network_v6_mask_bits = 64
-# Whether tenant network connectivity should be evaluated directly
-# (boolean value)
+# Whether tenant networks can be reached directly from the test
+# client. This must be set to True when the 'fixed' ssh_connect_method
+# is selected. (boolean value)
#tenant_networks_reachable = false
# Id of the public network that provides external connectivity (string
# value)
#public_network_id =
+# Default floating network name. Used to allocate floating IPs when
+# neutron is enabled. (string value)
+#floating_network_name = <None>
+
# Id of the public router that provides external connectivity. This
# should only be used when Neutron's 'allow_overlapping_ips' is set to
# 'False' in neutron.conf. usually not needed past 'Grizzly' release
@@ -1071,6 +1077,38 @@
#too_slow_to_test = true
+[validation]
+
+#
+# From tempest.config
+#
+
+# Default IP type used for validation: -fixed: uses the first IP
+# belonging to the fixed network -floating: creates and uses a
+# floating IP (string value)
+# Allowed values: fixed, floating
+#connect_method = floating
+
+# Default authentication method to the instance. Only ssh via keypair
+# is supported for now. Additional methods will be handled in a
+# separate spec. (string value)
+# Allowed values: keypair
+#auth_method = keypair
+
+# Default IP version for ssh connections. (integer value)
+#ip_version_for_ssh = 4
+
+# Timeout in seconds to wait for ping to succeed. (integer value)
+#ping_timeout = 120
+
+# Timeout in seconds to wait for the TCP connection to be successful.
+# (integer value)
+#connect_timeout = 60
+
+# Timeout in seconds to wait for the ssh banner. (integer value)
+#ssh_timeout = 300
+
+
[volume]
#
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index fec3bd4a2..f84771fd8 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -77,7 +77,8 @@ resource file::
- name: javelin_cirros
owner: javelin
file: cirros-0.3.2-x86_64-blank.img
- format: ami
+ disk_format: ami
+ container_format: ami
aki: cirros-0.3.2-x86_64-vmlinuz
ari: cirros-0.3.2-x86_64-initrd
@@ -629,6 +630,15 @@ def create_images(images):
for image in images:
client = client_for_user(image['owner'])
+ # DEPRECATED: 'format' was used for ami images
+ # Use 'disk_format' and 'container_format' instead
+ if 'format' in image:
+ LOG.warning("Deprecated: 'format' is deprecated for images "
+ "description. Please use 'disk_format' and 'container_"
+ "format' instead.")
+ image['disk_format'] = image['format']
+ image['container_format'] = image['format']
+
# only upload a new image if the name isn't there
if _get_image_by_name(client, image['name']):
LOG.info("Image '%s' already exists" % image['name'])
@@ -636,7 +646,7 @@ def create_images(images):
# special handling for 3 part image
extras = {}
- if image['format'] == 'ami':
+ if image['disk_format'] == 'ami':
name, fname = _resolve_image(image, 'aki')
aki = client.images.create_image(
'javelin_' + name, 'aki', 'aki')
@@ -651,7 +661,8 @@ def create_images(images):
_, fname = _resolve_image(image, 'file')
body = client.images.create_image(
- image['name'], image['format'], image['format'], **extras)
+ image['name'], image['container_format'],
+ image['disk_format'], **extras)
image_id = body.get('id')
client.images.store_image(image_id, open(fname, 'r'))
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 3c71e072e..b61f286ee 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -24,6 +24,7 @@ import httplib2
from six import moves
from tempest import clients
+from tempest.common import credentials
from tempest import config
@@ -254,7 +255,11 @@ def check_service_availability(os, update):
}
# Get catalog list for endpoints to use for validation
_token, auth_data = os.auth_provider.get_auth()
- for entry in auth_data['serviceCatalog']:
+ if os.auth_version == 'v2':
+ catalog_key = 'serviceCatalog'
+ else:
+ catalog_key = 'catalog'
+ for entry in auth_data[catalog_key]:
services.append(entry['type'])
# Pull all catalog types from config file and compare against endpoint list
for cfgname in dir(CONF._config):
@@ -329,7 +334,8 @@ def main():
CONF_PARSER = moves.configparser.SafeConfigParser()
CONF_PARSER.optionxform = str
CONF_PARSER.readfp(conf_file)
- os = clients.Manager()
+ icreds = credentials.get_isolated_credentials('verify_tempest_config')
+ os = clients.Manager(icreds.get_primary_creds())
services = check_service_availability(os, update)
results = {}
for service in ['nova', 'cinder', 'neutron', 'swift']:
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index b19faefab..29fb493ed 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -87,10 +87,11 @@ class RemoteClient(object):
cmd = 'sudo sh -c "echo \\"%s\\" >/dev/console"' % message
return self.exec_command(cmd)
- def ping_host(self, host):
+ def ping_host(self, host, count=CONF.compute.ping_count,
+ size=CONF.compute.ping_size):
addr = netaddr.IPAddress(host)
cmd = 'ping6' if addr.version == 6 else 'ping'
- cmd += ' -c1 -w1 {0}'.format(host)
+ cmd += ' -c{0} -w{0} -s{1} {2}'.format(count, size, host)
return self.exec_command(cmd)
def get_mac_address(self):
diff --git a/tempest/config.py b/tempest/config.py
index 3725f5843..6b8113efe 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -187,10 +187,6 @@ ComputeGroup = [
default="root",
help="User name used to authenticate to an instance using "
"the alternate image."),
- cfg.StrOpt('image_alt_ssh_password',
- default="password",
- help="Password used to authenticate to an instance using "
- "the alternate image."),
cfg.IntOpt('build_interval',
default=1,
help="Time in seconds between build status checks."),
@@ -205,16 +201,17 @@ ComputeGroup = [
cfg.StrOpt('ssh_auth_method',
default='keypair',
help="Auth method used for authenticate to the instance. "
- "Valid choices are: keypair, configured, adminpass. "
- "keypair: start the servers with an ssh keypair. "
- "configured: use the configured user and password. "
- "adminpass: use the injected adminPass. "
- "disabled: avoid using ssh when it is an option."),
+ "Valid choices are: keypair, configured, adminpass "
+ "and disabled. "
+ "Keypair: start the servers with a ssh keypair. "
+ "Configured: use the configured user and password. "
+ "Adminpass: use the injected adminPass. "
+ "Disabled: avoid using ssh when it is an option."),
cfg.StrOpt('ssh_connect_method',
- default='fixed',
+ default='floating',
help="How to connect to the instance? "
"fixed: using the first ip belongs the fixed network "
- "floating: creating and using a floating ip"),
+ "floating: creating and using a floating ip."),
cfg.StrOpt('ssh_user',
default='root',
help="User name used to authenticate to an instance."),
@@ -222,6 +219,14 @@ ComputeGroup = [
default=120,
help="Timeout in seconds to wait for ping to "
"succeed."),
+ cfg.IntOpt('ping_size',
+ default=56,
+ help="The packet size for ping packets originating "
+ "from remote linux hosts"),
+ cfg.IntOpt('ping_count',
+ default=1,
+ help="The number of ping packets originating from remote "
+ "linux hosts"),
cfg.IntOpt('ssh_timeout',
default=300,
help="Timeout in seconds to wait for authentication to "
@@ -239,7 +244,8 @@ ComputeGroup = [
"tenants. If multiple networks are available for a tenant"
" this is the network which will be used for creating "
"servers if tempest does not create a network or a "
- "network is not specified elsewhere"),
+ "network is not specified elsewhere. It may be used for "
+ "ssh validation only if floating IPs are disabled."),
cfg.StrOpt('network_for_ssh',
default='public',
help="Network used for SSH connections. Ignored if "
@@ -264,9 +270,6 @@ ComputeGroup = [
choices=['public', 'admin', 'internal',
'publicURL', 'adminURL', 'internalURL'],
help="The endpoint type to use for the compute service."),
- cfg.StrOpt('path_to_private_key',
- help="Path to a private key file for SSH access to remote "
- "hosts"),
cfg.StrOpt('volume_device_name',
default='vdb',
help="Expected device name when a volume is attached to "
@@ -449,12 +452,16 @@ NetworkGroup = [
help="The mask bits for tenant ipv6 subnets"),
cfg.BoolOpt('tenant_networks_reachable',
default=False,
- help="Whether tenant network connectivity should be "
- "evaluated directly"),
+ help="Whether tenant networks can be reached directly from "
+ "the test client. This must be set to True when the "
+ "'fixed' ssh_connect_method is selected."),
cfg.StrOpt('public_network_id',
default="",
help="Id of the public network that provides external "
"connectivity"),
+ cfg.StrOpt('floating_network_name',
+ help="Default floating network name. Used to allocate floating "
+ "IPs when neutron is enabled."),
cfg.StrOpt('public_router_id',
default="",
help="Id of the public router that provides external "
@@ -536,6 +543,37 @@ MessagingGroup = [
help='The maximum grace period for a claim'),
]
+validation_group = cfg.OptGroup(name='validation',
+ title='SSH Validation options')
+
+ValidationGroup = [
+ cfg.StrOpt('connect_method',
+ default='floating',
+ choices=['fixed', 'floating'],
+ help='Default IP type used for validation: '
+ '-fixed: uses the first IP belonging to the fixed network '
+ '-floating: creates and uses a floating IP'),
+ cfg.StrOpt('auth_method',
+ default='keypair',
+ choices=['keypair'],
+ help='Default authentication method to the instance. '
+ 'Only ssh via keypair is supported for now. '
+ 'Additional methods will be handled in a separate spec.'),
+ cfg.IntOpt('ip_version_for_ssh',
+ default=4,
+ help='Default IP version for ssh connections.'),
+ cfg.IntOpt('ping_timeout',
+ default=120,
+ help='Timeout in seconds to wait for ping to succeed.'),
+ cfg.IntOpt('connect_timeout',
+ default=60,
+ help='Timeout in seconds to wait for the TCP connection to be '
+ 'successful.'),
+ cfg.IntOpt('ssh_timeout',
+ default=300,
+ help='Timeout in seconds to wait for the ssh banner.'),
+]
+
volume_group = cfg.OptGroup(name='volume',
title='Block Storage Options')
@@ -1088,6 +1126,7 @@ _opts = [
(network_group, NetworkGroup),
(network_feature_group, NetworkFeaturesGroup),
(messaging_group, MessagingGroup),
+ (validation_group, ValidationGroup),
(volume_group, VolumeGroup),
(volume_feature_group, VolumeFeaturesGroup),
(object_storage_group, ObjectStoreGroup),
@@ -1148,6 +1187,7 @@ class TempestConfigPrivate(object):
self.image_feature_enabled = _CONF['image-feature-enabled']
self.network = _CONF.network
self.network_feature_enabled = _CONF['network-feature-enabled']
+ self.validation = _CONF.validation
self.volume = _CONF.volume
self.volume_feature_enabled = _CONF['volume-feature-enabled']
self.object_storage = _CONF['object-storage']
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 65d516f03..d2c41f08f 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -309,8 +309,13 @@ class ScenarioTest(tempest.test.BaseTestCase):
if isinstance(server_or_ip, six.string_types):
ip = server_or_ip
else:
- addr = server_or_ip['addresses'][CONF.compute.network_for_ssh][0]
- ip = addr['addr']
+ addrs = server_or_ip['addresses'][CONF.compute.network_for_ssh]
+ try:
+ ip = (addr['addr'] for addr in addrs if
+ netaddr.valid_ipv4(addr['addr'])).next()
+ except StopIteration:
+ raise lib_exc.NotFound("No IPv4 addresses to use for SSH to "
+ "remote server.")
if username is None:
username = CONF.scenario.ssh_user
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 835304813..2c4522dfb 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -318,11 +318,15 @@ class TestNetworkBasicOps(manager.NetworkScenarioTest):
LOG.info(msg)
return
- subnet = self._list_subnets(
- network_id=CONF.network.public_network_id)
- self.assertEqual(1, len(subnet), "Found %d subnets" % len(subnet))
-
- external_ips = [subnet[0]['gateway_ip']]
+ # We ping the external IP from the instance using its floating IP
+ # which is always IPv4, so we must only test connectivity to
+ # external IPv4 IPs if the external network is dualstack.
+ v4_subnets = [s for s in self._list_subnets(
+ network_id=CONF.network.public_network_id) if s['ip_version'] == 4]
+ self.assertEqual(1, len(v4_subnets),
+ "Found %d IPv4 subnets" % len(v4_subnets))
+
+ external_ips = [v4_subnets[0]['gateway_ip']]
self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
external_ips)
diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
index 40b7b32aa..d6377e620 100644
--- a/tempest/tests/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -100,15 +100,17 @@ class TestRemoteClient(base.TestCase):
self._assert_exec_called_with('cut -f1 -d. /proc/uptime')
def test_ping_host(self):
- ping_response = """PING localhost (127.0.0.1) 56(84) bytes of data.
-64 bytes from localhost (127.0.0.1): icmp_req=1 ttl=64 time=0.048 ms
+ ping_response = """PING localhost (127.0.0.1) 70(98) bytes of data.
+78 bytes from localhost (127.0.0.1): icmp_req=1 ttl=64 time=0.048 ms
+78 bytes from localhost (127.0.0.1): icmp_req=2 ttl=64 time=0.048 ms
--- localhost ping statistics ---
-1 packets transmitted, 1 received, 0% packet loss, time 0ms
+2 packets transmitted, 2 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.048/0.048/0.048/0.000 ms"""
self.ssh_mock.mock.exec_command.return_value = ping_response
- self.assertEqual(self.conn.ping_host('127.0.0.1'), ping_response)
- self._assert_exec_called_with('ping -c1 -w1 127.0.0.1')
+ self.assertEqual(self.conn.ping_host('127.0.0.1', count=2, size=70),
+ ping_response)
+ self._assert_exec_called_with('ping -c2 -w2 -s70 127.0.0.1')
def test_get_mac_address(self):
macs = """0a:0b:0c:0d:0e:0f