Browse Source

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
changes/74/782874/3
Ghanshyam Mann 1 year ago committed by Ghanshyam
parent
commit
6428139de1
  1. 205
      tempest/scenario/manager.py
  2. 16
      tempest/scenario/test_minimum_basic.py
  3. 4
      tempest/scenario/test_server_basic_ops.py
  4. 8
      tempest/scenario/test_volume_backup_restore.py

205
tempest/scenario/manager.py

@ -47,7 +47,7 @@ LATEST_MICROVERSION = 'latest'
class ScenarioTest(tempest.test.BaseTestCase):
"""Base class for scenario tests. Uses tempest own clients. """
credentials = ['primary']
credentials = ['primary', 'admin']
compute_min_microversion = None
compute_max_microversion = LATEST_MICROVERSION
@ -115,8 +115,6 @@ class ScenarioTest(tempest.test.BaseTestCase):
"""This setup the service clients for the tests"""
super(ScenarioTest, cls).setup_clients()
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:
# Check if glance v1 is available to determine which client to use.
if CONF.image_feature_enabled.api_v1:
@ -962,20 +960,98 @@ class ScenarioTest(tempest.test.BaseTestCase):
LOG.exception(extra_msg)
raise
def create_floating_ip(self, server, pool_name=None, **kwargs):
"""Create a floating IP and associates to a server on Nova"""
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 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
if not pool_name:
pool_name = CONF.network.floating_network_name
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.compute_floating_ips_client.delete_floating_ip,
client.delete_floatingip,
floating_ip['id'])
self.compute_floating_ips_client.associate_floating_ip_to_server(
floating_ip['ip'], server['id'])
return floating_ip
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
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
# and can't make use of the validation resources. So the
# 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':
# Determine the network name to look for based on config or creds
# provider network resources.
@ -1138,8 +1215,6 @@ class NetworkScenarioTest(ScenarioTest):
"""
credentials = ['primary', 'admin']
@classmethod
def skip_checks(cls):
super(NetworkScenarioTest, cls).skip_checks()
@ -1274,43 +1349,6 @@ class NetworkScenarioTest(ScenarioTest):
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):
net = self.os_admin.networks_client.list_networks(
name=network_name)['networks']
@ -1318,63 +1356,6 @@ class NetworkScenarioTest(ScenarioTest):
"Unable to get network by name: %s" % network_name)
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):
"""Verifies floatingip reaches the given status
@ -1575,8 +1556,6 @@ class NetworkScenarioTest(ScenarioTest):
class EncryptionScenarioTest(ScenarioTest):
"""Base class for encryption scenario tests"""
credentials = ['primary', 'admin']
@classmethod
def setup_clients(cls):
super(EncryptionScenarioTest, cls).setup_clients()
@ -1618,6 +1597,8 @@ class ObjectStorageScenarioTest(ScenarioTest):
class.
"""
credentials = ['primary']
@classmethod
def skip_checks(cls):
super(ObjectStorageScenarioTest, cls).skip_checks()

16
tempest/scenario/test_minimum_basic.py

@ -100,7 +100,7 @@ class TestMinimumBasicScenario(manager.ScenarioTest):
for addresses in server['addresses'].values():
for address in addresses:
if (address['OS-EXT-IPS:type'] == 'floating' and
address['addr'] == floating_ip['ip']):
address['addr'] == floating_ip['floating_ip_address']):
return address
@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']
if (CONF.network_feature_enabled.floating_ips and
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
# after associating the floating IP
server = self.servers_client.show_server(server['id'])['server']
@ -138,8 +140,8 @@ class TestMinimumBasicScenario(manager.ScenarioTest):
self.assertIsNotNone(
address,
"Failed to find floating IP '%s' in server addresses: %s" %
(floating_ip['ip'], server['addresses']))
ssh_ip = floating_ip['ip']
(floating_ip['floating_ip_address'], server['addresses']))
ssh_ip = floating_ip['floating_ip_address']
else:
ssh_ip = self.get_server_ip(server)
@ -162,8 +164,7 @@ class TestMinimumBasicScenario(manager.ScenarioTest):
if floating_ip:
# delete the floating IP, this should refresh the server addresses
self.compute_floating_ips_client.delete_floating_ip(
floating_ip['id'])
self.disassociate_floating_ip(floating_ip)
def is_floating_ip_detached_from_server():
server_info = self.servers_client.show_server(
@ -177,5 +178,6 @@ class TestMinimumBasicScenario(manager.ScenarioTest):
CONF.compute.build_timeout,
CONF.compute.build_interval):
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)

4
tempest/scenario/test_server_basic_ops.py

@ -52,7 +52,9 @@ class TestServerBasicOps(manager.ScenarioTest):
# Obtain a floating IP if floating_ips is enabled
if (CONF.network_feature_enabled.floating_ips and
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:
server = self.servers_client.show_server(
self.instance['id'])['server']

8
tempest/scenario/test_volume_backup_restore.py

@ -84,11 +84,11 @@ class TestVolumeBackupRestore(manager.ScenarioTest):
security_groups=[
{'name': security_group['name']}])
# Create a floating ip
floating_ip = self.create_floating_ip(server)
# Create a floating ip and associate it to server.
fip = self.create_floating_ip(server)
floating_ip = self.associate_floating_ip(fip, server)
# 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,
private_key=keypair['private_key'],
should_connect=True)

Loading…
Cancel
Save