javelin: implement floating-ip support
Consider multi-node environment when use_floatingip_for_ssh is True, so
we can run Javelin in multi-node environment.
* create: If CONF.use_floatingip_for_ssh is at True, we create and associate a
floating IP to a server.
* check: if the server has a floating IP, we
validate the server connectivity with it.
* destroy: disassociate the floating IP from the server.
This feature is useful when namespaces are
not reachable from the node where we run Javelin2.
Change-Id: I6c6d998588621b503bda941b54cd5c752eefb684
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 4c09bd2..4f88823 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -118,6 +118,7 @@
from tempest.openstack.common import log as logging
from tempest.openstack.common import timeutils
from tempest.services.compute.json import flavors_client
+from tempest.services.compute.json import floating_ips_client
from tempest.services.compute.json import security_groups_client
from tempest.services.compute.json import servers_client
from tempest.services.identity.v2.json import identity_client
@@ -194,6 +195,8 @@
**compute_params)
self.flavors = flavors_client.FlavorsClientJSON(_auth,
**compute_params)
+ self.floating_ips = floating_ips_client.FloatingIPsClientJSON(
+ _auth, **compute_params)
self.secgroups = security_groups_client.SecurityGroupsClientJSON(
_auth, **compute_params)
self.objects = object_client.ObjectClient(_auth,
@@ -451,15 +454,31 @@
# validate neutron is enabled and ironic disabled:
if (CONF.service_available.neutron and
not CONF.baremetal.driver_enabled):
+ _floating_is_alive = False
for network_name, body in found['addresses'].items():
for addr in body:
ip = addr['addr']
- if addr.get('OS-EXT-IPS:type', 'fixed') == 'fixed':
+ # If floatingip_for_ssh is at True, it's assumed
+ # you want to use the floating IP to reach the server,
+ # fallback to fixed IP, then other type.
+ # This is useful in multi-node environment.
+ if CONF.use_floatingip_for_ssh:
+ if addr.get('OS-EXT-IPS:type',
+ 'floating') == 'floating':
+ self._ping_ip(ip, 60)
+ _floating_is_alive = True
+ elif addr.get('OS-EXT-IPS:type', 'fixed') == 'fixed':
namespace = _get_router_namespace(client,
network_name)
self._ping_ip(ip, 60, namespace)
else:
self._ping_ip(ip, 60)
+ # if floatingip_for_ssh is at True, validate found a
+ # floating IP and ping worked.
+ if CONF.use_floatingip_for_ssh:
+ self.assertTrue(_floating_is_alive,
+ "Server %s has no floating IP." %
+ server['name'])
else:
addr = found['addresses']['private'][0]['addr']
self._ping_ip(addr, 60)
@@ -838,6 +857,10 @@
# create to security group(s) after server spawning
for secgroup in server['secgroups']:
client.servers.add_security_group(server_id, secgroup)
+ if CONF.compute.use_floatingip_for_ssh:
+ floating_ip = client.floating_ips.create_floating_ip()
+ client.floating_ips.associate_floating_ip_to_server(
+ floating_ip['ip'], server_id)
def destroy_servers(servers):
@@ -847,13 +870,31 @@
for server in servers:
client = client_for_user(server['owner'])
- response = _get_server_by_name(client, server['name'])
- if not response:
+ res = _get_server_by_name(client, server['name'])
+ if not res:
LOG.info("Server '%s' does not exist" % server['name'])
continue
- client.servers.delete_server(response['id'])
- client.servers.wait_for_server_termination(response['id'],
+ # we iterate all interfaces until we find a floating IP
+ # and stop looping after dropping it.
+ def _find_first_floating():
+ if (CONF.service_available.neutron and
+ not CONF.baremetal.driver_enabled and
+ CONF.use_floatingip_for_ssh):
+ for body in res['addresses'].items():
+ for addr in body:
+ ip = addr['addr']
+ if addr.get('OS-EXT-IPS:type',
+ 'floating') == 'floating':
+ (client.floating_ips.
+ disassociate_floating_ip_from_server(
+ ip, res['id']))
+ client.floating_ips.delete_floating_ip(ip)
+ return
+
+ _find_first_floating()
+ client.servers.delete_server(res['id'])
+ client.servers.wait_for_server_termination(res['id'],
ignore_error=True)