Merge "Move floating IP operation from nova-network to neutron"
This commit is contained in:
commit
2a08090a33
@ -47,7 +47,7 @@ LATEST_MICROVERSION = 'latest'
|
|||||||
class ScenarioTest(tempest.test.BaseTestCase):
|
class ScenarioTest(tempest.test.BaseTestCase):
|
||||||
"""Base class for scenario tests. Uses tempest own clients. """
|
"""Base class for scenario tests. Uses tempest own clients. """
|
||||||
|
|
||||||
credentials = ['primary']
|
credentials = ['primary', 'admin']
|
||||||
|
|
||||||
compute_min_microversion = None
|
compute_min_microversion = None
|
||||||
compute_max_microversion = LATEST_MICROVERSION
|
compute_max_microversion = LATEST_MICROVERSION
|
||||||
@ -115,8 +115,6 @@ class ScenarioTest(tempest.test.BaseTestCase):
|
|||||||
"""This setup the service clients for the tests"""
|
"""This setup the service clients for the tests"""
|
||||||
super(ScenarioTest, cls).setup_clients()
|
super(ScenarioTest, cls).setup_clients()
|
||||||
cls.flavors_client = cls.os_primary.flavors_client
|
cls.flavors_client = cls.os_primary.flavors_client
|
||||||
cls.compute_floating_ips_client = (
|
|
||||||
cls.os_primary.compute_floating_ips_client)
|
|
||||||
if CONF.service_available.glance:
|
if CONF.service_available.glance:
|
||||||
# Check if glance v1 is available to determine which client to use.
|
# Check if glance v1 is available to determine which client to use.
|
||||||
if CONF.image_feature_enabled.api_v1:
|
if CONF.image_feature_enabled.api_v1:
|
||||||
@ -962,20 +960,98 @@ class ScenarioTest(tempest.test.BaseTestCase):
|
|||||||
LOG.exception(extra_msg)
|
LOG.exception(extra_msg)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def create_floating_ip(self, server, pool_name=None, **kwargs):
|
def get_server_port_id_and_ip4(self, server, ip_addr=None, **kwargs):
|
||||||
"""Create a floating IP and associates to a server on Nova"""
|
|
||||||
|
|
||||||
if not pool_name:
|
if ip_addr and not kwargs.get('fixed_ips'):
|
||||||
pool_name = CONF.network.floating_network_name
|
kwargs['fixed_ips'] = 'ip_address=%s' % ip_addr
|
||||||
|
ports = self.os_admin.ports_client.list_ports(
|
||||||
|
device_id=server['id'], **kwargs)['ports']
|
||||||
|
|
||||||
|
# A port can have more than one IP address in some cases.
|
||||||
|
# If the network is dual-stack (IPv4 + IPv6), this port is associated
|
||||||
|
# with 2 subnets
|
||||||
|
|
||||||
|
def _is_active(port):
|
||||||
|
# NOTE(vsaienko) With Ironic, instances live on separate hardware
|
||||||
|
# servers. Neutron does not bind ports for Ironic instances, as a
|
||||||
|
# result the port remains in the DOWN state. This has been fixed
|
||||||
|
# with the introduction of the networking-baremetal plugin but
|
||||||
|
# it's not mandatory (and is not used on all stable branches).
|
||||||
|
return (port['status'] == 'ACTIVE' or
|
||||||
|
port.get('binding:vnic_type') == 'baremetal')
|
||||||
|
|
||||||
|
port_map = [(p["id"], fxip["ip_address"])
|
||||||
|
for p in ports
|
||||||
|
for fxip in p["fixed_ips"]
|
||||||
|
if (netutils.is_valid_ipv4(fxip["ip_address"]) and
|
||||||
|
_is_active(p))]
|
||||||
|
inactive = [p for p in ports if p['status'] != 'ACTIVE']
|
||||||
|
if inactive:
|
||||||
|
LOG.warning("Instance has ports that are not ACTIVE: %s", inactive)
|
||||||
|
|
||||||
|
self.assertNotEmpty(port_map,
|
||||||
|
"No IPv4 addresses found in: %s" % ports)
|
||||||
|
self.assertEqual(len(port_map), 1,
|
||||||
|
"Found multiple IPv4 addresses: %s. "
|
||||||
|
"Unable to determine which port to target."
|
||||||
|
% port_map)
|
||||||
|
return port_map[0]
|
||||||
|
|
||||||
|
def create_floating_ip(self, server, external_network_id=None,
|
||||||
|
port_id=None, client=None, **kwargs):
|
||||||
|
"""Create a floating IP and associates to a resource/port on Neutron"""
|
||||||
|
|
||||||
|
if not external_network_id:
|
||||||
|
external_network_id = CONF.network.public_network_id
|
||||||
|
if not client:
|
||||||
|
client = self.floating_ips_client
|
||||||
|
if not port_id:
|
||||||
|
port_id, ip4 = self.get_server_port_id_and_ip4(server)
|
||||||
|
else:
|
||||||
|
ip4 = None
|
||||||
|
|
||||||
|
floatingip_kwargs = {
|
||||||
|
'floating_network_id': external_network_id,
|
||||||
|
'port_id': port_id,
|
||||||
|
'tenant_id': server.get('project_id') or server['tenant_id'],
|
||||||
|
'fixed_ip_address': ip4,
|
||||||
|
}
|
||||||
|
if CONF.network.subnet_id:
|
||||||
|
floatingip_kwargs['subnet_id'] = CONF.network.subnet_id
|
||||||
|
|
||||||
|
floatingip_kwargs.update(kwargs)
|
||||||
|
result = client.create_floatingip(**floatingip_kwargs)
|
||||||
|
floating_ip = result['floatingip']
|
||||||
|
|
||||||
floating_ip = (self.compute_floating_ips_client.
|
|
||||||
create_floating_ip(pool=pool_name,
|
|
||||||
**kwargs)['floating_ip'])
|
|
||||||
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
|
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
|
||||||
self.compute_floating_ips_client.delete_floating_ip,
|
client.delete_floatingip,
|
||||||
floating_ip['id'])
|
floating_ip['id'])
|
||||||
self.compute_floating_ips_client.associate_floating_ip_to_server(
|
return floating_ip
|
||||||
floating_ip['ip'], server['id'])
|
|
||||||
|
def associate_floating_ip(self, floating_ip, server):
|
||||||
|
"""Associate floating ip to server
|
||||||
|
|
||||||
|
This wrapper utility attaches the floating_ip for
|
||||||
|
the respective port_id of server
|
||||||
|
"""
|
||||||
|
port_id, _ = self.get_server_port_id_and_ip4(server)
|
||||||
|
kwargs = dict(port_id=port_id)
|
||||||
|
floating_ip = self.floating_ips_client.update_floatingip(
|
||||||
|
floating_ip['id'], **kwargs)['floatingip']
|
||||||
|
self.assertEqual(port_id, floating_ip['port_id'])
|
||||||
|
return floating_ip
|
||||||
|
|
||||||
|
def disassociate_floating_ip(self, floating_ip):
|
||||||
|
"""Disassociates floating ip
|
||||||
|
|
||||||
|
This wrapper utility disassociates given floating ip.
|
||||||
|
:param floating_ip: a dict which is a return value of
|
||||||
|
floating_ips_client.create_floatingip method
|
||||||
|
"""
|
||||||
|
kwargs = dict(port_id=None)
|
||||||
|
floating_ip = self.floating_ips_client.update_floatingip(
|
||||||
|
floating_ip['id'], **kwargs)['floatingip']
|
||||||
|
self.assertIsNone(floating_ip['port_id'])
|
||||||
return floating_ip
|
return floating_ip
|
||||||
|
|
||||||
def create_timestamp(self, ip_address, dev_name=None, mount_path='/mnt',
|
def create_timestamp(self, ip_address, dev_name=None, mount_path='/mnt',
|
||||||
@ -1046,7 +1122,8 @@ class ScenarioTest(tempest.test.BaseTestCase):
|
|||||||
# The tests calling this method don't have a floating IP
|
# The tests calling this method don't have a floating IP
|
||||||
# and can't make use of the validation resources. So the
|
# and can't make use of the validation resources. So the
|
||||||
# method is creating the floating IP there.
|
# method is creating the floating IP there.
|
||||||
return self.create_floating_ip(server, **kwargs)['ip']
|
return self.create_floating_ip(
|
||||||
|
server, **kwargs)['floating_ip_address']
|
||||||
elif CONF.validation.connect_method == 'fixed':
|
elif CONF.validation.connect_method == 'fixed':
|
||||||
# Determine the network name to look for based on config or creds
|
# Determine the network name to look for based on config or creds
|
||||||
# provider network resources.
|
# provider network resources.
|
||||||
@ -1138,8 +1215,6 @@ class NetworkScenarioTest(ScenarioTest):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
credentials = ['primary', 'admin']
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def skip_checks(cls):
|
def skip_checks(cls):
|
||||||
super(NetworkScenarioTest, cls).skip_checks()
|
super(NetworkScenarioTest, cls).skip_checks()
|
||||||
@ -1274,43 +1349,6 @@ class NetworkScenarioTest(ScenarioTest):
|
|||||||
|
|
||||||
return subnet
|
return subnet
|
||||||
|
|
||||||
def get_server_port_id_and_ip4(self, server, ip_addr=None, **kwargs):
|
|
||||||
|
|
||||||
if ip_addr and not kwargs.get('fixed_ips'):
|
|
||||||
kwargs['fixed_ips'] = 'ip_address=%s' % ip_addr
|
|
||||||
ports = self.os_admin.ports_client.list_ports(
|
|
||||||
device_id=server['id'], **kwargs)['ports']
|
|
||||||
|
|
||||||
# A port can have more than one IP address in some cases.
|
|
||||||
# If the network is dual-stack (IPv4 + IPv6), this port is associated
|
|
||||||
# with 2 subnets
|
|
||||||
|
|
||||||
def _is_active(port):
|
|
||||||
# NOTE(vsaienko) With Ironic, instances live on separate hardware
|
|
||||||
# servers. Neutron does not bind ports for Ironic instances, as a
|
|
||||||
# result the port remains in the DOWN state. This has been fixed
|
|
||||||
# with the introduction of the networking-baremetal plugin but
|
|
||||||
# it's not mandatory (and is not used on all stable branches).
|
|
||||||
return (port['status'] == 'ACTIVE' or
|
|
||||||
port.get('binding:vnic_type') == 'baremetal')
|
|
||||||
|
|
||||||
port_map = [(p["id"], fxip["ip_address"])
|
|
||||||
for p in ports
|
|
||||||
for fxip in p["fixed_ips"]
|
|
||||||
if (netutils.is_valid_ipv4(fxip["ip_address"]) and
|
|
||||||
_is_active(p))]
|
|
||||||
inactive = [p for p in ports if p['status'] != 'ACTIVE']
|
|
||||||
if inactive:
|
|
||||||
LOG.warning("Instance has ports that are not ACTIVE: %s", inactive)
|
|
||||||
|
|
||||||
self.assertNotEmpty(port_map,
|
|
||||||
"No IPv4 addresses found in: %s" % ports)
|
|
||||||
self.assertEqual(len(port_map), 1,
|
|
||||||
"Found multiple IPv4 addresses: %s. "
|
|
||||||
"Unable to determine which port to target."
|
|
||||||
% port_map)
|
|
||||||
return port_map[0]
|
|
||||||
|
|
||||||
def get_network_by_name(self, network_name):
|
def get_network_by_name(self, network_name):
|
||||||
net = self.os_admin.networks_client.list_networks(
|
net = self.os_admin.networks_client.list_networks(
|
||||||
name=network_name)['networks']
|
name=network_name)['networks']
|
||||||
@ -1318,63 +1356,6 @@ class NetworkScenarioTest(ScenarioTest):
|
|||||||
"Unable to get network by name: %s" % network_name)
|
"Unable to get network by name: %s" % network_name)
|
||||||
return net[0]
|
return net[0]
|
||||||
|
|
||||||
def create_floating_ip(self, server, external_network_id=None,
|
|
||||||
port_id=None, client=None, **kwargs):
|
|
||||||
"""Create a floating IP and associates to a resource/port on Neutron"""
|
|
||||||
|
|
||||||
if not external_network_id:
|
|
||||||
external_network_id = CONF.network.public_network_id
|
|
||||||
if not client:
|
|
||||||
client = self.floating_ips_client
|
|
||||||
if not port_id:
|
|
||||||
port_id, ip4 = self.get_server_port_id_and_ip4(server)
|
|
||||||
else:
|
|
||||||
ip4 = None
|
|
||||||
|
|
||||||
floatingip_kwargs = {
|
|
||||||
'floating_network_id': external_network_id,
|
|
||||||
'port_id': port_id,
|
|
||||||
'tenant_id': server.get('project_id') or server['tenant_id'],
|
|
||||||
'fixed_ip_address': ip4,
|
|
||||||
}
|
|
||||||
if CONF.network.subnet_id:
|
|
||||||
floatingip_kwargs['subnet_id'] = CONF.network.subnet_id
|
|
||||||
|
|
||||||
floatingip_kwargs.update(kwargs)
|
|
||||||
result = client.create_floatingip(**floatingip_kwargs)
|
|
||||||
floating_ip = result['floatingip']
|
|
||||||
|
|
||||||
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
|
|
||||||
client.delete_floatingip,
|
|
||||||
floating_ip['id'])
|
|
||||||
return floating_ip
|
|
||||||
|
|
||||||
def associate_floating_ip(self, floating_ip, server):
|
|
||||||
"""Associate floating ip
|
|
||||||
|
|
||||||
This wrapper utility attaches the floating_ip for
|
|
||||||
the respective port_id of server
|
|
||||||
"""
|
|
||||||
port_id, _ = self.get_server_port_id_and_ip4(server)
|
|
||||||
kwargs = dict(port_id=port_id)
|
|
||||||
floating_ip = self.floating_ips_client.update_floatingip(
|
|
||||||
floating_ip['id'], **kwargs)['floatingip']
|
|
||||||
self.assertEqual(port_id, floating_ip['port_id'])
|
|
||||||
return floating_ip
|
|
||||||
|
|
||||||
def disassociate_floating_ip(self, floating_ip):
|
|
||||||
"""Disassociates floating ip
|
|
||||||
|
|
||||||
This wrapper utility disassociates given floating ip.
|
|
||||||
:param floating_ip: a dict which is a return value of
|
|
||||||
floating_ips_client.create_floatingip method
|
|
||||||
"""
|
|
||||||
kwargs = dict(port_id=None)
|
|
||||||
floating_ip = self.floating_ips_client.update_floatingip(
|
|
||||||
floating_ip['id'], **kwargs)['floatingip']
|
|
||||||
self.assertIsNone(floating_ip['port_id'])
|
|
||||||
return floating_ip
|
|
||||||
|
|
||||||
def check_floating_ip_status(self, floating_ip, status):
|
def check_floating_ip_status(self, floating_ip, status):
|
||||||
"""Verifies floatingip reaches the given status
|
"""Verifies floatingip reaches the given status
|
||||||
|
|
||||||
@ -1575,8 +1556,6 @@ class NetworkScenarioTest(ScenarioTest):
|
|||||||
class EncryptionScenarioTest(ScenarioTest):
|
class EncryptionScenarioTest(ScenarioTest):
|
||||||
"""Base class for encryption scenario tests"""
|
"""Base class for encryption scenario tests"""
|
||||||
|
|
||||||
credentials = ['primary', 'admin']
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup_clients(cls):
|
def setup_clients(cls):
|
||||||
super(EncryptionScenarioTest, cls).setup_clients()
|
super(EncryptionScenarioTest, cls).setup_clients()
|
||||||
@ -1618,6 +1597,8 @@ class ObjectStorageScenarioTest(ScenarioTest):
|
|||||||
class.
|
class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
credentials = ['primary']
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def skip_checks(cls):
|
def skip_checks(cls):
|
||||||
super(ObjectStorageScenarioTest, cls).skip_checks()
|
super(ObjectStorageScenarioTest, cls).skip_checks()
|
||||||
|
@ -100,7 +100,7 @@ class TestMinimumBasicScenario(manager.ScenarioTest):
|
|||||||
for addresses in server['addresses'].values():
|
for addresses in server['addresses'].values():
|
||||||
for address in addresses:
|
for address in addresses:
|
||||||
if (address['OS-EXT-IPS:type'] == 'floating' and
|
if (address['OS-EXT-IPS:type'] == 'floating' and
|
||||||
address['addr'] == floating_ip['ip']):
|
address['addr'] == floating_ip['floating_ip_address']):
|
||||||
return address
|
return address
|
||||||
|
|
||||||
@decorators.idempotent_id('bdbb5441-9204-419d-a225-b4fdbfb1a1a8')
|
@decorators.idempotent_id('bdbb5441-9204-419d-a225-b4fdbfb1a1a8')
|
||||||
@ -129,7 +129,9 @@ class TestMinimumBasicScenario(manager.ScenarioTest):
|
|||||||
server = self.servers_client.show_server(server['id'])['server']
|
server = self.servers_client.show_server(server['id'])['server']
|
||||||
if (CONF.network_feature_enabled.floating_ips and
|
if (CONF.network_feature_enabled.floating_ips and
|
||||||
CONF.network.floating_network_name):
|
CONF.network.floating_network_name):
|
||||||
floating_ip = self.create_floating_ip(server)
|
fip = self.create_floating_ip(server)
|
||||||
|
floating_ip = self.associate_floating_ip(
|
||||||
|
fip, server)
|
||||||
# fetch the server again to make sure the addresses were refreshed
|
# fetch the server again to make sure the addresses were refreshed
|
||||||
# after associating the floating IP
|
# after associating the floating IP
|
||||||
server = self.servers_client.show_server(server['id'])['server']
|
server = self.servers_client.show_server(server['id'])['server']
|
||||||
@ -138,8 +140,8 @@ class TestMinimumBasicScenario(manager.ScenarioTest):
|
|||||||
self.assertIsNotNone(
|
self.assertIsNotNone(
|
||||||
address,
|
address,
|
||||||
"Failed to find floating IP '%s' in server addresses: %s" %
|
"Failed to find floating IP '%s' in server addresses: %s" %
|
||||||
(floating_ip['ip'], server['addresses']))
|
(floating_ip['floating_ip_address'], server['addresses']))
|
||||||
ssh_ip = floating_ip['ip']
|
ssh_ip = floating_ip['floating_ip_address']
|
||||||
else:
|
else:
|
||||||
ssh_ip = self.get_server_ip(server)
|
ssh_ip = self.get_server_ip(server)
|
||||||
|
|
||||||
@ -162,8 +164,7 @@ class TestMinimumBasicScenario(manager.ScenarioTest):
|
|||||||
|
|
||||||
if floating_ip:
|
if floating_ip:
|
||||||
# delete the floating IP, this should refresh the server addresses
|
# delete the floating IP, this should refresh the server addresses
|
||||||
self.compute_floating_ips_client.delete_floating_ip(
|
self.disassociate_floating_ip(floating_ip)
|
||||||
floating_ip['id'])
|
|
||||||
|
|
||||||
def is_floating_ip_detached_from_server():
|
def is_floating_ip_detached_from_server():
|
||||||
server_info = self.servers_client.show_server(
|
server_info = self.servers_client.show_server(
|
||||||
@ -177,5 +178,6 @@ class TestMinimumBasicScenario(manager.ScenarioTest):
|
|||||||
CONF.compute.build_timeout,
|
CONF.compute.build_timeout,
|
||||||
CONF.compute.build_interval):
|
CONF.compute.build_interval):
|
||||||
msg = ("Floating IP '%s' should not be in server addresses: %s"
|
msg = ("Floating IP '%s' should not be in server addresses: %s"
|
||||||
% (floating_ip['ip'], server['addresses']))
|
% (floating_ip['floating_ip_address'],
|
||||||
|
server['addresses']))
|
||||||
raise exceptions.TimeoutException(msg)
|
raise exceptions.TimeoutException(msg)
|
||||||
|
@ -52,7 +52,9 @@ class TestServerBasicOps(manager.ScenarioTest):
|
|||||||
# Obtain a floating IP if floating_ips is enabled
|
# Obtain a floating IP if floating_ips is enabled
|
||||||
if (CONF.network_feature_enabled.floating_ips and
|
if (CONF.network_feature_enabled.floating_ips and
|
||||||
CONF.network.floating_network_name):
|
CONF.network.floating_network_name):
|
||||||
self.ip = self.create_floating_ip(self.instance)['ip']
|
fip = self.create_floating_ip(self.instance)
|
||||||
|
self.ip = self.associate_floating_ip(
|
||||||
|
fip, self.instance)['floating_ip_address']
|
||||||
else:
|
else:
|
||||||
server = self.servers_client.show_server(
|
server = self.servers_client.show_server(
|
||||||
self.instance['id'])['server']
|
self.instance['id'])['server']
|
||||||
|
@ -84,11 +84,11 @@ class TestVolumeBackupRestore(manager.ScenarioTest):
|
|||||||
security_groups=[
|
security_groups=[
|
||||||
{'name': security_group['name']}])
|
{'name': security_group['name']}])
|
||||||
|
|
||||||
# Create a floating ip
|
# Create a floating ip and associate it to server.
|
||||||
floating_ip = self.create_floating_ip(server)
|
fip = self.create_floating_ip(server)
|
||||||
|
floating_ip = self.associate_floating_ip(fip, server)
|
||||||
# Check server connectivity
|
# Check server connectivity
|
||||||
self.check_vm_connectivity(floating_ip['ip'],
|
self.check_vm_connectivity(floating_ip['floating_ip_address'],
|
||||||
username=CONF.validation.image_ssh_user,
|
username=CONF.validation.image_ssh_user,
|
||||||
private_key=keypair['private_key'],
|
private_key=keypair['private_key'],
|
||||||
should_connect=True)
|
should_connect=True)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user