Move floating IP operation from nova-network to neutron
nova-network is no more available in nova and all network request needs to move to neutron. Scenario tests are something we should be testing with the latest interface not the deprecated one so we can remove the nova netowrk specific service clients and methods. This commit moves the floating ip operation from nova-network to neutron. nova network create_floating_ip used to associate the FIP to server also so with neutron create floating ip we need to associate the FIP to server in separate method. Implements: blueprint tempest-scenario-manager-stable Change-Id: I6ad260731eedc2e1f56fe67b3a9e19fed8d4a38e
This commit is contained in:
parent
f0a2967f3d
commit
6428139de1
@ -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…
Reference in New Issue
Block a user