Merge "Add reno for removing Cinder v1 API tests"
diff --git a/README.rst b/README.rst
index f44c503..c1c6a10 100644
--- a/README.rst
+++ b/README.rst
@@ -104,7 +104,7 @@
$ tempest run
from the Tempest workspace directory. Or you can use the ``--workspace``
- argument to run in the workspace you created regarless of your current
+ argument to run in the workspace you created regardless of your current
working directory. For example::
$ tempest run --workspace cloud-01
diff --git a/releasenotes/notes/add-tempest-lib-remote-client-adbeb3f42a36910b.yaml b/releasenotes/notes/add-tempest-lib-remote-client-adbeb3f42a36910b.yaml
index c21751b..1b8cda2 100644
--- a/releasenotes/notes/add-tempest-lib-remote-client-adbeb3f42a36910b.yaml
+++ b/releasenotes/notes/add-tempest-lib-remote-client-adbeb3f42a36910b.yaml
@@ -1,10 +1,11 @@
---
features:
- - Add remote_client under tempest.lib.
+ - |
+ Add remote_client under tempest.lib.
This remote_client under tempest.lib is defined as stable
interface, and now this module provides the following
essential methods.
- * exec_command
- * validate_authentication
- * ping_host
+ - exec_command
+ - validate_authentication
+ - ping_host
diff --git a/tempest/api/compute/admin/test_volume_swap.py b/tempest/api/compute/admin/test_volume_swap.py
index 45472df..984f1a9 100644
--- a/tempest/api/compute/admin/test_volume_swap.py
+++ b/tempest/api/compute/admin/test_volume_swap.py
@@ -30,6 +30,9 @@
5. Swap volume from "volume1" to "volume2" as admin.
6. Check the swap volume is successful and "volume2"
is attached to "instance1" and "volume1" is in available state.
+ 7. Swap volume from "volume2" to "volume1" as admin.
+ 8. Check the swap volume is successful and "volume1"
+ is attached to "instance1" and "volume2" is in available state.
"""
@classmethod
@@ -58,13 +61,21 @@
volume1['id'], 'available')
waiters.wait_for_volume_resource_status(self.volumes_client,
volume2['id'], 'in-use')
- self.addCleanup(self.servers_client.detach_volume,
- server['id'], volume2['id'])
# Verify "volume2" is attached to the server
vol_attachments = self.servers_client.list_volume_attachments(
server['id'])['volumeAttachments']
self.assertEqual(1, len(vol_attachments))
self.assertIn(volume2['id'], vol_attachments[0]['volumeId'])
- # TODO(mriedem): Test swapping back from volume2 to volume1 after
- # nova bug 1490236 is fixed.
+ # Swap volume from "volume2" to "volume1"
+ self.admin_servers_client.update_attached_volume(
+ server['id'], volume2['id'], volumeId=volume1['id'])
+ waiters.wait_for_volume_resource_status(self.volumes_client,
+ volume2['id'], 'available')
+ waiters.wait_for_volume_resource_status(self.volumes_client,
+ volume1['id'], 'in-use')
+ # Verify "volume1" is attached to the server
+ vol_attachments = self.servers_client.list_volume_attachments(
+ server['id'])['volumeAttachments']
+ self.assertEqual(1, len(vol_attachments))
+ self.assertIn(volume1['id'], vol_attachments[0]['volumeId'])
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index 7e55b12..87265ec 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -14,6 +14,7 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import compute
from tempest.lib import decorators
@@ -21,13 +22,16 @@
@decorators.idempotent_id('61e03386-89c3-449c-9bb1-a06f423fd9d1')
def test_multiple_create(self):
- body = self.create_test_server(wait_until='ACTIVE',
- min_count=1,
- max_count=2)
+ body, servers = compute.create_test_server(self.os,
+ wait_until='ACTIVE',
+ min_count=2)
+ for server in servers:
+ self.addCleanup(self.servers_client.delete_server, server['id'])
# NOTE(maurosr): do status response check and also make sure that
# reservation_id is not in the response body when the request send
# contains return_reservation_id=False
self.assertNotIn('reservation_id', body)
+ self.assertEqual(2, len(servers))
@decorators.idempotent_id('864777fb-2f1e-44e3-b5b9-3eb6fa84f2f7')
def test_multiple_create_with_reservation_return(self):
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index fbfcafc..742fe59 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -239,6 +239,36 @@
'enable_snat': False})
self._verify_gateway_port(router['id'])
+ @decorators.idempotent_id('cbe42f84-04c2-11e7-8adb-fa163e4fa634')
+ @test.requires_ext(extension='ext-gw-mode', service='network')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
+ def test_create_router_set_gateway_with_fixed_ip(self):
+ # Don't know public_network_address, so at first create address
+ # from public_network and delete
+ port = self.admin_ports_client.create_port(
+ network_id=CONF.network.public_network_id)['port']
+ self.admin_ports_client.delete_port(port_id=port['id'])
+
+ fixed_ip = {
+ 'subnet_id': port['fixed_ips'][0]['subnet_id'],
+ 'ip_address': port['fixed_ips'][0]['ip_address']
+ }
+ external_gateway_info = {
+ 'network_id': CONF.network.public_network_id,
+ 'external_fixed_ips': [fixed_ip]
+ }
+
+ # Create a router and set gateway to fixed_ip
+ router = self.admin_routers_client.create_router(
+ external_gateway_info=external_gateway_info)['router']
+ self.addCleanup(self.admin_routers_client.delete_router,
+ router_id=router['id'])
+ # Examine router's gateway is equal to fixed_ip
+ self.assertEqual(router['external_gateway_info'][
+ 'external_fixed_ips'][0]['ip_address'],
+ fixed_ip['ip_address'])
+
@decorators.idempotent_id('ad81b7ee-4f81-407b-a19c-17e623f763e8')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index e945ac9..8d680e9 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -14,6 +14,7 @@
# under the License.
import netaddr
+import testtools
from tempest.api.network import base_routers as base
from tempest import config
@@ -82,6 +83,31 @@
subnet02['id'])
@test.attr(type=['negative'])
+ @decorators.idempotent_id('7101cc02-058a-11e7-93e1-fa163e4fa634')
+ @test.requires_ext(extension='ext-gw-mode', service='network')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
+ def test_router_set_gateway_used_ip_returns_409(self):
+ # At first create a address from public_network_id
+ port = self.admin_ports_client.create_port(
+ network_id=CONF.network.public_network_id)['port']
+ self.addCleanup(self.admin_ports_client.delete_port,
+ port_id=port['id'])
+ # Add used ip and subnet_id in external_fixed_ips
+ fixed_ip = {
+ 'subnet_id': port['fixed_ips'][0]['subnet_id'],
+ 'ip_address': port['fixed_ips'][0]['ip_address']
+ }
+ external_gateway_info = {
+ 'network_id': CONF.network.public_network_id,
+ 'external_fixed_ips': [fixed_ip]
+ }
+ # Create a router and set gateway to used ip
+ self.assertRaises(lib_exc.Conflict,
+ self.admin_routers_client.create_router,
+ external_gateway_info=external_gateway_info)
+
+ @test.attr(type=['negative'])
@decorators.idempotent_id('04df80f9-224d-47f5-837a-bf23e33d1c20')
def test_router_remove_interface_in_use_returns_409(self):
self.routers_client.add_router_interface(self.router['id'],
diff --git a/tempest/lib/api_schema/response/compute/v2_26/servers.py b/tempest/lib/api_schema/response/compute/v2_26/servers.py
index d873402..b03bdf6 100644
--- a/tempest/lib/api_schema/response/compute/v2_26/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_26/servers.py
@@ -52,12 +52,7 @@
'response_body': {
'type': 'object',
'properties': {
- 'tags': {
- 'type': 'array',
- 'items': {
- 'type': 'string'
- }
- }
+ 'tags': tag_items,
},
'additionalProperties': False,
'required': ['tags']
diff --git a/tempest/lib/common/cred_client.py b/tempest/lib/common/cred_client.py
index ea06011..a81f53c 100644
--- a/tempest/lib/common/cred_client.py
+++ b/tempest/lib/common/cred_client.py
@@ -59,7 +59,8 @@
def _check_role_exists(self, role_name):
try:
roles = self._list_roles()
- role = next(r for r in roles if r['name'] == role_name)
+ lc_role_name = role_name.lower()
+ role = next(r for r in roles if r['name'].lower() == lc_role_name)
except StopIteration:
return None
return role
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 5bbc039..15a0a70 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -104,7 +104,6 @@
def _setup_network_and_servers(self, **kwargs):
boot_with_port = kwargs.pop('boot_with_port', False)
- self.security_group = self._create_security_group()
self.network, self.subnet, self.router = self.create_networks(**kwargs)
self.check_networks()
@@ -152,7 +151,9 @@
def _create_server(self, network, port_id=None):
keypair = self.create_keypair()
self.keypairs[keypair['name']] = keypair
- security_groups = [{'name': self.security_group['name']}]
+ security_groups = [
+ {'name': self._create_security_group()['name']}
+ ]
network = {'uuid': network['id']}
if port_id is not None:
network['port'] = port_id
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index d9b93fe..cfd83d0 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -72,11 +72,11 @@
if dualnet - create IPv6 subnets on a different network
:return: list of created networks
"""
- self.network = self._create_network()
+ network = self._create_network()
if dualnet:
- self.network_v6 = self._create_network()
+ network_v6 = self._create_network()
- sub4 = self._create_subnet(network=self.network,
+ sub4 = self._create_subnet(network=network,
namestart='sub4',
ip_version=4)
@@ -90,7 +90,7 @@
self.subnets_v6 = []
for _ in range(n_subnets6):
- net6 = self.network_v6 if dualnet else self.network
+ net6 = network_v6 if dualnet else network
sub6 = self._create_subnet(network=net6,
namestart='sub6',
ip_version=6,
@@ -105,7 +105,7 @@
router['id'], subnet_id=sub6['id'])
self.subnets_v6.append(sub6)
- return [self.network, self.network_v6] if dualnet else [self.network]
+ return [network, network_v6] if dualnet else [network]
@staticmethod
def define_server_ips(srv):
@@ -121,8 +121,6 @@
def prepare_server(self, networks=None):
username = CONF.validation.image_ssh_user
- networks = networks or [self.network]
-
srv = self.create_server(
key_name=self.keypair['name'],
security_groups=[{'name': self.sec_grp['name']}],
@@ -134,7 +132,7 @@
username=username)
return ssh, ips, srv["id"]
- def turn_nic6_on(self, ssh, sid):
+ def turn_nic6_on(self, ssh, sid, network_id):
"""Turns the IPv6 vNIC on
Required because guest images usually set only the first vNIC on boot.
@@ -142,16 +140,18 @@
@param ssh: RemoteClient ssh instance to server
@param sid: server uuid
+ @param network_id: the network id the NIC is connected to
"""
ports = [
p["mac_address"] for p in
self.admin_manager.ports_client.list_ports(
- device_id=sid, network_id=self.network_v6['id'])['ports']
+ device_id=sid, network_id=network_id)['ports']
]
+
self.assertEqual(1, len(ports),
message=("Multiple IPv6 ports found on network %s. "
"ports: %s")
- % (self.network_v6, ports))
+ % (network_id, ports))
mac6 = ports[0]
ssh.set_nic_state(ssh.get_nic_name_by_mac(mac6))
@@ -168,8 +168,9 @@
# Turn on 2nd NIC for Cirros when dualnet
if dualnet:
- self.turn_nic6_on(sshv4_1, sid1)
- self.turn_nic6_on(sshv4_2, sid2)
+ network, network_v6 = net_list
+ self.turn_nic6_on(sshv4_1, sid1, network_v6['id'])
+ self.turn_nic6_on(sshv4_2, sid2, network_v6['id'])
# get addresses assigned to vNIC as reported by 'ip address' utility
ips_from_ip_1 = sshv4_1.exec_command("ip address")