Add a control point for floating IP assignment
In the basic network scenario test, the test for accessiblity via the
floating IP stands a very good chance of failing because the attempt to
connect begins before the system has had a chance to associate the
floating IP address. While an extended delay does signify a performance
issue for those types of operations, the timing of the test can be
adversly affected by other factors (e.g. parallel tests, loaded test
system). If it is extreme the check for the IP address will fail the
test as well. This addition also covers a loophole in the test where
the connectivity would work but the metadata that is provided through
the client call is not updated properly.
An additional small fix in manager.py resolves an issue when a client
API uses mixed or lower case for status strings (e.g. cinder).
There isn't a specific bug that this modification addresses.
Change-Id: Ifb1889f67588e6ee4d19f592da61ab574d456be2
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 8ccc899..97e2ae3 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -334,7 +334,11 @@
raise
new_status = thing.status
- if new_status == error_status:
+
+ # Some components are reporting error status in lower case
+ # so case sensitive comparisons can really mess things
+ # up.
+ if new_status.lower() == error_status.lower():
message = "%s failed to get to expected status. \
In %s state." % (thing, new_status)
raise exceptions.BuildErrorException(message)
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 6cd9fe8..5bf5900 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -20,14 +20,61 @@
from tempest.common import debug
from tempest.common.utils.data_utils import rand_name
from tempest import config
+from tempest.openstack.common import jsonutils
from tempest.openstack.common import log as logging
from tempest.scenario import manager
+
+import tempest.test
from tempest.test import attr
from tempest.test import services
LOG = logging.getLogger(__name__)
+class FloatingIPCheckTracker(object):
+ """
+ Checking VM connectivity through floating IP addresses is bound to fail
+ if the floating IP has not actually been associated with the VM yet.
+ This helper class facilitates checking for floating IP assignments on
+ VMs. It only checks for a given IP address once.
+ """
+
+ def __init__(self, compute_client, floating_ip_map):
+ self.compute_client = compute_client
+ self.unchecked = {}
+ for k in floating_ip_map.keys():
+ self.unchecked[k] = [f.floating_ip_address
+ for f in floating_ip_map[k]]
+
+ def run_checks(self):
+ """Check for any remaining unverified floating IPs
+
+ Gets VM details from nova and checks for floating IPs
+ within the returned information. Returns true when all
+ checks are complete and is suitable for use with
+ tempest.test.call_until_true()
+ """
+ to_delete = []
+ loggable_map = {}
+ for k, check_addrs in self.unchecked.iteritems():
+ serverdata = self.compute_client.servers.get(k.id)
+ for net_name, ip_addr in serverdata.networks.iteritems():
+ for addr in ip_addr:
+ if addr in check_addrs:
+ check_addrs.remove(addr)
+ if len(check_addrs) == 0:
+ to_delete.append(k)
+ else:
+ loggable_map[k.id] = check_addrs
+
+ for to_del in to_delete:
+ del self.unchecked[to_del]
+
+ LOG.debug('Unchecked floating IPs: %s',
+ jsonutils.dumps(loggable_map))
+ return len(self.unchecked) == 0
+
+
class TestNetworkBasicOps(manager.NetworkScenarioTest):
"""
@@ -227,11 +274,27 @@
# key-based authentication by cloud-init.
ssh_login = self.config.compute.image_ssh_user
private_key = self.keypairs[self.tenant_id].private_key
- for server in self.servers:
- for net_name, ip_addresses in server.networks.iteritems():
- for ip_address in ip_addresses:
- self._check_vm_connectivity(ip_address, ssh_login,
- private_key)
+ try:
+ for server in self.servers:
+ for net_name, ip_addresses in server.networks.iteritems():
+ for ip_address in ip_addresses:
+ self._check_vm_connectivity(ip_address, ssh_login,
+ private_key)
+ except Exception as exc:
+ LOG.exception(exc)
+ debug.log_ip_ns()
+ raise exc
+
+ def _wait_for_floating_ip_association(self):
+ ip_tracker = FloatingIPCheckTracker(self.compute_client,
+ self.floating_ips)
+
+ self.assertTrue(
+ tempest.test.call_until_true(
+ ip_tracker.run_checks, self.config.compute.build_timeout,
+ self.config.compute.build_interval),
+ "Timed out while waiting for the floating IP assignments "
+ "to propagate")
def _assign_floating_ips(self):
public_network_id = self.config.network.public_network_id
@@ -266,5 +329,6 @@
self._check_networks()
self._create_servers()
self._assign_floating_ips()
- self._check_public_network_connectivity()
+ self._wait_for_floating_ip_association()
self._check_tenant_network_connectivity()
+ self._check_public_network_connectivity()