Merge "Fix typos in scenario tests, etc."
diff --git a/.gitignore b/.gitignore
index f584532..efba45e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,4 +19,4 @@
.coverage*
!.coveragerc
cover/
-doc/source/_static/tempest.conf
+doc/source/_static/tempest.conf.sample
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 3ec25ea..f85899b 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -15,18 +15,6 @@
import os
import subprocess
-# Build a tempest sample config file:
-def build_sample_config(app):
- root_dir = os.path.dirname(
- os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
- subprocess.call(["oslo-config-generator", "--config-file",
- "tools/config/config-generator.tempest.conf",
- "--output-file", "doc/source/_static/tempest.conf"],
- cwd=root_dir)
-
-def setup(app):
- app.connect('builder-inited', build_sample_config)
-
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
@@ -42,9 +30,13 @@
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.todo',
'sphinx.ext.viewcode',
- 'oslosphinx'
+ 'oslosphinx',
+ 'oslo_config.sphinxconfiggen',
]
+config_generator_config_file = '../../tools/config/config-generator.tempest.conf'
+sample_config_basename = '_static/tempest'
+
todo_include_todos = True
# Add any paths that contain templates here, relative to this directory.
diff --git a/doc/source/sampleconf.rst b/doc/source/sampleconf.rst
index 2a72971..c290140 100644
--- a/doc/source/sampleconf.rst
+++ b/doc/source/sampleconf.rst
@@ -8,7 +8,6 @@
if you are having issues with an option, please compare your version of
Tempest with the version of this documentation.
-The sample configuration can also be viewed in `file form <_static/tempest.conf>`_.
+The sample configuration can also be viewed in `file form <_static/tempest.conf.sample>`_.
-.. include:: _static/tempest.conf
- :code:
+.. literalinclude:: _static/tempest.conf.sample
diff --git a/requirements.txt b/requirements.txt
index 5ebcb65..b25b9d3 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
-pbr<2.0,>=1.4
+pbr<2.0,>=1.6
cliff>=1.14.0 # Apache-2.0
anyjson>=0.3.3
httplib2>=0.7.5
@@ -9,11 +9,11 @@
testtools>=1.4.0
boto>=2.32.1
paramiko>=1.13.0
-netaddr>=0.7.12,!=0.7.16
+netaddr!=0.7.16,>=0.7.12
testrepository>=0.0.18
pyOpenSSL>=0.14
oslo.concurrency>=2.3.0 # Apache-2.0
-oslo.config>=2.1.0 # Apache-2.0
+oslo.config>=2.3.0 # Apache-2.0
oslo.i18n>=1.5.0 # Apache-2.0
oslo.log>=1.8.0 # Apache-2.0
oslo.serialization>=1.4.0 # Apache-2.0
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index 3553ce7..4d05ff7 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -223,5 +223,5 @@
server = self.create_test_server(name=server_name,
availability_zone=az_name,
wait_until='ACTIVE')
- body = admin_servers_client.show_server(server['id'])
+ body = admin_servers_client.show_server(server['id'])['server']
self.assertEqual(self.host, body[self._host_key])
diff --git a/tempest/api/compute/admin/test_fixed_ips.py b/tempest/api/compute/admin/test_fixed_ips.py
index 669585c..9cda0cd 100644
--- a/tempest/api/compute/admin/test_fixed_ips.py
+++ b/tempest/api/compute/admin/test_fixed_ips.py
@@ -38,7 +38,7 @@
def resource_setup(cls):
super(FixedIPsTestJson, cls).resource_setup()
server = cls.create_test_server(wait_until='ACTIVE')
- server = cls.servers_client.show_server(server['id'])
+ server = cls.servers_client.show_server(server['id'])['server']
for ip_set in server['addresses']:
for ip in server['addresses'][ip_set]:
if ip['OS-EXT-IPS:type'] == 'fixed':
diff --git a/tempest/api/compute/admin/test_fixed_ips_negative.py b/tempest/api/compute/admin/test_fixed_ips_negative.py
index e67936c..8d745c9 100644
--- a/tempest/api/compute/admin/test_fixed_ips_negative.py
+++ b/tempest/api/compute/admin/test_fixed_ips_negative.py
@@ -40,7 +40,7 @@
def resource_setup(cls):
super(FixedIPsNegativeTestJson, cls).resource_setup()
server = cls.create_test_server(wait_until='ACTIVE')
- server = cls.servers_client.show_server(server['id'])
+ server = cls.servers_client.show_server(server['id'])['server']
for ip_set in server['addresses']:
for ip in server['addresses'][ip_set]:
if ip['OS-EXT-IPS:type'] == 'fixed':
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 42a2984..085916e 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -221,7 +221,8 @@
# Verify flavor is not used by other user
self.assertRaises(lib_exc.BadRequest,
self.os.servers_client.create_server,
- 'test', self.image_ref, flavor['id'])
+ name='test', imageRef=self.image_ref,
+ flavorRef=flavor['id'])
@test.idempotent_id('b345b196-bfbd-4231-8ac1-6d7fe15ff3a3')
def test_list_public_flavor_with_other_user(self):
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 410f7b7..9d49124 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -49,7 +49,7 @@
]
def _get_server_details(self, server_id):
- body = self.admin_servers_client.show_server(server_id)
+ body = self.admin_servers_client.show_server(server_id)['server']
return body
def _get_host_for_server(self, server_id):
diff --git a/tempest/api/compute/admin/test_networks.py b/tempest/api/compute/admin/test_networks.py
index deb81a9..1da3f6e 100644
--- a/tempest/api/compute/admin/test_networks.py
+++ b/tempest/api/compute/admin/test_networks.py
@@ -32,7 +32,7 @@
@classmethod
def setup_clients(cls):
super(NetworksTest, cls).setup_clients()
- cls.client = cls.os_adm.networks_client
+ cls.client = cls.os_adm.compute_networks_client
@test.idempotent_id('d206d211-8912-486f-86e2-a9d090d1f416')
def test_get_network(self):
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index ef96f9b..dbca6bb 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -97,58 +97,56 @@
# TODO(afazekas): merge these test cases
@test.idempotent_id('ce9e0815-8091-4abd-8345-7fe5b85faa1d')
def test_get_updated_quotas(self):
- # Verify that GET shows the updated quota set of tenant
- tenant_name = data_utils.rand_name('cpu_quota_tenant')
- tenant_desc = tenant_name + '-desc'
- identity_client = self.os_adm.identity_client
- tenant = identity_client.create_tenant(name=tenant_name,
- description=tenant_desc)
- tenant_id = tenant['id']
- self.addCleanup(identity_client.delete_tenant, tenant_id)
+ # Verify that GET shows the updated quota set of project
+ project_name = data_utils.rand_name('cpu_quota_project')
+ project_desc = project_name + '-desc'
+ project = self.identity_utils.create_project(name=project_name,
+ description=project_desc)
+ project_id = project['id']
+ self.addCleanup(self.identity_utils.delete_project, project_id)
- self.adm_client.update_quota_set(tenant_id, ram='5120')
- quota_set = self.adm_client.show_quota_set(tenant_id)['quota_set']
+ self.adm_client.update_quota_set(project_id, ram='5120')
+ quota_set = self.adm_client.show_quota_set(project_id)['quota_set']
self.assertEqual(5120, quota_set['ram'])
# Verify that GET shows the updated quota set of user
user_name = data_utils.rand_name('cpu_quota_user')
password = data_utils.rand_name('password')
email = user_name + '@testmail.tm'
- user = identity_client.create_user(name=user_name,
- password=password,
- tenant_id=tenant_id,
- email=email)
+ user = self.identity_utils.create_user(username=user_name,
+ password=password,
+ project=project,
+ email=email)
if 'user' in user:
user = user['user']
user_id = user['id']
- self.addCleanup(identity_client.delete_user, user_id)
+ self.addCleanup(self.identity_utils.delete_user, user_id)
- self.adm_client.update_quota_set(tenant_id,
+ self.adm_client.update_quota_set(project_id,
user_id=user_id,
ram='2048')
quota_set = self.adm_client.show_quota_set(
- tenant_id, user_id=user_id)['quota_set']
+ project_id, user_id=user_id)['quota_set']
self.assertEqual(2048, quota_set['ram'])
@test.idempotent_id('389d04f0-3a41-405f-9317-e5f86e3c44f0')
def test_delete_quota(self):
- # Admin can delete the resource quota set for a tenant
- tenant_name = data_utils.rand_name('ram_quota_tenant')
- tenant_desc = tenant_name + '-desc'
- identity_client = self.os_adm.identity_client
- tenant = identity_client.create_tenant(name=tenant_name,
- description=tenant_desc)
- tenant_id = tenant['id']
- self.addCleanup(identity_client.delete_tenant, tenant_id)
- quota_set_default = (self.adm_client.show_quota_set(tenant_id)
+ # Admin can delete the resource quota set for a project
+ project_name = data_utils.rand_name('ram_quota_project')
+ project_desc = project_name + '-desc'
+ project = self.identity_utils.create_project(name=project_name,
+ description=project_desc)
+ project_id = project['id']
+ self.addCleanup(self.identity_utils.delete_project, project_id)
+ quota_set_default = (self.adm_client.show_quota_set(project_id)
['quota_set'])
ram_default = quota_set_default['ram']
- self.adm_client.update_quota_set(tenant_id, ram='5120')
+ self.adm_client.update_quota_set(project_id, ram='5120')
- self.adm_client.delete_quota_set(tenant_id)
+ self.adm_client.delete_quota_set(project_id)
- quota_set_new = self.adm_client.show_quota_set(tenant_id)['quota_set']
+ quota_set_new = self.adm_client.show_quota_set(project_id)['quota_set']
self.assertEqual(ram_default, quota_set_new['ram'])
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index 758cd43..bdbfde4 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -49,8 +49,8 @@
self.demo_tenant_id,
ram=0)
- # TODO(afazekas): Add dedicated tenant to the skiped quota tests
- # it can be moved into the setUpClass as well
+ # TODO(afazekas): Add dedicated tenant to the skipped quota tests.
+ # It can be moved into the setUpClass as well.
@test.attr(type=['negative'])
@test.idempotent_id('91058876-9947-4807-9f22-f6eb17140d9b')
def test_create_server_when_cpu_quota_is_full(self):
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index 0528fa5..dfaa5d5 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -66,7 +66,7 @@
# Reset server's state to 'active'
self.client.reset_state(self.s1_id, state='active')
# Verify server's state
- server = self.client.show_server(self.s1_id)
+ server = self.client.show_server(self.s1_id)['server']
self.assertEqual(server['status'], 'ACTIVE')
servers = body['servers']
# Verify error server in list result
@@ -111,12 +111,13 @@
image_id = self.image_ref
network = self.get_tenant_network()
network_kwargs = fixed_network.set_networks_kwarg(network)
- test_server = self.client.create_server(name, image_id, flavor,
- **network_kwargs)
+ test_server = self.client.create_server(name=name, imageRef=image_id,
+ flavorRef=flavor,
+ **network_kwargs)['server']
self.addCleanup(self.client.delete_server, test_server['id'])
waiters.wait_for_server_status(self.client,
test_server['id'], 'ACTIVE')
- server = self.client.show_server(test_server['id'])
+ server = self.client.show_server(test_server['id'])['server']
self.assertEqual(server['status'], 'ACTIVE')
hostname = server[self._host_key]
params = {'host': hostname}
@@ -135,14 +136,14 @@
self.client.reset_state(self.s1_id)
# Verify server's state
- server = self.client.show_server(self.s1_id)
+ server = self.client.show_server(self.s1_id)['server']
self.assertEqual(server['status'], 'ERROR')
# Reset server's state to 'active'
self.client.reset_state(self.s1_id, state='active')
# Verify server's state
- server = self.client.show_server(self.s1_id)
+ server = self.client.show_server(self.s1_id)['server']
self.assertEqual(server['status'], 'ACTIVE')
@decorators.skip_because(bug="1240043")
@@ -164,7 +165,7 @@
# resetting vm state require admin privilege
self.client.reset_state(self.s1_id, state='error')
rebuilt_server = self.non_admin_client.rebuild_server(
- self.s1_id, self.image_ref_alt)
+ self.s1_id, self.image_ref_alt)['server']
self.addCleanup(waiters.wait_for_server_status, self.non_admin_client,
self.s1_id, 'ACTIVE')
self.addCleanup(self.non_admin_client.rebuild_server, self.s1_id,
@@ -179,7 +180,8 @@
rebuilt_server['id'], 'ACTIVE',
raise_on_error=False)
# Verify the server properties after rebuilding
- server = self.non_admin_client.show_server(rebuilt_server['id'])
+ server = (self.non_admin_client.show_server(rebuilt_server['id'])
+ ['server'])
rebuilt_image_id = server['image']['id']
self.assertEqual(self.image_ref_alt, rebuilt_image_id)
@@ -197,5 +199,5 @@
hints = {
'same_host': self.s1_id
}
- self.create_test_server(sched_hints=hints,
+ self.create_test_server(scheduler_hints=hints,
wait_until='ACTIVE')
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 1f53f9a..3952439 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -69,12 +69,11 @@
cls.security_group_rules_client = cls.os.security_group_rules_client
cls.security_groups_client = cls.os.security_groups_client
cls.quotas_client = cls.os.quotas_client
- # NOTE(mriedem): os-quota-class-sets is v2 API only
cls.quota_classes_client = cls.os.quota_classes_client
- # NOTE(mriedem): os-networks is v2 API only
- cls.networks_client = cls.os.networks_client
+ cls.compute_networks_client = cls.os.compute_networks_client
cls.limits_client = cls.os.limits_client
cls.volumes_extensions_client = cls.os.volumes_extensions_client
+ cls.snapshots_extensions_client = cls.os.snapshots_extensions_client
cls.interfaces_client = cls.os.interfaces_client
cls.fixed_ips_client = cls.os.fixed_ips_client
cls.availability_zone_client = cls.os.availability_zone_client
diff --git a/tempest/api/compute/limits/test_absolute_limits_negative.py b/tempest/api/compute/limits/test_absolute_limits_negative.py
index 5755f5b..73e852f 100644
--- a/tempest/api/compute/limits/test_absolute_limits_negative.py
+++ b/tempest/api/compute/limits/test_absolute_limits_negative.py
@@ -55,4 +55,4 @@
# A 403 Forbidden or 413 Overlimit (old behaviour) exception
# will be raised when out of quota
self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
- self.create_test_server, meta=meta_data)
+ self.create_test_server, metadata=meta_data)
diff --git a/tempest/api/compute/security_groups/test_security_group_rules.py b/tempest/api/compute/security_groups/test_security_group_rules.py
index 3c22d28..9aa59f7 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -161,8 +161,8 @@
self.addCleanup(self.client.delete_security_group_rule, rule2_id)
# Get rules of the created Security Group
- rules = (self.client.list_security_group_rules(securitygroup_id)
- ['rules'])
+ rules = self.security_groups_client.show_security_group(
+ securitygroup_id)['security_group']['rules']
self.assertTrue(any([i for i in rules if i['id'] == rule1_id]))
self.assertTrue(any([i for i in rules if i['id'] == rule2_id]))
@@ -187,6 +187,7 @@
# Delete group2
self.security_groups_client.delete_security_group(sg2_id)
# Get rules of the Group1
- rules = self.client.list_security_group_rules(sg1_id)['rules']
+ rules = (self.security_groups_client.show_security_group(sg1_id)
+ ['security_group']['rules'])
# The group1 has no rules because group2 has deleted
self.assertEqual(0, len(rules))
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index dcdb562..24d503f 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -186,10 +186,10 @@
self.assertTrue(interface_count > 0)
self._check_interface(ifs[0])
network_id = ifs[0]['net_id']
- self.client.add_fixed_ip(server['id'], networkId=network_id)
+ self.servers_client.add_fixed_ip(server['id'], networkId=network_id)
# Remove the fixed IP from server.
server_detail = self.os.servers_client.show_server(
- server['id'])
+ server['id'])['server']
# Get the Fixed IP from server.
fixed_ip = None
for ip_set in server_detail['addresses']:
@@ -199,4 +199,4 @@
break
if fixed_ip is not None:
break
- self.client.remove_fixed_ip(server['id'], address=fixed_ip)
+ self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 529b596..68af81c 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -58,13 +58,14 @@
validatable=True,
wait_until='ACTIVE',
name=cls.name,
- meta=cls.meta,
+ metadata=cls.meta,
accessIPv4=cls.accessIPv4,
accessIPv6=cls.accessIPv6,
personality=personality,
disk_config=disk_config)
cls.password = cls.server_initial['adminPass']
- cls.server = cls.client.show_server(cls.server_initial['id'])
+ cls.server = (cls.client.show_server(cls.server_initial['id'])
+ ['server'])
def _create_net_subnet_ret_net_from_cidr(self, cidr):
name_net = data_utils.rand_name(self.__class__.__name__)
@@ -149,7 +150,7 @@
group_id)
hints = {'group': group_id}
- server = self.create_test_server(sched_hints=hints,
+ server = self.create_test_server(scheduler_hints=hints,
wait_until='ACTIVE')
# Check a server is in the group
@@ -185,7 +186,8 @@
self.addCleanup(cleanup_server)
- addresses = self.client.list_addresses(server_multi_nics['id'])
+ addresses = (self.client.list_addresses(server_multi_nics['id'])
+ ['addresses'])
# We can't predict the ip addresses assigned to the server on networks.
# Sometimes the assigned addresses are ['19.80.0.2', '19.86.0.2'], at
@@ -226,7 +228,8 @@
self.addCleanup(cleanup_server)
- addresses = self.client.list_addresses(server_multi_nics['id'])
+ addresses = (self.client.list_addresses(server_multi_nics['id'])
+ ['addresses'])
addr = [addresses[net1['network']['name']][0]['addr'],
addresses[net2['network']['name']][0]['addr'],
@@ -315,7 +318,7 @@
# Get partition number of server without extra specs.
server_no_eph_disk = self.client.show_server(
- server_no_eph_disk['id'])
+ server_no_eph_disk['id'])['server']
linux_client = remote_client.RemoteClient(
self.get_server_ip(server_no_eph_disk),
self.ssh_user,
@@ -333,7 +336,7 @@
flavor=flavor_with_eph_disk_id)
server_with_eph_disk = self.client.show_server(
- server_with_eph_disk['id'])
+ server_with_eph_disk['id'])['server']
linux_client = remote_client.RemoteClient(
self.get_server_ip(server_with_eph_disk),
self.ssh_user,
diff --git a/tempest/api/compute/servers/test_delete_server.py b/tempest/api/compute/servers/test_delete_server.py
index d7b4470..6796bb5 100644
--- a/tempest/api/compute/servers/test_delete_server.py
+++ b/tempest/api/compute/servers/test_delete_server.py
@@ -117,7 +117,8 @@
device = '/dev/%s' % CONF.compute.volume_device_name
server = self.create_test_server(wait_until='ACTIVE')
- volume = volumes_client.create_volume(size=CONF.volume.volume_size)
+ volume = (volumes_client.create_volume(size=CONF.volume.volume_size)
+ ['volume'])
self.addCleanup(volumes_client.delete_volume, volume['id'])
waiters.wait_for_volume_status(volumes_client,
volume['id'], 'available')
@@ -149,7 +150,7 @@
server = self.create_test_server(wait_until='ACTIVE')
self.admin_client.reset_state(server['id'], state='error')
# Verify server's state
- server = self.non_admin_client.show_server(server['id'])
+ server = self.non_admin_client.show_server(server['id'])['server']
self.assertEqual(server['status'], 'ERROR')
self.non_admin_client.delete_server(server['id'])
waiters.wait_for_server_termination(self.servers_client,
diff --git a/tempest/api/compute/servers/test_disk_config.py b/tempest/api/compute/servers/test_disk_config.py
index 929b300..617cdd5 100644
--- a/tempest/api/compute/servers/test_disk_config.py
+++ b/tempest/api/compute/servers/test_disk_config.py
@@ -44,12 +44,12 @@
cls.server_id = server['id']
def _update_server_with_disk_config(self, disk_config):
- server = self.client.show_server(self.server_id)
+ server = self.client.show_server(self.server_id)['server']
if disk_config != server['OS-DCF:diskConfig']:
- server = self.client.update_server(self.server_id,
- disk_config=disk_config)
+ server = self.client.update_server(
+ self.server_id, disk_config=disk_config)['server']
waiters.wait_for_server_status(self.client, server['id'], 'ACTIVE')
- server = self.client.show_server(server['id'])
+ server = self.client.show_server(server['id'])['server']
self.assertEqual(disk_config, server['OS-DCF:diskConfig'])
@test.idempotent_id('bef56b09-2e8c-4883-a370-4950812f430e')
@@ -59,13 +59,13 @@
server = self.client.rebuild_server(self.server_id,
self.image_ref_alt,
- disk_config='MANUAL')
+ disk_config='MANUAL')['server']
# Wait for the server to become active
waiters.wait_for_server_status(self.client, server['id'], 'ACTIVE')
# Verify the specified attributes are set correctly
- server = self.client.show_server(server['id'])
+ server = self.client.show_server(server['id'])['server']
self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
@test.idempotent_id('9c9fae77-4feb-402f-8450-bf1c8b609713')
@@ -75,17 +75,17 @@
server = self.client.rebuild_server(self.server_id,
self.image_ref_alt,
- disk_config='AUTO')
+ disk_config='AUTO')['server']
# Wait for the server to become active
waiters.wait_for_server_status(self.client, server['id'], 'ACTIVE')
# Verify the specified attributes are set correctly
- server = self.client.show_server(server['id'])
+ server = self.client.show_server(server['id'])['server']
self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
def _get_alternative_flavor(self):
- server = self.client.show_server(self.server_id)
+ server = self.client.show_server(self.server_id)['server']
if server['flavor']['id'] == self.flavor_ref:
return self.flavor_ref_alt
@@ -108,7 +108,7 @@
self.client.confirm_resize_server(self.server_id)
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
- server = self.client.show_server(self.server_id)
+ server = self.client.show_server(self.server_id)['server']
self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
@test.idempotent_id('693d16f3-556c-489a-8bac-3d0ca2490bad')
@@ -127,7 +127,7 @@
self.client.confirm_resize_server(self.server_id)
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
- server = self.client.show_server(self.server_id)
+ server = self.client.show_server(self.server_id)['server']
self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
@test.idempotent_id('5ef18867-358d-4de9-b3c9-94d4ba35742f')
@@ -137,9 +137,9 @@
# Update the disk_config attribute to manual
server = self.client.update_server(self.server_id,
- disk_config='MANUAL')
+ disk_config='MANUAL')['server']
waiters.wait_for_server_status(self.client, server['id'], 'ACTIVE')
# Verify the disk_config attribute is set correctly
- server = self.client.show_server(server['id'])
+ server = self.client.show_server(server['id'])['server']
self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
diff --git a/tempest/api/compute/servers/test_instance_actions.py b/tempest/api/compute/servers/test_instance_actions.py
index 4ac1a49..97d47fd 100644
--- a/tempest/api/compute/servers/test_instance_actions.py
+++ b/tempest/api/compute/servers/test_instance_actions.py
@@ -38,7 +38,8 @@
self.client.reboot_server(self.server_id, 'HARD')
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
- body = self.client.list_instance_actions(self.server_id)
+ body = (self.client.list_instance_actions(self.server_id)
+ ['instanceActions'])
self.assertTrue(len(body) == 2, str(body))
self.assertTrue(any([i for i in body if i['action'] == 'create']))
self.assertTrue(any([i for i in body if i['action'] == 'reboot']))
@@ -46,7 +47,7 @@
@test.idempotent_id('aacc71ca-1d70-4aa5-bbf6-0ff71470e43c')
def test_get_instance_action(self):
# Get the action details of the provided server
- body = self.client.get_instance_action(self.server_id,
- self.request_id)
+ body = self.client.get_instance_action(
+ self.server_id, self.request_id)['instanceAction']
self.assertEqual(self.server_id, body['instance_uuid'])
self.assertEqual('create', body['action'])
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 16e4392..3acff98 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -274,7 +274,7 @@
if not self.fixed_network_name:
msg = 'fixed_network_name needs to be configured to run this test'
raise self.skipException(msg)
- self.s1 = self.client.show_server(self.s1['id'])
+ self.s1 = self.client.show_server(self.s1['id'])['server']
for addr_spec in self.s1['addresses'][self.fixed_network_name]:
ip = addr_spec['addr']
if addr_spec['version'] == 4:
@@ -298,7 +298,7 @@
if not self.fixed_network_name:
msg = 'fixed_network_name needs to be configured to run this test'
raise self.skipException(msg)
- self.s1 = self.client.show_server(self.s1['id'])
+ self.s1 = self.client.show_server(self.s1['id'])['server']
addr_spec = self.s1['addresses'][self.fixed_network_name][0]
ip = addr_spec['addr'][0:-3]
if addr_spec['version'] == 4:
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index c99adc5..f0cd2a1 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -52,8 +52,8 @@
self.__class__.server_id = server['id']
except Exception:
# Rebuild server if something happened to it during a test
- self.__class__.server_id = self.rebuild_server(self.server_id,
- validatable=True)
+ self.__class__.server_id = self.rebuild_server(
+ self.server_id, validatable=True)['server']
def tearDown(self):
self.server_check_teardown()
@@ -87,7 +87,7 @@
if CONF.validation.run_validation:
# Verify that the user can authenticate with the new password
- server = self.client.show_server(self.server_id)
+ server = self.client.show_server(self.server_id)['server']
linux_client = remote_client.RemoteClient(
self.get_server_ip(server),
self.ssh_user,
@@ -97,7 +97,7 @@
def _test_reboot_server(self, reboot_type):
if CONF.validation.run_validation:
# Get the time the server was last rebooted,
- server = self.client.show_server(self.server_id)
+ server = self.client.show_server(self.server_id)['server']
linux_client = remote_client.RemoteClient(
self.get_server_ip(server),
self.ssh_user,
@@ -132,7 +132,8 @@
self._test_reboot_server('SOFT')
def _rebuild_server_and_check(self, image_ref):
- rebuilt_server = self.client.rebuild_server(self.server_id, image_ref)
+ rebuilt_server = (self.client.rebuild_server(self.server_id, image_ref)
+ ['server'])
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
msg = ('Server was not rebuilt to the original image. '
'The original image: {0}. The current image: {1}'
@@ -148,12 +149,13 @@
personality = [{'path': 'rebuild.txt',
'contents': base64.b64encode(file_contents)}]
password = 'rebuildPassw0rd'
- rebuilt_server = self.client.rebuild_server(self.server_id,
- self.image_ref_alt,
- name=new_name,
- metadata=meta,
- personality=personality,
- adminPass=password)
+ rebuilt_server = self.client.rebuild_server(
+ self.server_id,
+ self.image_ref_alt,
+ name=new_name,
+ metadata=meta,
+ personality=personality,
+ adminPass=password)['server']
# If the server was rebuilt on a different image, restore it to the
# original image once the test ends
@@ -169,7 +171,7 @@
# Verify the server properties after the rebuild completes
waiters.wait_for_server_status(self.client,
rebuilt_server['id'], 'ACTIVE')
- server = self.client.show_server(rebuilt_server['id'])
+ server = self.client.show_server(rebuilt_server['id'])['server']
rebuilt_image_id = server['image']['id']
self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
self.assertEqual(new_name, server['name'])
@@ -187,13 +189,14 @@
def test_rebuild_server_in_stop_state(self):
# The server in stop state should be rebuilt using the provided
# image and remain in SHUTOFF state
- server = self.client.show_server(self.server_id)
+ server = self.client.show_server(self.server_id)['server']
old_image = server['image']['id']
new_image = (self.image_ref_alt
if old_image == self.image_ref else self.image_ref)
self.client.stop_server(self.server_id)
waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF')
- rebuilt_server = self.client.rebuild_server(self.server_id, new_image)
+ rebuilt_server = (self.client.rebuild_server(self.server_id, new_image)
+ ['server'])
# If the server was rebuilt on a different image, restore it to the
# original image once the test ends
if self.image_ref_alt != self.image_ref:
@@ -208,7 +211,7 @@
# Verify the server properties after the rebuild completes
waiters.wait_for_server_status(self.client,
rebuilt_server['id'], 'SHUTOFF')
- server = self.client.show_server(rebuilt_server['id'])
+ server = self.client.show_server(rebuilt_server['id'])['server']
rebuilt_image_id = server['image']['id']
self.assertEqual(new_image, rebuilt_image_id)
@@ -232,7 +235,7 @@
waiters.wait_for_server_status(self.client, self.server_id,
expected_status)
- server = self.client.show_server(self.server_id)
+ server = self.client.show_server(self.server_id)['server']
self.assertEqual(self.flavor_ref_alt, server['flavor']['id'])
if stop:
@@ -269,7 +272,7 @@
self.client.revert_resize_server(self.server_id)
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
- server = self.client.show_server(self.server_id)
+ server = self.client.show_server(self.server_id)['server']
self.assertEqual(self.flavor_ref, server['flavor']['id'])
@test.idempotent_id('b963d4f1-94b3-4c40-9e97-7b583f46e470')
@@ -358,7 +361,7 @@
def _get_output(self):
output = self.client.get_console_output(
- self.server_id, 10).data
+ self.server_id, 10)['output']
self.assertTrue(output, "Console output was empty.")
lines = len(output.split('\n'))
self.assertEqual(lines, 10)
@@ -387,7 +390,7 @@
def _check_full_length_console_log():
output = self.client.get_console_output(server['id'],
- None).data
+ None)['output']
self.assertTrue(output, "Console output was empty.")
lines = len(output.split('\n'))
@@ -453,7 +456,7 @@
waiters.wait_for_server_status(self.client, self.server_id,
'SHELVED_OFFLOADED')
- server = self.client.show_server(self.server_id)
+ server = self.client.show_server(self.server_id)['server']
image_name = server['name'] + '-shelved'
params = {'name': image_name}
images = self.images_client.list_images(**params)['images']
@@ -475,7 +478,7 @@
# Lock the server,try server stop(exceptions throw),unlock it and retry
self.client.lock_server(self.server_id)
self.addCleanup(self.client.unlock_server, self.server_id)
- server = self.client.show_server(self.server_id)
+ server = self.client.show_server(self.server_id)['server']
self.assertEqual(server['status'], 'ACTIVE')
# Locked server is not allowed to be stopped by non-admin user
self.assertRaises(lib_exc.Conflict,
@@ -501,7 +504,7 @@
console_types = ['novnc', 'xvpvnc']
for console_type in console_types:
body = self.client.get_vnc_console(self.server_id,
- console_type)
+ console_type)['console']
self.assertEqual(console_type, body['type'])
self.assertNotEqual('', body['url'])
self._validate_url(body['url'])
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index a17f581..864f38f 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -45,7 +45,7 @@
# All public and private addresses for
# a server should be returned
- addresses = self.client.list_addresses(self.server['id'])
+ addresses = self.client.list_addresses(self.server['id'])['addresses']
# We do not know the exact network configuration, but an instance
# should at least have a single public or private address
@@ -63,7 +63,7 @@
# Providing a network type should filter
# the addresses return by that type
- addresses = self.client.list_addresses(self.server['id'])
+ addresses = self.client.list_addresses(self.server['id'])['addresses']
# Once again we don't know the environment's exact network config,
# but the response for each individual network should be the same
diff --git a/tempest/api/compute/servers/test_server_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index 234633b..77ddb3b 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -28,18 +28,19 @@
@classmethod
def resource_setup(cls):
super(ServerMetadataTestJSON, cls).resource_setup()
- server = cls.create_test_server(meta={}, wait_until='ACTIVE')
+ server = cls.create_test_server(metadata={}, wait_until='ACTIVE')
cls.server_id = server['id']
def setUp(self):
super(ServerMetadataTestJSON, self).setUp()
meta = {'key1': 'value1', 'key2': 'value2'}
- self.client.set_server_metadata(self.server_id, meta)
+ self.client.set_server_metadata(self.server_id, meta)['metadata']
@test.idempotent_id('479da087-92b3-4dcf-aeb3-fd293b2d14ce')
def test_list_server_metadata(self):
# All metadata key/value pairs for a server should be returned
- resp_metadata = self.client.list_server_metadata(self.server_id)
+ resp_metadata = (self.client.list_server_metadata(self.server_id)
+ ['metadata'])
# Verify the expected metadata items are in the list
expected = {'key1': 'value1', 'key2': 'value2'}
@@ -50,11 +51,13 @@
# The server's metadata should be replaced with the provided values
# Create a new set of metadata for the server
req_metadata = {'meta2': 'data2', 'meta3': 'data3'}
- self.client.set_server_metadata(self.server_id, req_metadata)
+ self.client.set_server_metadata(self.server_id,
+ req_metadata)['metadata']
# Verify the expected values are correct, and that the
# previous values have been removed
- resp_metadata = self.client.list_server_metadata(self.server_id)
+ resp_metadata = (self.client.list_server_metadata(self.server_id)
+ ['metadata'])
self.assertEqual(resp_metadata, req_metadata)
@test.idempotent_id('344d981e-0c33-4997-8a5d-6c1d803e4134')
@@ -65,7 +68,8 @@
self.client.update_server_metadata(self.server_id, meta)
# Verify the values have been updated to the proper values
- resp_metadata = self.client.list_server_metadata(self.server_id)
+ resp_metadata = (self.client.list_server_metadata(self.server_id)
+ ['metadata'])
expected = {'key1': 'alt1', 'key2': 'value2', 'key3': 'value3'}
self.assertEqual(expected, resp_metadata)
@@ -75,14 +79,16 @@
# passed
meta = {}
self.client.update_server_metadata(self.server_id, meta)
- resp_metadata = self.client.list_server_metadata(self.server_id)
+ resp_metadata = (self.client.list_server_metadata(self.server_id)
+ ['metadata'])
expected = {'key1': 'value1', 'key2': 'value2'}
self.assertEqual(expected, resp_metadata)
@test.idempotent_id('3043c57d-7e0e-49a6-9a96-ad569c265e6a')
def test_get_server_metadata_item(self):
# The value for a specific metadata key should be returned
- meta = self.client.get_server_metadata_item(self.server_id, 'key2')
+ meta = self.client.get_server_metadata_item(self.server_id,
+ 'key2')['meta']
self.assertEqual('value2', meta['key2'])
@test.idempotent_id('58c02d4f-5c67-40be-8744-d3fa5982eb1c')
@@ -93,7 +99,8 @@
self.client.set_server_metadata_item(self.server_id, 'nova', meta)
# Verify the meta item's value has been updated
- resp_metadata = self.client.list_server_metadata(self.server_id)
+ resp_metadata = (self.client.list_server_metadata(self.server_id)
+ ['metadata'])
expected = {'key1': 'value1', 'key2': 'value2', 'nova': 'alt'}
self.assertEqual(expected, resp_metadata)
@@ -103,6 +110,7 @@
self.client.delete_server_metadata_item(self.server_id, 'key1')
# Verify the metadata item has been removed
- resp_metadata = self.client.list_server_metadata(self.server_id)
+ resp_metadata = (self.client.list_server_metadata(self.server_id)
+ ['metadata'])
expected = {'key2': 'value2'}
self.assertEqual(expected, resp_metadata)
diff --git a/tempest/api/compute/servers/test_server_metadata_negative.py b/tempest/api/compute/servers/test_server_metadata_negative.py
index 5804dbe..cee60fb 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.py
@@ -32,7 +32,7 @@
def resource_setup(cls):
super(ServerMetadataNegativeTestJSON, cls).resource_setup()
cls.tenant_id = cls.client.tenant_id
- server = cls.create_test_server(meta={}, wait_until='ACTIVE')
+ server = cls.create_test_server(metadata={}, wait_until='ACTIVE')
cls.server_id = server['id']
@@ -48,7 +48,7 @@
meta = {key: 'data1'}
self.assertRaises((lib_exc.BadRequest, lib_exc.OverLimit),
self.create_test_server,
- meta=meta)
+ metadata=meta)
# no teardown - all creates should fail
@@ -59,7 +59,7 @@
meta = {'': 'data1'}
self.assertRaises(lib_exc.BadRequest,
self.create_test_server,
- meta=meta)
+ metadata=meta)
@test.attr(type=['negative'])
@test.idempotent_id('4d9cd7a3-2010-4b41-b8fe-3bbf0b169466')
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index 9d06188..f8567cf 100644
--- a/tempest/api/compute/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/servers/test_server_rescue_negative.py
@@ -62,7 +62,7 @@
def _create_volume(self):
volume = self.volumes_extensions_client.create_volume(
size=CONF.volume.volume_size, display_name=data_utils.rand_name(
- self.__class__.__name__ + '_volume'))
+ self.__class__.__name__ + '_volume'))['volume']
self.addCleanup(self.delete_volume, volume['id'])
waiters.wait_for_volume_status(self.volumes_extensions_client,
volume['id'], 'available')
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index 8cfb670..d2fb652 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -52,9 +52,9 @@
wait_until='ACTIVE')
id2 = server['id']
self.assertNotEqual(id1, id2, "Did not create a new server")
- server = self.client.show_server(id1)
+ server = self.client.show_server(id1)['server']
name1 = server['name']
- server = self.client.show_server(id2)
+ server = self.client.show_server(id2)['server']
name2 = server['name']
self.assertEqual(name1, name2)
@@ -68,7 +68,7 @@
self.keypairs_client.list_keypairs()
server = self.create_test_server(key_name=key_name)
waiters.wait_for_server_status(self.client, server['id'], 'ACTIVE')
- server = self.client.show_server(server['id'])
+ server = self.client.show_server(server['id'])['server']
self.assertEqual(key_name, server['key_name'])
def _update_server_name(self, server_id, status):
@@ -80,7 +80,7 @@
waiters.wait_for_server_status(self.client, server_id, status)
# Verify the name of the server has changed
- server = self.client.show_server(server_id)
+ server = self.client.show_server(server_id)['server']
self.assertEqual(new_name, server['name'])
return server
@@ -112,7 +112,7 @@
waiters.wait_for_server_status(self.client, server['id'], 'ACTIVE')
# Verify the access addresses have been updated
- server = self.client.show_server(server['id'])
+ server = self.client.show_server(server['id'])['server']
self.assertEqual('1.1.1.1', server['accessIPv4'])
self.assertEqual('::babe:202:202', server['accessIPv6'])
@@ -121,5 +121,5 @@
# Create a server without an IPv4 address(only IPv6 address).
server = self.create_test_server(accessIPv6='2001:2001::3')
waiters.wait_for_server_status(self.client, server['id'], 'ACTIVE')
- server = self.client.show_server(server['id'])
+ server = self.client.show_server(server['id'])['server']
self.assertEqual('2001:2001::3', server['accessIPv6'])
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index d5b60da..6946be4 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -236,7 +236,7 @@
metadata = {'a': 'b' * 260}
self.assertRaises((lib_exc.BadRequest, lib_exc.OverLimit),
self.create_test_server,
- meta=metadata)
+ metadata=metadata)
@test.attr(type=['negative'])
@test.idempotent_id('aa8eed43-e2cb-4ebf-930b-da14f6a21d81')
@@ -476,7 +476,7 @@
self.server_id,
'SHELVED')
- server = self.client.show_server(self.server_id)
+ server = self.client.show_server(self.server_id)['server']
image_name = server['name'] + '-shelved'
params = {'name': image_name}
images = self.images_client.list_images(**params)['images']
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index b5a24c7..484c156 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -64,7 +64,7 @@
def resource_setup(cls):
super(AuthorizationTestJSON, cls).resource_setup()
server = cls.create_test_server(wait_until='ACTIVE')
- cls.server = cls.client.show_server(server['id'])
+ cls.server = cls.client.show_server(server['id'])['server']
name = data_utils.rand_name('image')
body = cls.glance_client.create_image(name=name,
@@ -181,7 +181,8 @@
def test_create_server_with_unauthorized_image(self):
# Server creation with another user's image should fail
self.assertRaises(lib_exc.BadRequest, self.alt_client.create_server,
- 'test', self.image['id'], self.flavor_ref)
+ name='test', imageRef=self.image['id'],
+ flavorRef=self.flavor_ref)
@test.idempotent_id('acf8724b-142b-4044-82c3-78d31a533f24')
def test_create_server_fails_when_tenant_incorrect(self):
@@ -193,8 +194,8 @@
auth_data=self.client.auth_provider.auth_data
)
self.assertRaises(lib_exc.BadRequest,
- self.alt_client.create_server, 'test',
- self.image['id'], self.flavor_ref)
+ self.alt_client.create_server, name='test',
+ imageRef=self.image['id'], flavorRef=self.flavor_ref)
@test.idempotent_id('f03d1ded-7fd4-4d29-bc13-e2391f29c625')
def test_create_keypair_in_analt_user_tenant(self):
diff --git a/tempest/api/compute/test_networks.py b/tempest/api/compute/test_networks.py
index b53db3d..d4b8003 100644
--- a/tempest/api/compute/test_networks.py
+++ b/tempest/api/compute/test_networks.py
@@ -29,7 +29,7 @@
@classmethod
def setup_clients(cls):
super(ComputeNetworksTest, cls).setup_clients()
- cls.client = cls.os.networks_client
+ cls.client = cls.os.compute_networks_client
@test.idempotent_id('3fe07175-312e-49a5-a623-5f52eeada4c2')
def test_list_networks(self):
diff --git a/tempest/api/compute/test_versions.py b/tempest/api/compute/test_versions.py
index 369cf31..f94cee6 100644
--- a/tempest/api/compute/test_versions.py
+++ b/tempest/api/compute/test_versions.py
@@ -20,5 +20,53 @@
@test.idempotent_id('6c0a0990-43b6-4529-9b61-5fd8daf7c55c')
def test_list_api_versions(self):
+ """Test that a get of the unversioned url returns the choices doc.
+
+ A key feature in OpenStack services is the idea that you can
+ GET / on the service and get a list of the versioned endpoints
+ that you can access. This comes back as a status 300
+ request. It's important that this is available to API
+ consumers to discover the API they can use.
+
+ """
result = self.versions_client.list_versions()
- self.assertIsNotNone(result)
+ versions = result['versions']
+ # NOTE(sdague): at a later point we may want to loosen this
+ # up, but for now this should be true of all Novas deployed.
+ self.assertEqual(versions[0]['id'], 'v2.0',
+ "The first listed version should be v2.0")
+
+ @test.idempotent_id('b953a29e-929c-4a8e-81be-ec3a7e03cb76')
+ def test_get_version_details(self):
+ """Test individual version endpoints info works.
+
+ In addition to the GET / version request, there is also a
+ version info document stored at the top of the versioned
+ endpoints. This provides access to details about that
+ endpoint, including min / max version if that implements
+ microversions.
+
+ This test starts with the version list, iterates all the
+ returned endpoints, and fetches them. This will also ensure
+ that all the version links are followable constructs which
+ will help detect configuration issues when SSL termination
+ isn't done completely for a site.
+
+ """
+ result = self.versions_client.list_versions()
+ versions = result['versions']
+
+ # iterate through all the versions that are returned and
+ # attempt to get their version documents.
+ for version in versions:
+ links = [x for x in version['links'] if x['rel'] == 'self']
+ self.assertEqual(
+ len(links), 1,
+ "There should only be 1 self link in %s" % version)
+ link = links[0]
+ # this is schema validated
+ result = self.versions_client.get_version_by_url(link['href'])
+ # ensure the new self link matches the old one
+ newlinks = [x for x in result['version']['links']
+ if x['rel'] == 'self']
+ self.assertEqual(links, newlinks)
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index ba34039..ab4ddf7 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -70,8 +70,8 @@
adminPass=admin_pass)
# Record addresses so that we can ssh later
- self.server['addresses'] = (
- self.servers_client.list_addresses(self.server['id']))
+ self.server['addresses'] = self.servers_client.list_addresses(
+ self.server['id'])['addresses']
# Create a volume and wait for it to become ready
self.volume = self.volumes_client.create_volume(
@@ -84,7 +84,7 @@
self.attachment = self.servers_client.attach_volume(
self.server['id'],
volumeId=self.volume['id'],
- device='/dev/%s' % self.device)
+ device='/dev/%s' % self.device)['volumeAttachment']
self.volumes_client.wait_for_volume_status(self.volume['id'], 'in-use')
self.addCleanup(self._detach, self.server['id'], self.volume['id'])
@@ -139,14 +139,14 @@
self._create_and_attach()
# List Volume attachment of the server
body = self.servers_client.list_volume_attachments(
- self.server['id'])
+ self.server['id'])['volumeAttachments']
self.assertEqual(1, len(body))
self.assertIn(self.attachment, body)
# Get Volume attachment of the server
body = self.servers_client.get_volume_attachment(
self.server['id'],
- self.attachment['id'])
+ self.attachment['id'])['volumeAttachment']
self.assertEqual(self.server['id'], body['serverId'])
self.assertEqual(self.volume['id'], body['volumeId'])
self.assertEqual(self.attachment['id'], body['id'])
diff --git a/tempest/api/compute/volumes/test_volume_snapshots.py b/tempest/api/compute/volumes/test_volume_snapshots.py
new file mode 100644
index 0000000..a00c0ba
--- /dev/null
+++ b/tempest/api/compute/volumes/test_volume_snapshots.py
@@ -0,0 +1,73 @@
+# Copyright 2015 Fujitsu(fnst) Corporation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest.common import waiters
+from tempest import config
+from tempest import test
+
+
+CONF = config.CONF
+
+
+class VolumesSnapshotsTestJSON(base.BaseV2ComputeTest):
+
+ @classmethod
+ def skip_checks(cls):
+ super(VolumesSnapshotsTestJSON, cls).skip_checks()
+ if not CONF.service_available.cinder:
+ skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+
+ @classmethod
+ def setup_clients(cls):
+ super(VolumesSnapshotsTestJSON, cls).setup_clients()
+ cls.volumes_client = cls.volumes_extensions_client
+ cls.snapshots_client = cls.snapshots_extensions_client
+
+ @test.idempotent_id('cd4ec87d-7825-450d-8040-6e2068f2da8f')
+ def test_volume_snapshot_create_get_list_delete(self):
+ v_name = data_utils.rand_name('Volume')
+ volume = self.volumes_client.create_volume(
+ size=CONF.volume.volume_size,
+ display_name=v_name)['volume']
+ self.addCleanup(self.delete_volume, volume['id'])
+ waiters.wait_for_volume_status(self.volumes_client, volume['id'],
+ 'available')
+ s_name = data_utils.rand_name('Snapshot')
+ # Create snapshot
+ snapshot = self.snapshots_client.create_snapshot(
+ volume['id'],
+ display_name=s_name)['snapshot']
+
+ def delete_snapshot(snapshot_id):
+ waiters.wait_for_snapshot_status(self.snapshots_client,
+ snapshot_id,
+ 'available')
+ # Delete snapshot
+ self.snapshots_client.delete_snapshot(snapshot_id)
+ self.snapshots_client.wait_for_resource_deletion(snapshot_id)
+
+ self.addCleanup(delete_snapshot, snapshot['id'])
+ self.assertEqual(volume['id'], snapshot['volumeId'])
+ # Get snapshot
+ fetched_snapshot = self.snapshots_client.show_snapshot(
+ snapshot['id'])['snapshot']
+ self.assertEqual(s_name, fetched_snapshot['displayName'])
+ self.assertEqual(volume['id'], fetched_snapshot['volumeId'])
+ # Fetch all snapshots
+ snapshots = self.snapshots_client.list_snapshots()['snapshots']
+ self.assertIn(snapshot['id'], map(lambda x: x['id'], snapshots))
diff --git a/tempest/api/compute/volumes/test_volumes_get.py b/tempest/api/compute/volumes/test_volumes_get.py
index f05a5a3..6074054 100644
--- a/tempest/api/compute/volumes/test_volumes_get.py
+++ b/tempest/api/compute/volumes/test_volumes_get.py
@@ -48,7 +48,7 @@
# Create volume
volume = self.client.create_volume(size=CONF.volume.volume_size,
display_name=v_name,
- metadata=metadata)
+ metadata=metadata)['volume']
self.addCleanup(self.delete_volume, volume['id'])
self.assertIn('id', volume)
self.assertIn('displayName', volume)
@@ -60,7 +60,7 @@
# Wait for Volume status to become ACTIVE
waiters.wait_for_volume_status(self.client, volume['id'], 'available')
# GET Volume
- fetched_volume = self.client.show_volume(volume['id'])
+ fetched_volume = self.client.show_volume(volume['id'])['volume']
# Verification of details of fetched Volume
self.assertEqual(v_name,
fetched_volume['displayName'],
diff --git a/tempest/api/compute/volumes/test_volumes_list.py b/tempest/api/compute/volumes/test_volumes_list.py
index 421d96f..f0ed141 100644
--- a/tempest/api/compute/volumes/test_volumes_list.py
+++ b/tempest/api/compute/volumes/test_volumes_list.py
@@ -56,10 +56,10 @@
try:
volume = cls.client.create_volume(size=CONF.volume.volume_size,
display_name=v_name,
- metadata=metadata)
+ metadata=metadata)['volume']
waiters.wait_for_volume_status(cls.client,
volume['id'], 'available')
- volume = cls.client.show_volume(volume['id'])
+ volume = cls.client.show_volume(volume['id'])['volume']
cls.volume_list.append(volume)
cls.volume_id_list.append(volume['id'])
except Exception:
@@ -89,7 +89,7 @@
def test_volume_list(self):
# Should return the list of Volumes
# Fetch all Volumes
- fetched_list = self.client.list_volumes()
+ fetched_list = self.client.list_volumes()['volumes']
# Now check if all the Volumes created in setup are in fetched list
missing_volumes = [
v for v in self.volume_list if v not in fetched_list
@@ -104,7 +104,7 @@
def test_volume_list_with_details(self):
# Should return the list of Volumes with details
# Fetch all Volumes
- fetched_list = self.client.list_volumes(detail=True)
+ fetched_list = self.client.list_volumes(detail=True)['volumes']
# Now check if all the Volumes created in setup are in fetched list
missing_volumes = [
v for v in self.volume_list if v not in fetched_list
@@ -119,7 +119,7 @@
def test_volume_list_param_limit(self):
# Return the list of volumes based on limit set
params = {'limit': 2}
- fetched_vol_list = self.client.list_volumes(**params)
+ fetched_vol_list = self.client.list_volumes(**params)['volumes']
self.assertEqual(len(fetched_vol_list), params['limit'],
"Failed to list volumes by limit set")
@@ -128,7 +128,8 @@
def test_volume_list_with_detail_param_limit(self):
# Return the list of volumes with details based on limit set.
params = {'limit': 2}
- fetched_vol_list = self.client.list_volumes(detail=True, **params)
+ fetched_vol_list = self.client.list_volumes(detail=True,
+ **params)['volumes']
self.assertEqual(len(fetched_vol_list), params['limit'],
"Failed to list volume details by limit set")
@@ -137,9 +138,9 @@
def test_volume_list_param_offset_and_limit(self):
# Return the list of volumes based on offset and limit set.
# get all volumes list
- all_vol_list = self.client.list_volumes()
+ all_vol_list = self.client.list_volumes()['volumes']
params = {'offset': 1, 'limit': 1}
- fetched_vol_list = self.client.list_volumes(**params)
+ fetched_vol_list = self.client.list_volumes(**params)['volumes']
# Validating length of the fetched volumes
self.assertEqual(len(fetched_vol_list), params['limit'],
@@ -154,9 +155,10 @@
def test_volume_list_with_detail_param_offset_and_limit(self):
# Return the list of volumes details based on offset and limit set.
# get all volumes list
- all_vol_list = self.client.list_volumes(detail=True)
+ all_vol_list = self.client.list_volumes(detail=True)['volumes']
params = {'offset': 1, 'limit': 1}
- fetched_vol_list = self.client.list_volumes(detail=True, **params)
+ fetched_vol_list = self.client.list_volumes(detail=True,
+ **params)['volumes']
# Validating length of the fetched volumes
self.assertEqual(len(fetched_vol_list), params['limit'],
diff --git a/tempest/api/database/flavors/test_flavors.py b/tempest/api/database/flavors/test_flavors.py
index c97ddd7..62c1e05 100644
--- a/tempest/api/database/flavors/test_flavors.py
+++ b/tempest/api/database/flavors/test_flavors.py
@@ -28,7 +28,8 @@
@test.idempotent_id('c94b825e-0132-4686-8049-8a4a2bc09525')
def test_get_db_flavor(self):
# The expected flavor details should be returned
- flavor = self.client.get_db_flavor_details(self.db_flavor_ref)
+ flavor = (self.client.get_db_flavor_details(self.db_flavor_ref)
+ ['flavor'])
self.assertEqual(self.db_flavor_ref, str(flavor['id']))
self.assertIn('ram', flavor)
self.assertIn('links', flavor)
@@ -37,9 +38,10 @@
@test.attr(type='smoke')
@test.idempotent_id('685025d6-0cec-4673-8a8d-995cb8e0d3bb')
def test_list_db_flavors(self):
- flavor = self.client.get_db_flavor_details(self.db_flavor_ref)
+ flavor = (self.client.get_db_flavor_details(self.db_flavor_ref)
+ ['flavor'])
# List of all flavors should contain the expected flavor
- flavors = self.client.list_db_flavors()
+ flavors = self.client.list_db_flavors()['flavors']
self.assertIn(flavor, flavors)
def _check_values(self, names, db_flavor, os_flavor, in_db=True):
@@ -57,7 +59,7 @@
@test.idempotent_id('afb2667f-4ec2-4925-bcb7-313fdcffb80d')
@test.services('compute')
def test_compare_db_flavors_with_os(self):
- db_flavors = self.client.list_db_flavors()
+ db_flavors = self.client.list_db_flavors()['flavors']
os_flavors = (self.os_flavors_client.list_flavors(detail=True)
['flavors'])
self.assertEqual(len(os_flavors), len(db_flavors),
@@ -65,7 +67,7 @@
(os_flavors, db_flavors))
for os_flavor in os_flavors:
db_flavor =\
- self.client.get_db_flavor_details(os_flavor['id'])
+ self.client.get_db_flavor_details(os_flavor['id'])['flavor']
self._check_values(['id', 'name', 'ram'], db_flavor, os_flavor)
self._check_values(['disk', 'vcpus', 'swap'], db_flavor, os_flavor,
in_db=False)
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index 5681ac6..b5f86da 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -92,7 +92,6 @@
token_id = token_auth.response['x-subject-token']
orig_expires_at = token_auth['token']['expires_at']
- orig_issued_at = token_auth['token']['issued_at']
orig_user = token_auth['token']['user']
self.assertIsInstance(token_auth['token']['expires_at'], unicode)
@@ -117,7 +116,6 @@
self.assertEqual(orig_expires_at, token_auth['token']['expires_at'],
'Expiration time should match original token')
self.assertIsInstance(token_auth['token']['issued_at'], unicode)
- self.assertNotEqual(orig_issued_at, token_auth['token']['issued_at'])
self.assertEqual(set(['password', 'token']),
set(token_auth['token']['methods']))
self.assertEqual(orig_user, token_auth['token']['user'],
diff --git a/tempest/api/identity/v2/test_ec2_credentials.py b/tempest/api/identity/v2/test_ec2_credentials.py
new file mode 100644
index 0000000..dbb50be
--- /dev/null
+++ b/tempest/api/identity/v2/test_ec2_credentials.py
@@ -0,0 +1,111 @@
+# Copyright 2015 OpenStack Foundation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest_lib import exceptions as lib_exc
+
+from tempest.api.identity import base
+from tempest import test
+
+
+class EC2CredentialsTest(base.BaseIdentityV2Test):
+
+ @classmethod
+ def skip_checks(cls):
+ super(EC2CredentialsTest, cls).skip_checks()
+ if not test.is_extension_enabled('OS-EC2', 'identity'):
+ msg = "OS-EC2 identity extension not enabled."
+ raise cls.skipException(msg)
+
+ @classmethod
+ def resource_setup(cls):
+ super(EC2CredentialsTest, cls).resource_setup()
+ cls.creds = cls.os.credentials
+
+ @test.idempotent_id('b580fab9-7ae9-46e8-8138-417260cb6f9f')
+ def test_create_ec2_credentials(self):
+ """Create user ec2 credentials."""
+ resp = self.non_admin_client.create_user_ec2_credentials(
+ self.creds.credentials.user_id,
+ self.creds.credentials.tenant_id)
+ access = resp['access']
+ self.addCleanup(
+ self.non_admin_client.delete_user_ec2_credentials,
+ self.creds.credentials.user_id, access)
+ self.assertNotEmpty(resp['access'])
+ self.assertNotEmpty(resp['secret'])
+ self.assertEqual(self.creds.credentials.user_id, resp['user_id'])
+ self.assertEqual(self.creds.credentials.tenant_id, resp['tenant_id'])
+
+ @test.idempotent_id('9e2ea42f-0a4f-468c-a768-51859ce492e0')
+ def test_list_ec2_credentials(self):
+ """Get the list of user ec2 credentials."""
+ created_creds = []
+ fetched_creds = []
+ # create first ec2 credentials
+ creds1 = self.non_admin_client.create_user_ec2_credentials(
+ self.creds.credentials.user_id, self.creds.credentials.tenant_id)
+ created_creds.append(creds1['access'])
+ # create second ec2 credentials
+ creds2 = self.non_admin_client.create_user_ec2_credentials(
+ self.creds.credentials.user_id, self.creds.credentials.tenant_id)
+ created_creds.append(creds2['access'])
+ # add credentials to be cleaned up
+ self.addCleanup(
+ self.non_admin_client.delete_user_ec2_credentials,
+ self.creds.credentials.user_id, creds1['access'])
+ self.addCleanup(
+ self.non_admin_client.delete_user_ec2_credentials,
+ self.creds.credentials.user_id, creds2['access'])
+ # get the list of user ec2 credentials
+ resp = self.non_admin_client.list_user_ec2_credentials(
+ self.creds.credentials.user_id)
+ fetched_creds = [cred['access'] for cred in resp]
+ # created credentials should be in a fetched list
+ missing = [cred for cred in created_creds
+ if cred not in fetched_creds]
+ self.assertEmpty(missing,
+ "Failed to find ec2_credentials %s in fetched list" %
+ ', '.join(cred for cred in missing))
+
+ @test.idempotent_id('cb284075-b613-440d-83ca-fe0b33b3c2b8')
+ def test_show_ec2_credentials(self):
+ """Get the definite user ec2 credentials."""
+ resp = self.non_admin_client.create_user_ec2_credentials(
+ self.creds.credentials.user_id,
+ self.creds.credentials.tenant_id)
+ self.addCleanup(
+ self.non_admin_client.delete_user_ec2_credentials,
+ self.creds.credentials.user_id, resp['access'])
+
+ ec2_creds = self.non_admin_client.show_user_ec2_credentials(
+ self.creds.credentials.user_id, resp['access']
+ )
+ for key in ['access', 'secret', 'user_id', 'tenant_id']:
+ self.assertEqual(ec2_creds[key], resp[key])
+
+ @test.idempotent_id('6aba0d4c-b76b-4e46-aa42-add79bc1551d')
+ def test_delete_ec2_credentials(self):
+ """Delete user ec2 credentials."""
+ resp = self.non_admin_client.create_user_ec2_credentials(
+ self.creds.credentials.user_id,
+ self.creds.credentials.tenant_id)
+ access = resp['access']
+ self.non_admin_client.delete_user_ec2_credentials(
+ self.creds.credentials.user_id, access)
+ self.assertRaises(
+ lib_exc.NotFound,
+ self.non_admin_client.show_user_ec2_credentials,
+ self.creds.credentials.user_id,
+ access)
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index b446ec3..a336507 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -172,7 +172,7 @@
self.assertEqual(params[key], image[key], msg)
@test.idempotent_id('1e341d7a-90a9-494c-b143-2cdf2aeb6aee')
- def test_index_no_params(self):
+ def test_list_no_params(self):
# Simple test to see all fixture images returned
images_list = self.client.list_images()['images']
image_list = map(lambda x: x['id'], images_list)
diff --git a/tempest/api/network/admin/test_quotas.py b/tempest/api/network/admin/test_quotas.py
index 63395cc..f5c5784 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -51,18 +51,17 @@
def _check_quotas(self, new_quotas):
# Add a tenant to conduct the test
- test_tenant = data_utils.rand_name('test_tenant_')
- test_description = data_utils.rand_name('desc_')
- tenant = self.identity_admin_client.create_tenant(
- name=test_tenant,
- description=test_description)
- tenant_id = tenant['id']
- self.addCleanup(self.identity_admin_client.delete_tenant, tenant_id)
+ project = data_utils.rand_name('test_project_')
+ description = data_utils.rand_name('desc_')
+ project = self.identity_utils.create_project(name=project,
+ description=description)
+ project_id = project['id']
+ self.addCleanup(self.identity_utils.delete_project, project_id)
# Change quotas for tenant
- quota_set = self.admin_client.update_quotas(tenant_id,
+ quota_set = self.admin_client.update_quotas(project_id,
**new_quotas)['quota']
- self.addCleanup(self.admin_client.reset_quotas, tenant_id)
+ self.addCleanup(self.admin_client.reset_quotas, project_id)
for key, value in six.iteritems(new_quotas):
self.assertEqual(value, quota_set[key])
@@ -70,21 +69,21 @@
non_default_quotas = self.admin_client.list_quotas()
found = False
for qs in non_default_quotas['quotas']:
- if qs['tenant_id'] == tenant_id:
+ if qs['tenant_id'] == project_id:
found = True
self.assertTrue(found)
# Confirm from API quotas were changed as requested for tenant
- quota_set = self.admin_client.show_quotas(tenant_id)
+ quota_set = self.admin_client.show_quotas(project_id)
quota_set = quota_set['quota']
for key, value in six.iteritems(new_quotas):
self.assertEqual(value, quota_set[key])
# Reset quotas to default and confirm
- self.admin_client.reset_quotas(tenant_id)
+ self.admin_client.reset_quotas(project_id)
non_default_quotas = self.admin_client.list_quotas()
for q in non_default_quotas['quotas']:
- self.assertNotEqual(tenant_id, q['tenant_id'])
+ self.assertNotEqual(project_id, q['tenant_id'])
@test.idempotent_id('2390f766-836d-40ef-9aeb-e810d78207fb')
def test_quotas(self):
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index aa3d274..ca5a868 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -85,21 +85,21 @@
self.assertEqual(show_body['router']['name'], updated_name)
@test.idempotent_id('e54dd3a3-4352-4921-b09d-44369ae17397')
- def test_create_router_setting_tenant_id(self):
- # Test creating router from admin user setting tenant_id.
- test_tenant = data_utils.rand_name('test_tenant_')
- test_description = data_utils.rand_name('desc_')
- tenant = self.identity_admin_client.create_tenant(
- name=test_tenant, description=test_description)
- tenant_id = tenant['id']
- self.addCleanup(self.identity_admin_client.delete_tenant, tenant_id)
+ def test_create_router_setting_project_id(self):
+ # Test creating router from admin user setting project_id.
+ project = data_utils.rand_name('test_tenant_')
+ description = data_utils.rand_name('desc_')
+ project = self.identity_utils.create_project(name=project,
+ description=description)
+ project_id = project['id']
+ self.addCleanup(self.identity_utils.delete_project, project_id)
name = data_utils.rand_name('router-')
create_body = self.admin_client.create_router(name,
- tenant_id=tenant_id)
+ tenant_id=project_id)
self.addCleanup(self.admin_client.delete_router,
create_body['router']['id'])
- self.assertEqual(tenant_id, create_body['router']['tenant_id'])
+ self.assertEqual(project_id, create_body['router']['tenant_id'])
@test.idempotent_id('847257cc-6afd-4154-b8fb-af49f5670ce8')
@test.requires_ext(extension='ext-gw-mode', service='network')
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index cb6d1db..8f1f0d6 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -87,7 +87,7 @@
server_id = body['physical_resource_id']
LOG.debug('Console output for %s', server_id)
output = cls.servers_client.get_console_output(
- server_id, None).data
+ server_id, None)['output']
LOG.debug(output)
raise e
@@ -184,7 +184,7 @@
def test_created_server(self):
"""Verifies created sever."""
server_id = self.test_resources.get('Server')['physical_resource_id']
- server = self.servers_client.show_server(server_id)
+ server = self.servers_client.show_server(server_id)['server']
self.assertEqual(self.keypair_name, server['key_name'])
self.assertEqual('ACTIVE', server['status'])
network = server['addresses'][self.neutron_basic_template['resources'][
diff --git a/tempest/api/telemetry/test_telemetry_alarming_api.py b/tempest/api/telemetry/test_telemetry_alarming_api.py
index 13da9cb..6c84b98 100644
--- a/tempest/api/telemetry/test_telemetry_alarming_api.py
+++ b/tempest/api/telemetry/test_telemetry_alarming_api.py
@@ -56,18 +56,24 @@
'comparison_operator': 'eq',
'threshold': 70.0,
'period': 60}
- alarm_name = data_utils.rand_name('telemetry-alarm-update')
+ alarm_name_updated = data_utils.rand_name('telemetry-alarm-update')
body = self.telemetry_client.update_alarm(
alarm_id,
threshold_rule=new_rule,
- name=alarm_name,
+ name=alarm_name_updated,
type='threshold')
- self.assertEqual(alarm_name, body['name'])
+ self.assertEqual(alarm_name_updated, body['name'])
self.assertDictContainsSubset(new_rule, body['threshold_rule'])
# Get and verify details of an alarm after update
body = self.telemetry_client.show_alarm(alarm_id)
- self.assertEqual(alarm_name, body['name'])
+ self.assertEqual(alarm_name_updated, body['name'])
self.assertDictContainsSubset(new_rule, body['threshold_rule'])
+ # Get history for the alarm and verify the same
+ body = self.telemetry_client.show_alarm_history(alarm_id)
+ self.assertEqual("rule change", body[0]['type'])
+ self.assertIn(alarm_name_updated, body[0]['detail'])
+ self.assertEqual("creation", body[1]['type'])
+ self.assertIn(alarm_name, body[1]['detail'])
# Delete alarm and verify if deleted
self.telemetry_client.delete_alarm(alarm_id)
self.assertRaises(lib_exc.NotFound,
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index 784f1b6..aa6bfdf 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -15,10 +15,18 @@
from tempest.api.volume import base
from tempest.common.utils import data_utils
+from tempest import config
from tempest import test
+CONF = config.CONF
+
class SnapshotsActionsV2Test(base.BaseVolumeAdminTest):
+ @classmethod
+ def skip_checks(cls):
+ super(SnapshotsActionsV2Test, cls).skip_checks()
+ if not CONF.volume_feature_enabled.snapshot:
+ raise cls.skipException("Cinder snapshot feature disabled")
@classmethod
def setup_clients(cls):
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index f9117ed..b2e52bb 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -98,21 +98,22 @@
@test.idempotent_id('874b35a9-51f1-4258-bec5-cd561b6690d3')
def test_delete_quota(self):
- # Admin can delete the resource quota set for a tenant
- tenant_name = data_utils.rand_name('quota_tenant')
- identity_client = self.os_adm.identity_client
- tenant = identity_client.create_tenant(tenant_name)
- tenant_id = tenant['id']
- self.addCleanup(identity_client.delete_tenant, tenant_id)
+ # Admin can delete the resource quota set for a project
+ project_name = data_utils.rand_name('quota_tenant')
+ description = data_utils.rand_name('desc_')
+ project = self.identity_utils.create_project(project_name,
+ description=description)
+ project_id = project['id']
+ self.addCleanup(self.identity_utils.delete_project, project_id)
quota_set_default = self.quotas_client.show_default_quota_set(
- tenant_id)['quota_set']
+ project_id)['quota_set']
volume_default = quota_set_default['volumes']
- self.quotas_client.update_quota_set(tenant_id,
+ self.quotas_client.update_quota_set(project_id,
volumes=(int(volume_default) + 5))
- self.quotas_client.delete_quota_set(tenant_id)
- quota_set_new = (self.quotas_client.show_quota_set(tenant_id)
+ self.quotas_client.delete_quota_set(project_id)
+ quota_set_new = (self.quotas_client.show_quota_set(project_id)
['quota_set'])
self.assertEqual(volume_default, quota_set_new['volumes'])
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index cc020e3..12e6761 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -61,7 +61,7 @@
def setup_clients(cls):
super(BaseVolumeTest, cls).setup_clients()
cls.servers_client = cls.os.servers_client
- cls.networks_client = cls.os.networks_client
+ cls.compute_networks_client = cls.os.compute_networks_client
cls.images_client = cls.os.images_client
if cls._api_version == 1:
diff --git a/tempest/api/volume/test_snapshot_metadata.py b/tempest/api/volume/test_snapshot_metadata.py
index ce6ba90..e50ca95 100644
--- a/tempest/api/volume/test_snapshot_metadata.py
+++ b/tempest/api/volume/test_snapshot_metadata.py
@@ -16,10 +16,18 @@
from testtools import matchers
from tempest.api.volume import base
+from tempest import config
from tempest import test
+CONF = config.CONF
+
class SnapshotV2MetadataTestJSON(base.BaseVolumeTest):
+ @classmethod
+ def skip_checks(cls):
+ super(SnapshotV2MetadataTestJSON, cls).skip_checks()
+ if not CONF.volume_feature_enabled.snapshot:
+ raise cls.skipException("Cinder snapshot feature disabled")
@classmethod
def setup_clients(cls):
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 7eaa9cc..9866da3 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -85,9 +85,7 @@
snapshot = self.create_snapshot(self.volume_origin['id'],
force=True)
# Delete the snapshot
- self.snapshots_client.delete_snapshot(snapshot['id'])
- self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
- self.snapshots.remove(snapshot)
+ self.cleanup_snapshot(snapshot)
@test.idempotent_id('2a8abbe4-d871-46db-b049-c41f5af8216e')
def test_snapshot_create_get_list_update_delete(self):
@@ -126,9 +124,7 @@
self.assertEqual(new_desc, updated_snapshot[self.descrip_field])
# Delete the snapshot
- self.snapshots_client.delete_snapshot(snapshot['id'])
- self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
- self.snapshots.remove(snapshot)
+ self.cleanup_snapshot(snapshot)
@test.idempotent_id('59f41f43-aebf-48a9-ab5d-d76340fab32b')
def test_snapshots_list_with_params(self):
@@ -137,6 +133,7 @@
display_name = data_utils.rand_name('snap')
params = {self.name_field: display_name}
snapshot = self.create_snapshot(self.volume_origin['id'], **params)
+ self.addCleanup(self.cleanup_snapshot, snapshot)
# Verify list snapshots by display_name filter
params = {self.name_field: snapshot[self.name_field]}
@@ -158,6 +155,7 @@
display_name = data_utils.rand_name('snap')
params = {self.name_field: display_name}
snapshot = self.create_snapshot(self.volume_origin['id'], **params)
+ self.addCleanup(self.cleanup_snapshot, snapshot)
# Verify list snapshot details by display_name filter
params = {self.name_field: snapshot[self.name_field]}
@@ -181,7 +179,13 @@
self.volumes_client.wait_for_volume_status(volume['id'], 'available')
self.volumes_client.delete_volume(volume['id'])
self.volumes_client.wait_for_resource_deletion(volume['id'])
- self.clear_snapshots()
+ self.cleanup_snapshot(snapshot)
+
+ def cleanup_snapshot(self, snapshot):
+ # Delete the snapshot
+ self.snapshots_client.delete_snapshot(snapshot['id'])
+ self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
+ self.snapshots.remove(snapshot)
class VolumesV1SnapshotTestJSON(VolumesV2SnapshotTestJSON):
diff --git a/tempest/api_schema/response/compute/v2_1/snapshots.py b/tempest/api_schema/response/compute/v2_1/snapshots.py
new file mode 100644
index 0000000..01a524b
--- /dev/null
+++ b/tempest/api_schema/response/compute/v2_1/snapshots.py
@@ -0,0 +1,61 @@
+# Copyright 2015 Fujitsu(fnst) Corporation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+common_snapshot_info = {
+ 'type': 'object',
+ 'properties': {
+ 'id': {'type': 'string'},
+ 'volumeId': {'type': 'string'},
+ 'status': {'type': 'string'},
+ 'size': {'type': 'integer'},
+ 'createdAt': {'type': 'string'},
+ 'displayName': {'type': ['string', 'null']},
+ 'displayDescription': {'type': ['string', 'null']}
+ },
+ 'additionalProperties': False,
+ 'required': ['id', 'volumeId', 'status', 'size',
+ 'createdAt', 'displayName', 'displayDescription']
+}
+
+create_get_snapshot = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'snapshot': common_snapshot_info
+ },
+ 'additionalProperties': False,
+ 'required': ['snapshot']
+ }
+}
+
+list_snapshots = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'snapshots': {
+ 'type': 'array',
+ 'items': common_snapshot_info
+ }
+ },
+ 'additionalProperties': False,
+ 'required': ['snapshots']
+ }
+}
+
+delete_snapshot = {
+ 'status_code': [202]
+}
diff --git a/tempest/api_schema/response/compute/v2_1/versions.py b/tempest/api_schema/response/compute/v2_1/versions.py
index a01dd41..08a9fab 100644
--- a/tempest/api_schema/response/compute/v2_1/versions.py
+++ b/tempest/api_schema/response/compute/v2_1/versions.py
@@ -12,6 +12,45 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
+
+
+_version = {
+ 'type': 'object',
+ 'properties': {
+ 'id': {'type': 'string'},
+ 'links': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'href': {'type': 'string', 'format': 'uri'},
+ 'rel': {'type': 'string'},
+ 'type': {'type': 'string'},
+ },
+ 'required': ['href', 'rel'],
+ 'additionalProperties': False
+ }
+ },
+ 'status': {'type': 'string'},
+ 'updated': {'type': 'string', 'format': 'date-time'},
+ 'version': {'type': 'string'},
+ 'min_version': {'type': 'string'},
+ 'media-types': {
+ 'type': 'array',
+ 'properties': {
+ 'base': {'type': 'string'},
+ 'type': {'type': 'string'},
+ }
+ },
+ },
+ # NOTE: version and min_version have been added since Kilo,
+ # so they should not be required.
+ # NOTE(sdague): media-types only shows up in single version requests.
+ 'required': ['id', 'links', 'status', 'updated'],
+ 'additionalProperties': False
+}
+
list_versions = {
'status_code': [200],
'response_body': {
@@ -19,36 +58,53 @@
'properties': {
'versions': {
'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'id': {'type': 'string'},
- 'links': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'href': {'type': 'string',
- 'format': 'uri'},
- 'rel': {'type': 'string'},
- },
- 'required': ['href', 'rel'],
- 'additionalProperties': False
- }
- },
- 'status': {'type': 'string'},
- 'updated': {'type': 'string', 'format': 'date-time'},
- 'version': {'type': 'string'},
- 'min_version': {'type': 'string'}
- },
- # NOTE: version and min_version have been added since Kilo,
- # so they should not be required.
- 'required': ['id', 'links', 'status', 'updated'],
- 'additionalProperties': False
- }
+ 'items': _version
}
},
'required': ['versions'],
'additionalProperties': False
}
}
+
+
+_detail_get_version = copy.deepcopy(_version)
+_detail_get_version['properties'].pop('min_version')
+_detail_get_version['properties'].pop('version')
+_detail_get_version['properties'].pop('updated')
+_detail_get_version['properties']['media-types'] = {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'base': {'type': 'string'},
+ 'type': {'type': 'string'}
+ }
+ }
+}
+_detail_get_version['required'] = ['id', 'links', 'status', 'media-types']
+
+get_version = {
+ 'status_code': [300],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'choices': {
+ 'type': 'array',
+ 'items': _detail_get_version
+ }
+ },
+ 'required': ['choices'],
+ 'additionalProperties': False
+ }
+}
+
+get_one_version = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'version': _version
+ },
+ 'additionalProperties': False
+ }
+}
diff --git a/tempest/clients.py b/tempest/clients.py
index c0d4585..2756fa8 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -16,8 +16,8 @@
import copy
from oslo_log import log as logging
-from tempest_lib.services.identity.v2.token_client import TokenClientJSON
-from tempest_lib.services.identity.v3.token_client import V3TokenClientJSON
+from tempest_lib.services.identity.v2.token_client import TokenClient
+from tempest_lib.services.identity.v3.token_client import V3TokenClient
from tempest.common import cred_provider
from tempest.common import negative_rest_client
@@ -59,7 +59,8 @@
from tempest.services.compute.json.limits_client import LimitsClient
from tempest.services.compute.json.migrations_client import \
MigrationsClient
-from tempest.services.compute.json.networks_client import NetworksClient
+from tempest.services.compute.json.networks_client import NetworksClient \
+ as ComputeNetworksClient
from tempest.services.compute.json.quota_classes_client import \
QuotaClassesClient
from tempest.services.compute.json.quotas_client import QuotasClient
@@ -73,6 +74,8 @@
ServerGroupsClient
from tempest.services.compute.json.servers_client import ServersClient
from tempest.services.compute.json.services_client import ServicesClient
+from tempest.services.compute.json.snapshots_extensions_client import \
+ SnapshotsExtensionsClient
from tempest.services.compute.json.tenant_networks_client import \
TenantNetworksClient
from tempest.services.compute.json.tenant_usages_client import \
@@ -260,7 +263,8 @@
params.update(self.default_params)
self.agents_client = AgentsClient(self.auth_provider, **params)
- self.networks_client = NetworksClient(self.auth_provider, **params)
+ self.compute_networks_client = ComputeNetworksClient(
+ self.auth_provider, **params)
self.migrations_client = MigrationsClient(self.auth_provider,
**params)
self.security_group_default_rules_client = (
@@ -325,6 +329,8 @@
self.auth_provider, **params_volume)
self.compute_versions_client = VersionsClient(self.auth_provider,
**params_volume)
+ self.snapshots_extensions_client = SnapshotsExtensionsClient(
+ self.auth_provider, **params_volume)
def _set_database_clients(self):
self.database_flavors_client = DatabaseFlavorsClient(
@@ -377,14 +383,14 @@
# API version is marked as enabled
if CONF.identity_feature_enabled.api_v2:
if CONF.identity.uri:
- self.token_client = TokenClientJSON(
+ self.token_client = TokenClient(
CONF.identity.uri, **self.default_params)
else:
msg = 'Identity v2 API enabled, but no identity.uri set'
raise exceptions.InvalidConfiguration(msg)
if CONF.identity_feature_enabled.api_v3:
if CONF.identity.uri_v3:
- self.token_v3_client = V3TokenClientJSON(
+ self.token_v3_client = V3TokenClient(
CONF.identity.uri_v3, **self.default_params)
else:
msg = 'Identity v3 API enabled, but no identity.uri_v3 set'
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index 3d24547..ce7728e 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -90,7 +90,7 @@
import yaml
from tempest import config
-from tempest import exceptions
+from tempest import exceptions as exc
from tempest.services.identity.v2.json import identity_client
from tempest.services.network.json import network_client
import tempest_lib.auth
@@ -155,11 +155,10 @@
for r in u.get('roles', ()):
try:
role = filter(lambda r_: r_['name'] == r, roles)[0]
- u['role_ids'] += [role['id']]
except IndexError:
- raise exceptions.TempestException(
- "Role: %s - doesn't exist" % r
- )
+ msg = "Role: %s doesn't exist" % r
+ raise exc.InvalidConfiguration(msg)
+ u['role_ids'] += [role['id']]
existing = [x['name'] for x in identity_admin.list_tenants()['tenants']]
for tenant in resources['tenants']:
if tenant not in existing:
@@ -285,17 +284,21 @@
{'number': 1,
'prefix': 'alt',
'roles': (CONF.auth.tempest_roles +
- [CONF.object_storage.operator_role])},
- {'number': 1,
- 'prefix': 'swift_admin',
- 'roles': (CONF.auth.tempest_roles +
- [CONF.object_storage.operator_role,
- CONF.object_storage.reseller_admin_role])},
- {'number': 1,
- 'prefix': 'stack_owner',
- 'roles': (CONF.auth.tempest_roles +
- [CONF.orchestration.stack_owner_role])},
- ]
+ [CONF.object_storage.operator_role])}]
+ if CONF.service_available.swift:
+ spec.append({'number': 1,
+ 'prefix': 'swift_operator',
+ 'roles': (CONF.auth.tempest_roles +
+ [CONF.object_storage.operator_role])})
+ spec.append({'number': 1,
+ 'prefix': 'swift_reseller_admin',
+ 'roles': (CONF.auth.tempest_roles +
+ [CONF.object_storage.reseller_admin_role])})
+ if CONF.service_available.heat:
+ spec.append({'number': 1,
+ 'prefix': 'stack_owner',
+ 'roles': (CONF.auth.tempest_roles +
+ [CONF.orchestration.stack_owner_role])})
if opts.admin:
spec.append({
'number': 1,
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 6973c87..5566f63 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -457,7 +457,7 @@
found,
"Couldn't find expected server %s" % server['name'])
- found = client.servers.show_server(found['id'])
+ found = client.servers.show_server(found['id'])['server']
# validate neutron is enabled and ironic disabled:
if (CONF.service_available.neutron and
not CONF.baremetal.driver_enabled):
@@ -869,7 +869,8 @@
kwargs['networks'] = [{'uuid': get_net_id(network)}
for network in server['networks']]
body = client.servers.create_server(
- server['name'], image_id, flavor_id, **kwargs)
+ name=server['name'], imageRef=image_id, flavorRef=flavor_id,
+ **kwargs)['server']
server_id = body['id']
client.servers.wait_for_server_status(server_id, 'ACTIVE')
# create security group(s) after server spawning
diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py
index 27b44f6..9e6bee3 100644
--- a/tempest/common/accounts.py
+++ b/tempest/common/accounts.py
@@ -284,7 +284,7 @@
identity_version=self.identity_version, **creds_dict)
net_creds = cred_provider.TestResources(credential)
net_clients = clients.Manager(credentials=credential)
- compute_network_client = net_clients.networks_client
+ compute_network_client = net_clients.compute_networks_client
net_name = self.hash_dict['networks'].get(hash, None)
try:
network = fixed_network.get_network_from_name(
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index 198814e..176be51 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -18,6 +18,7 @@
from tempest_lib.common.utils import data_utils
from tempest.common import fixed_network
+from tempest.common import service_client
from tempest.common import waiters
from tempest import config
@@ -50,8 +51,8 @@
else:
name = data_utils.rand_name(__name__ + "-instance")
- flavor = kwargs.get('flavor', CONF.compute.flavor_ref)
- image_id = kwargs.get('image_id', CONF.compute.image_ref)
+ flavor = kwargs.pop('flavor', CONF.compute.flavor_ref)
+ image_id = kwargs.pop('image_id', CONF.compute.image_ref)
kwargs = fixed_network.set_networks_kwarg(
tenant_network, kwargs) or {}
@@ -84,16 +85,20 @@
if wait_until is None:
wait_until = 'ACTIVE'
- body = clients.servers_client.create_server(name, image_id, flavor,
+ body = clients.servers_client.create_server(name=name, imageRef=image_id,
+ flavorRef=flavor,
**kwargs)
# handle the case of multiple servers
- servers = [body]
+ servers = []
if 'min_count' in kwargs or 'max_count' in kwargs:
# Get servers created which name match with name param.
body_servers = clients.servers_client.list_servers()
servers = \
[s for s in body_servers['servers'] if s['name'].startswith(name)]
+ else:
+ body = service_client.ResponseBody(body.response, body['server'])
+ servers = [body]
# The name of the method to associate a floating IP to as server is too
# long for PEP8 compliance so:
diff --git a/tempest/common/cred_client.py b/tempest/common/cred_client.py
new file mode 100644
index 0000000..7c3a77f
--- /dev/null
+++ b/tempest/common/cred_client.py
@@ -0,0 +1,146 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import abc
+
+from oslo_log import log as logging
+import six
+from tempest_lib import exceptions as lib_exc
+
+from tempest.common import cred_provider
+from tempest import config
+from tempest import exceptions
+from tempest.services.identity.v2.json import identity_client as v2_identity
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+@six.add_metaclass(abc.ABCMeta)
+class CredsClient(object):
+ """This class is a wrapper around the identity clients, to provide a
+ single interface for managing credentials in both v2 and v3 cases.
+ It's not bound to created credentials, only to a specific set of admin
+ credentials used for generating credentials.
+ """
+
+ def __init__(self, identity_client):
+ # The client implies version and credentials
+ self.identity_client = identity_client
+ self.credentials = self.identity_client.auth_provider.credentials
+
+ def create_user(self, username, password, project, email):
+ user = self.identity_client.create_user(
+ username, password, project['id'], email)
+ if 'user' in user:
+ user = user['user']
+ return user
+
+ @abc.abstractmethod
+ def create_project(self, name, description):
+ pass
+
+ def _check_role_exists(self, role_name):
+ try:
+ roles = self._list_roles()
+ role = next(r for r in roles if r['name'] == role_name)
+ except StopIteration:
+ return None
+ return role
+
+ def create_user_role(self, role_name):
+ if not self._check_role_exists(role_name):
+ self.identity_client.create_role(role_name)
+
+ def assign_user_role(self, user, project, role_name):
+ role = self._check_role_exists(role_name)
+ if not role:
+ msg = 'No "%s" role found' % role_name
+ raise lib_exc.NotFound(msg)
+ try:
+ self.identity_client.assign_user_role(project['id'], user['id'],
+ role['id'])
+ except lib_exc.Conflict:
+ LOG.debug("Role %s already assigned on project %s for user %s" % (
+ role['id'], project['id'], user['id']))
+
+ @abc.abstractmethod
+ def get_credentials(self, user, project, password):
+ pass
+
+ def delete_user(self, user_id):
+ self.identity_client.delete_user(user_id)
+
+ def _list_roles(self):
+ roles = self.identity_client.list_roles()
+ return roles
+
+
+class V2CredsClient(CredsClient):
+
+ def create_project(self, name, description):
+ tenant = self.identity_client.create_tenant(
+ name=name, description=description)
+ return tenant
+
+ def get_credentials(self, user, project, password):
+ return cred_provider.get_credentials(
+ identity_version='v2',
+ username=user['name'], user_id=user['id'],
+ tenant_name=project['name'], tenant_id=project['id'],
+ password=password)
+
+ def delete_project(self, project_id):
+ self.identity_client.delete_tenant(project_id)
+
+
+class V3CredsClient(CredsClient):
+
+ def __init__(self, identity_client, domain_name):
+ super(V3CredsClient, self).__init__(identity_client)
+ try:
+ # Domain names must be unique, in any case a list is returned,
+ # selecting the first (and only) element
+ self.creds_domain = self.identity_client.list_domains(
+ params={'name': domain_name})['domains'][0]
+ except lib_exc.NotFound:
+ # TODO(andrea) we could probably create the domain on the fly
+ msg = "Configured domain %s could not be found" % domain_name
+ raise exceptions.InvalidConfiguration(msg)
+
+ def create_project(self, name, description):
+ project = self.identity_client.create_project(
+ name=name, description=description,
+ domain_id=self.creds_domain['id'])['project']
+ return project
+
+ def get_credentials(self, user, project, password):
+ return cred_provider.get_credentials(
+ identity_version='v3',
+ username=user['name'], user_id=user['id'],
+ project_name=project['name'], project_id=project['id'],
+ password=password,
+ project_domain_name=self.creds_domain['name'])
+
+ def delete_project(self, project_id):
+ self.identity_client.delete_project(project_id)
+
+ def _list_roles(self):
+ roles = self.identity_client.list_roles()['roles']
+ return roles
+
+
+def get_creds_client(identity_client, project_domain_name=None):
+ if isinstance(identity_client, v2_identity.IdentityClient):
+ return V2CredsClient(identity_client)
+ else:
+ return V3CredsClient(identity_client, project_domain_name)
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 6dca3a3..a4081c9 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -12,144 +12,22 @@
# License for the specific language governing permissions and limitations
# under the License.
-import abc
import netaddr
from oslo_log import log as logging
import six
from tempest_lib import exceptions as lib_exc
from tempest import clients
+from tempest.common import cred_client
from tempest.common import cred_provider
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
-from tempest.services.identity.v2.json import identity_client as v2_identity
CONF = config.CONF
LOG = logging.getLogger(__name__)
-@six.add_metaclass(abc.ABCMeta)
-class CredsClient(object):
- """This class is a wrapper around the identity clients, to provide a
- single interface for managing credentials in both v2 and v3 cases.
- It's not bound to created credentials, only to a specific set of admin
- credentials used for generating credentials.
- """
-
- def __init__(self, identity_client):
- # The client implies version and credentials
- self.identity_client = identity_client
- self.credentials = self.identity_client.auth_provider.credentials
-
- def create_user(self, username, password, project, email):
- user = self.identity_client.create_user(
- username, password, project['id'], email)
- if 'user' in user:
- user = user['user']
- return user
-
- @abc.abstractmethod
- def create_project(self, name, description):
- pass
-
- def _check_role_exists(self, role_name):
- try:
- roles = self._list_roles()
- role = next(r for r in roles if r['name'] == role_name)
- except StopIteration:
- return None
- return role
-
- def create_user_role(self, role_name):
- if not self._check_role_exists(role_name):
- self.identity_client.create_role(role_name)
-
- def assign_user_role(self, user, project, role_name):
- role = self._check_role_exists(role_name)
- if not role:
- msg = 'No "%s" role found' % role_name
- raise lib_exc.NotFound(msg)
- try:
- self.identity_client.assign_user_role(project['id'], user['id'],
- role['id'])
- except lib_exc.Conflict:
- LOG.debug("Role %s already assigned on project %s for user %s" % (
- role['id'], project['id'], user['id']))
-
- @abc.abstractmethod
- def get_credentials(self, user, project, password):
- pass
-
- def delete_user(self, user_id):
- self.identity_client.delete_user(user_id)
-
- def _list_roles(self):
- roles = self.identity_client.list_roles()
- return roles
-
-
-class V2CredsClient(CredsClient):
-
- def create_project(self, name, description):
- tenant = self.identity_client.create_tenant(
- name=name, description=description)
- return tenant
-
- def get_credentials(self, user, project, password):
- return cred_provider.get_credentials(
- identity_version='v2',
- username=user['name'], user_id=user['id'],
- tenant_name=project['name'], tenant_id=project['id'],
- password=password)
-
- def delete_project(self, project_id):
- self.identity_client.delete_tenant(project_id)
-
-
-class V3CredsClient(CredsClient):
-
- def __init__(self, identity_client, domain_name):
- super(V3CredsClient, self).__init__(identity_client)
- try:
- # Domain names must be unique, in any case a list is returned,
- # selecting the first (and only) element
- self.creds_domain = self.identity_client.list_domains(
- params={'name': domain_name})['domains'][0]
- except lib_exc.NotFound:
- # TODO(andrea) we could probably create the domain on the fly
- msg = "Configured domain %s could not be found" % domain_name
- raise exceptions.InvalidConfiguration(msg)
-
- def create_project(self, name, description):
- project = self.identity_client.create_project(
- name=name, description=description,
- domain_id=self.creds_domain['id'])['project']
- return project
-
- def get_credentials(self, user, project, password):
- return cred_provider.get_credentials(
- identity_version='v3',
- username=user['name'], user_id=user['id'],
- project_name=project['name'], project_id=project['id'],
- password=password,
- project_domain_name=self.creds_domain['name'])
-
- def delete_project(self, project_id):
- self.identity_client.delete_project(project_id)
-
- def _list_roles(self):
- roles = self.identity_client.list_roles()['roles']
- return roles
-
-
-def get_creds_client(identity_client, project_domain_name=None):
- if isinstance(identity_client, v2_identity.IdentityClient):
- return V2CredsClient(identity_client)
- else:
- return V3CredsClient(identity_client, project_domain_name)
-
-
class IsolatedCreds(cred_provider.CredentialProvider):
def __init__(self, identity_version=None, name=None,
@@ -171,7 +49,7 @@
self.creds_domain_name = (
self.default_admin_creds.project_domain_name or
CONF.auth.default_credentials_domain_name)
- self.creds_client = get_creds_client(
+ self.creds_client = cred_client.get_creds_client(
self.identity_admin_client, self.creds_domain_name)
def _get_admin_clients(self):
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index b0afcc1..867d3f6 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -34,7 +34,7 @@
# NOTE(afazekas): UNKNOWN status possible on ERROR
# or in a very early stage.
- body = client.show_server(server_id)
+ body = client.show_server(server_id)['server']
old_status = server_status = body['status']
old_task_state = task_state = _get_task_state(body)
start_time = int(time.time())
@@ -61,7 +61,7 @@
return
time.sleep(client.build_interval)
- body = client.show_server(server_id)
+ body = client.show_server(server_id)['server']
server_status = body['status']
task_state = _get_task_state(body)
if (server_status != old_status) or (task_state != old_task_state):
@@ -102,7 +102,7 @@
start_time = int(time.time())
while True:
try:
- body = client.show_server(server_id)
+ body = client.show_server(server_id)['server']
except lib_exc.NotFound:
return
@@ -162,20 +162,13 @@
def wait_for_volume_status(client, volume_id, status):
"""Waits for a Volume to reach a given status."""
- body = client.show_volume(volume_id)
- if 'volume' in body:
- body = body['volume']
+ body = client.show_volume(volume_id)['volume']
volume_status = body['status']
start = int(time.time())
while volume_status != status:
time.sleep(client.build_interval)
- body = client.show_volume(volume_id)
- # TODO(jswarren) always extract 'volume' value
- # once the compute clients also return the full
- # response.
- if 'volume' in body:
- body = body['volume']
+ body = client.show_volume(volume_id)['volume']
volume_status = body['status']
if volume_status == 'error':
raise exceptions.VolumeBuildErrorException(volume_id=volume_id)
@@ -190,6 +183,27 @@
raise exceptions.TimeoutException(message)
+def wait_for_snapshot_status(client, snapshot_id, status):
+ """Waits for a Snapshot to reach a given status."""
+ body = client.show_snapshot(snapshot_id)['snapshot']
+ snapshot_status = body['status']
+ start = int(time.time())
+
+ while snapshot_status != status:
+ time.sleep(client.build_interval)
+ body = client.show_snapshot(snapshot_id)['snapshot']
+ snapshot_status = body['status']
+ if snapshot_status == 'error':
+ raise exceptions.SnapshotBuildErrorException(
+ snapshot_id=snapshot_id)
+ if int(time.time()) - start >= client.build_timeout:
+ message = ('Snapshot %s failed to reach %s status (current %s) '
+ 'within the required time (%s s).' %
+ (snapshot_id, status, snapshot_status,
+ client.build_timeout))
+ raise exceptions.TimeoutException(message)
+
+
def wait_for_bm_node_status(client, node_id, attr, status):
"""Waits for a baremetal node attribute to reach given status.
diff --git a/tempest/config.py b/tempest/config.py
index 5721c27..3d3ddff 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -117,9 +117,7 @@
choices=['public', 'admin', 'internal',
'publicURL', 'adminURL', 'internalURL'],
help="The admin endpoint type to use for OpenStack Identity "
- "(Keystone) API v2",
- deprecated_opts=[cfg.DeprecatedOpt('endpoint_type',
- group='identity')]),
+ "(Keystone) API v2"),
cfg.StrOpt('v2_public_endpoint_type',
default='publicURL',
choices=['public', 'admin', 'internal',
@@ -133,9 +131,7 @@
choices=['public', 'admin', 'internal',
'publicURL', 'adminURL', 'internalURL'],
help="The endpoint type to use for OpenStack Identity "
- "(Keystone) API v3",
- deprecated_opts=[cfg.DeprecatedOpt('endpoint_type',
- group='identity')]),
+ "(Keystone) API v3"),
cfg.StrOpt('username',
help="Username to use for Nova API requests."),
cfg.StrOpt('tenant_name',
@@ -192,6 +188,12 @@
cfg.BoolOpt('api_v3',
default=True,
help='Is the v3 identity API enabled'),
+ cfg.ListOpt('api_extensions',
+ default=['all'],
+ help="A list of enabled identity extensions with a special "
+ "entry all which indicates every extension is enabled. "
+ "Empty list indicates all extensions are disabled. "
+ "To get the list of extensions run: 'keystone discover'")
]
compute_group = cfg.OptGroup(name='compute',
@@ -611,6 +613,12 @@
' validation resources to enable remote access',
deprecated_opts=[cfg.DeprecatedOpt('run_ssh',
group='compute')]),
+ cfg.BoolOpt('security_group',
+ default=True,
+ help='Enable/disable security groups.'),
+ cfg.BoolOpt('security_group_rules',
+ default=True,
+ help='Enable/disable security group rules.'),
cfg.StrOpt('connect_method',
default='floating',
choices=['fixed', 'floating'],
@@ -1040,7 +1048,7 @@
# TODO(yfried): add support for dhcpcd
cfg.StrOpt('dhcp_client',
default='udhcpc',
- choices=["udhcpc", "dhclient"],
+ choices=["udhcpc", "dhclient", ""],
help='DHCP client used by images to renew DCHP lease. '
'If left empty, update operation will be skipped. '
'Supported clients: "udhcpc", "dhclient"')
@@ -1141,7 +1149,7 @@
title='Baremetal provisioning service options',
help='When enabling baremetal tests, Nova '
'must be configured to use the Ironic '
- 'driver. The following paremeters for the '
+ 'driver. The following parameters for the '
'[compute] section must be disabled: '
'console_output, interface_attach, '
'live_migration, pause, rescue, resize '
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 15482ab..b3d60f6 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -64,7 +64,7 @@
class InvalidIdentityVersion(TempestException):
- message = "Invalid version %(identity_version) of the identity service"
+ message = "Invalid version %(identity_version)s of the identity service"
class TimeoutException(TempestException):
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 4f113d3..9ff434d 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -178,8 +178,9 @@
LOG.debug("Creating a server (name: %s, image: %s, flavor: %s)",
name, image, flavor)
- server = self.servers_client.create_server(name, image, flavor,
- **create_kwargs)
+ server = self.servers_client.create_server(name=name, imageRef=image,
+ flavorRef=flavor,
+ **create_kwargs)['server']
if wait_on_delete:
self.addCleanup(waiters.wait_for_server_termination,
self.servers_client,
@@ -197,7 +198,7 @@
# The instance retrieved on creation is missing network
# details, necessitating retrieval after it becomes active to
# ensure correct details.
- server = self.servers_client.show_server(server['id'])
+ server = self.servers_client.show_server(server['id'])['server']
self.assertEqual(server['name'], name)
return server
@@ -400,7 +401,7 @@
servers = servers['servers']
for server in servers:
console_output = self.servers_client.get_console_output(
- server['id'], length=None).data
+ server['id'], length=None)['output']
LOG.debug('Console output for %s\nbody=\n%s',
server['id'], console_output)
@@ -450,7 +451,7 @@
def nova_volume_attach(self):
volume = self.servers_client.attach_volume(
self.server['id'], volumeId=self.volume['id'], device='/dev/%s'
- % CONF.compute.volume_device_name)
+ % CONF.compute.volume_device_name)['volumeAttachment']
self.assertEqual(self.volume['id'], volume['id'])
self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
# Refresh the volume after the attachment
@@ -1073,7 +1074,10 @@
def create_server(self, name=None, image=None, flavor=None,
wait_on_boot=True, wait_on_delete=True,
- create_kwargs=None):
+ network_client=None, create_kwargs=None):
+ if network_client is None:
+ network_client = self.network_client
+
vnic_type = CONF.network.port_vnic_type
# If vnic_type is configured create port for
@@ -1084,19 +1088,16 @@
create_port_body = {'binding:vnic_type': vnic_type,
'namestart': 'port-smoke'}
if create_kwargs:
- net_client = create_kwargs.get("network_client",
- self.network_client)
-
# Convert security group names to security group ids
# to pass to create_port
if create_kwargs.get('security_groups'):
- security_groups = net_client.list_security_groups().get(
- 'security_groups')
+ security_groups = network_client.list_security_groups(
+ ).get('security_groups')
sec_dict = dict([(s['name'], s['id'])
for s in security_groups])
- sec_groups_names = [s['name'] for s in create_kwargs[
- 'security_groups']]
+ sec_groups_names = [s['name'] for s in create_kwargs.get(
+ 'security_groups')]
security_groups_ids = [sec_dict[s]
for s in sec_groups_names]
@@ -1104,15 +1105,14 @@
create_port_body[
'security_groups'] = security_groups_ids
networks = create_kwargs.get('networks')
- else:
- net_client = self.network_client
+
# If there are no networks passed to us we look up
# for the tenant's private networks and create a port
# if there is only one private network. The same behaviour
# as we would expect when passing the call to the clients
# with no networks
if not networks:
- networks = net_client.list_networks(filters={
+ networks = network_client.list_networks(filters={
'router:external': False})
self.assertEqual(1, len(networks),
"There is more than one"
@@ -1120,7 +1120,7 @@
for net in networks:
net_id = net['uuid']
port = self._create_port(network_id=net_id,
- client=net_client,
+ client=network_client,
**create_port_body)
ports.append({'port': port.id})
if ports:
@@ -1278,7 +1278,8 @@
waiters.wait_for_server_status(self.servers_client,
self.instance['id'], 'ACTIVE')
self.node = self.get_node(instance_id=self.instance['id'])
- self.instance = self.servers_client.show_server(self.instance['id'])
+ self.instance = (self.servers_client.show_server(self.instance['id'])
+ ['server'])
def terminate_instance(self):
self.servers_client.delete_server(self.instance['id'])
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index 2ad5d2d..63dd4f0 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -99,9 +99,9 @@
create_kwargs = fixed_network.set_networks_kwarg(network,
create_kwargs)
self.servers_client.create_server(
- name,
- self.image,
- flavor_id,
+ name=name,
+ imageRef=self.image,
+ flavorRef=flavor_id,
**create_kwargs)
# needed because of bug 1199788
params = {'name': name}
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 402bc68..eac8311 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -62,7 +62,8 @@
self.assertIn(self.server['id'], [x['id'] for x in servers])
def nova_show(self):
- got_server = self.servers_client.show_server(self.server['id'])
+ got_server = (self.servers_client.show_server(self.server['id'])
+ ['server'])
excluded_keys = ['OS-EXT-AZ:availability_zone']
# Exclude these keys because of LP:#1486475
excluded_keys.extend(['OS-EXT-STS:power_state', 'updated'])
@@ -98,7 +99,8 @@
self.server['id'], secgroup['name'])
def wait_for_secgroup_add():
- body = self.servers_client.show_server(self.server['id'])
+ body = (self.servers_client.show_server(self.server['id'])
+ ['server'])
return {'name': secgroup['name']} in body['security_groups']
if not test.call_until_true(wait_for_secgroup_add,
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 1db1ac2..297076c 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -244,11 +244,12 @@
{'uuid': tenant.network.id},
],
'key_name': tenant.keypair['name'],
- 'security_groups': security_groups_names,
- 'tenant_id': tenant.creds.tenant_id,
- 'network_client': tenant.manager.network_client
+ 'security_groups': security_groups_names
}
- server = self.create_server(name=name, create_kwargs=create_kwargs)
+ server = self.create_server(
+ name=name,
+ network_client=tenant.manager.network_client,
+ create_kwargs=create_kwargs)
self.assertEqual(
sorted([s['name'] for s in security_groups]),
sorted([s['name'] for s in server['security_groups']]))
@@ -553,3 +554,44 @@
username=ssh_login,
private_key=private_key,
should_connect=True)
+
+ @test.requires_ext(service='network', extension='port-security')
+ @test.idempotent_id('7c811dcc-263b-49a3-92d2-1b4d8405f50c')
+ @test.services('compute', 'network')
+ def test_port_security_disable_security_group(self):
+ """
+ This test verifies port_security_enabled=False disables
+ the default security group rules.
+ """
+ new_tenant = self.primary_tenant
+
+ # Create server
+ name = 'server-{tenant}-gen-1'.format(
+ tenant=new_tenant.creds.tenant_name
+ )
+ name = data_utils.rand_name(name)
+ server = self._create_server(name, new_tenant)
+
+ access_point_ssh = self._connect_to_access_point(new_tenant)
+ server_id = server['id']
+ port_id = self._list_ports(device_id=server_id)[0]['id']
+
+ # Flip the port's port security and check connectivity
+ try:
+ self.network_client.update_port(port_id,
+ port_security_enabled=True,
+ security_groups=[])
+ self._check_connectivity(access_point=access_point_ssh,
+ ip=self._get_server_ip(server),
+ should_succeed=False)
+
+ self.network_client.update_port(port_id,
+ port_security_enabled=False,
+ security_groups=[])
+ self._check_connectivity(
+ access_point=access_point_ssh,
+ ip=self._get_server_ip(server))
+ except Exception:
+ for tenant in self.tenants.values():
+ self._log_console_output(servers=tenant.servers)
+ raise
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index 99eecae..c83dbb1 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -81,19 +81,22 @@
self.servers_client.suspend_server(instance_id)
waiters.wait_for_server_status(self.servers_client, instance_id,
'SUSPENDED')
- fetched_instance = self.servers_client.show_server(instance_id)
+ fetched_instance = (self.servers_client.show_server(instance_id)
+ ['server'])
LOG.debug("Resuming instance %s. Current status: %s",
instance_id, fetched_instance['status'])
self.servers_client.resume_server(instance_id)
waiters.wait_for_server_status(self.servers_client, instance_id,
'ACTIVE')
- fetched_instance = self.servers_client.show_server(instance_id)
+ fetched_instance = (self.servers_client.show_server(instance_id)
+ ['server'])
LOG.debug("Suspending instance %s. Current status: %s",
instance_id, fetched_instance['status'])
self.servers_client.suspend_server(instance_id)
waiters.wait_for_server_status(self.servers_client, instance_id,
'SUSPENDED')
- fetched_instance = self.servers_client.show_server(instance_id)
+ fetched_instance = (self.servers_client.show_server(instance_id)
+ ['server'])
LOG.debug("Resuming instance %s. Current status: %s",
instance_id, fetched_instance['status'])
self.servers_client.resume_server(instance_id)
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 4896447..bf4b8e7 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -64,22 +64,29 @@
waiters.wait_for_server_status(self.servers_client, server['id'],
'ACTIVE')
- @test.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
- @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
- 'Shelve is not available.')
- @test.services('compute', 'network', 'image')
- def test_shelve_instance(self):
+ def _create_server_then_shelve_and_unshelve(self, boot_from_volume=False):
self.keypair = self.create_keypair()
self.security_group = self._create_security_group()
security_groups = [{'name': self.security_group['name']}]
-
create_kwargs = {
'key_name': self.keypair['name'],
'security_groups': security_groups
}
- server = self.create_server(image=CONF.compute.image_ref,
- create_kwargs=create_kwargs)
+
+ if boot_from_volume:
+ volume = self.create_volume(size=CONF.volume.volume_size,
+ imageRef=CONF.compute.image_ref)
+ bd_map = [{
+ 'device_name': 'vda',
+ 'volume_id': volume['id'],
+ 'delete_on_termination': '0'}]
+
+ create_kwargs['block_device_mapping'] = bd_map
+ server = self.create_server(create_kwargs=create_kwargs)
+ else:
+ server = self.create_server(image=CONF.compute.image_ref,
+ create_kwargs=create_kwargs)
if CONF.compute.use_floatingip_for_ssh:
floating_ip = (self.floating_ips_client.create_floating_ip()
@@ -101,3 +108,17 @@
self._check_timestamp(floating_ip['ip'])
else:
self._check_timestamp(server)
+
+ @test.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
+ @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
+ 'Shelve is not available.')
+ @test.services('compute', 'network', 'image')
+ def test_shelve_instance(self):
+ self._create_server_then_shelve_and_unshelve()
+
+ @test.idempotent_id('c1b6318c-b9da-490b-9c67-9339b627271f')
+ @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
+ 'Shelve is not available.')
+ @test.services('compute', 'volume', 'network', 'image')
+ def test_shelve_volume_backed_instance(self):
+ self._create_server_then_shelve_and_unshelve(boot_from_volume=True)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 474c939..91e4657 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -106,7 +106,7 @@
def _attach_volume(self, server, volume):
attached_volume = self.servers_client.attach_volume(
server['id'], volumeId=volume['id'], device='/dev/%s'
- % CONF.compute.volume_device_name)
+ % CONF.compute.volume_device_name)['volumeAttachment']
self.assertEqual(volume['id'], attached_volume['id'])
self._wait_for_volume_status(attached_volume, 'in-use')
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index 0a7d492..2841060 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -91,8 +91,8 @@
def test_create_server_metadata(self):
name = rand_name('instance')
self.servers_client.create_server(name=name,
- flavor_ref=self.flavor_ref,
- image_ref=self.image_ref)
+ flavorRef=self.flavor_ref,
+ imageRef=self.image_ref)
"""
validchars = "-_.{ascii}{digit}".format(ascii=string.ascii_letters,
digit=string.digits)
diff --git a/tempest/services/compute/json/interfaces_client.py b/tempest/services/compute/json/interfaces_client.py
index 2e66082..fe076d8 100644
--- a/tempest/services/compute/json/interfaces_client.py
+++ b/tempest/services/compute/json/interfaces_client.py
@@ -16,7 +16,6 @@
from oslo_serialization import jsonutils as json
from tempest.api_schema.response.compute.v2_1 import interfaces as schema
-from tempest.api_schema.response.compute.v2_1 import servers as servers_schema
from tempest.common import service_client
@@ -49,21 +48,3 @@
port_id))
self.validate_response(schema.delete_interface, resp, body)
return service_client.ResponseBody(resp, body)
-
- def add_fixed_ip(self, server_id, **kwargs):
- """Add a fixed IP to input server instance."""
- post_body = json.dumps({'addFixedIp': kwargs})
- resp, body = self.post('servers/%s/action' % server_id,
- post_body)
- self.validate_response(servers_schema.server_actions_common_schema,
- resp, body)
- return service_client.ResponseBody(resp, body)
-
- def remove_fixed_ip(self, server_id, **kwargs):
- """Remove input fixed IP from input server instance."""
- post_body = json.dumps({'removeFixedIp': kwargs})
- resp, body = self.post('servers/%s/action' % server_id,
- post_body)
- self.validate_response(servers_schema.server_actions_common_schema,
- resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/security_group_rules_client.py b/tempest/services/compute/json/security_group_rules_client.py
index c1c6b1a..9626f60 100644
--- a/tempest/services/compute/json/security_group_rules_client.py
+++ b/tempest/services/compute/json/security_group_rules_client.py
@@ -14,7 +14,6 @@
# under the License.
from oslo_serialization import jsonutils as json
-from tempest_lib import exceptions as lib_exc
from tempest.api_schema.response.compute.v2_1 import security_groups as schema
from tempest.common import service_client
@@ -46,13 +45,3 @@
group_rule_id)
self.validate_response(schema.delete_security_group_rule, resp, body)
return service_client.ResponseBody(resp, body)
-
- def list_security_group_rules(self, security_group_id):
- """List all rules for a security group."""
- resp, body = self.get('os-security-groups')
- body = json.loads(body)
- self.validate_response(schema.list_security_groups, resp, body)
- for sg in body['security_groups']:
- if sg['id'] == security_group_id:
- return service_client.ResponseBody(resp, sg)
- raise lib_exc.NotFound('No such Security Group')
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 5603fed..1d2c7b2 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -14,6 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
+
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
@@ -29,59 +31,28 @@
auth_provider, service, region, **kwargs)
self.enable_instance_password = enable_instance_password
- def create_server(self, name, image_ref, flavor_ref, **kwargs):
+ def create_server(self, **kwargs):
"""
Creates an instance of a server.
- name (Required): The name of the server.
- image_ref (Required): Reference to the image used to build the server.
- flavor_ref (Required): The flavor used to build the server.
- Following optional keyword arguments are accepted:
- adminPass: Sets the initial root password.
- key_name: Key name of keypair that was created earlier.
- meta: A dictionary of values to be used as metadata.
- personality: A list of dictionaries for files to be injected into
- the server.
- security_groups: A list of security group dicts.
- networks: A list of network dicts with UUID and fixed_ip.
- user_data: User data for instance.
- availability_zone: Availability zone in which to launch instance.
- accessIPv4: The IPv4 access address for the server.
- accessIPv6: The IPv6 access address for the server.
- min_count: Count of minimum number of instances to launch.
- max_count: Count of maximum number of instances to launch.
- disk_config: Determines if user or admin controls disk configuration.
- return_reservation_id: Enable/Disable the return of reservation id
- block_device_mapping: Block device mapping for the server.
- block_device_mapping_v2: Block device mapping V2 for the server.
+ Most parameters except the following are passed to the API without
+ any changes.
+ :param disk_config: The name is changed to OS-DCF:diskConfig
+ :param scheduler_hints: The name is changed to os:scheduler_hints and
+ the parameter is set in the same level as the parameter 'server'.
"""
- post_body = {
- 'name': name,
- 'imageRef': image_ref,
- 'flavorRef': flavor_ref
- }
+ body = copy.deepcopy(kwargs)
+ if body.get('disk_config'):
+ body['OS-DCF:diskConfig'] = body.pop('disk_config')
- for option in ['personality', 'adminPass', 'key_name',
- 'security_groups', 'networks', 'user_data',
- 'availability_zone', 'accessIPv4', 'accessIPv6',
- 'min_count', 'max_count', ('metadata', 'meta'),
- ('OS-DCF:diskConfig', 'disk_config'),
- 'return_reservation_id', 'block_device_mapping',
- 'block_device_mapping_v2']:
- if isinstance(option, tuple):
- post_param = option[0]
- key = option[1]
- else:
- post_param = option
- key = option
- value = kwargs.get(key)
- if value is not None:
- post_body[post_param] = value
+ hints = None
+ if body.get('scheduler_hints'):
+ hints = {'os:scheduler_hints': body.pop('scheduler_hints')}
- post_body = {'server': post_body}
+ post_body = {'server': body}
- if 'sched_hints' in kwargs:
- hints = {'os:scheduler_hints': kwargs.get('sched_hints')}
+ if hints:
post_body = dict(post_body.items() + hints.items())
+
post_body = json.dumps(post_body)
resp, body = self.post('servers', post_body)
@@ -95,7 +66,7 @@
else:
create_schema = schema.create_server
self.validate_response(create_schema, resp, body)
- return service_client.ResponseBody(resp, body['server'])
+ return service_client.ResponseBody(resp, body)
def update_server(self, server_id, **kwargs):
"""Updates the properties of an existing server.
@@ -110,14 +81,14 @@
resp, body = self.put("servers/%s" % server_id, post_body)
body = json.loads(body)
self.validate_response(schema.update_server, resp, body)
- return service_client.ResponseBody(resp, body['server'])
+ return service_client.ResponseBody(resp, body)
def show_server(self, server_id):
"""Returns the details of an existing server."""
resp, body = self.get("servers/%s" % server_id)
body = json.loads(body)
self.validate_response(schema.get_server, resp, body)
- return service_client.ResponseBody(resp, body['server'])
+ return service_client.ResponseBody(resp, body)
def delete_server(self, server_id):
"""Deletes the given server."""
@@ -147,7 +118,7 @@
resp, body = self.get("servers/%s/ips" % server_id)
body = json.loads(body)
self.validate_response(schema.list_addresses, resp, body)
- return service_client.ResponseBody(resp, body['addresses'])
+ return service_client.ResponseBody(resp, body)
def list_addresses_by_network(self, server_id, network_id):
"""Lists all addresses of a specific network type for a server."""
@@ -157,30 +128,27 @@
self.validate_response(schema.list_addresses_by_network, resp, body)
return service_client.ResponseBody(resp, body)
- def action(self, server_id, action_name, response_key,
+ def action(self, server_id, action_name,
schema=schema.server_actions_common_schema,
- response_class=service_client.ResponseBody, **kwargs):
+ **kwargs):
post_body = json.dumps({action_name: kwargs})
resp, body = self.post('servers/%s/action' % server_id,
post_body)
- if response_key is not None:
+ if body:
body = json.loads(body)
- self.validate_response(schema, resp, body)
- body = body[response_key]
- else:
- self.validate_response(schema, resp, body)
- return response_class(resp, body)
+ self.validate_response(schema, resp, body)
+ return service_client.ResponseBody(resp, body)
def create_backup(self, server_id, backup_type, rotation, name):
"""Backup a server instance."""
- return self.action(server_id, "createBackup", None,
+ return self.action(server_id, "createBackup",
backup_type=backup_type,
rotation=rotation,
name=name)
def change_password(self, server_id, adminPass):
"""Changes the root password for the server."""
- return self.action(server_id, 'changePassword', None,
+ return self.action(server_id, 'changePassword',
adminPass=adminPass)
def get_password(self, server_id):
@@ -204,7 +172,7 @@
def reboot_server(self, server_id, reboot_type):
"""Reboots a server."""
- return self.action(server_id, 'reboot', None, type=reboot_type)
+ return self.action(server_id, 'reboot', type=reboot_type)
def rebuild_server(self, server_id, image_ref, **kwargs):
"""Rebuilds a server with a new image.
@@ -219,7 +187,7 @@
rebuild_schema = schema.rebuild_server_with_admin_pass
else:
rebuild_schema = schema.rebuild_server
- return self.action(server_id, 'rebuild', 'server',
+ return self.action(server_id, 'rebuild',
rebuild_schema, **kwargs)
def resize_server(self, server_id, flavor_ref, **kwargs):
@@ -231,23 +199,23 @@
kwargs['flavorRef'] = flavor_ref
if 'disk_config' in kwargs:
kwargs['OS-DCF:diskConfig'] = kwargs.pop('disk_config')
- return self.action(server_id, 'resize', None, **kwargs)
+ return self.action(server_id, 'resize', **kwargs)
def confirm_resize_server(self, server_id, **kwargs):
"""Confirms the flavor change for a server."""
return self.action(server_id, 'confirmResize',
- None, schema.server_actions_confirm_resize,
+ schema.server_actions_confirm_resize,
**kwargs)
def revert_resize_server(self, server_id, **kwargs):
"""Reverts a server back to its original flavor."""
- return self.action(server_id, 'revertResize', None, **kwargs)
+ return self.action(server_id, 'revertResize', **kwargs)
def list_server_metadata(self, server_id):
resp, body = self.get("servers/%s/metadata" % server_id)
body = json.loads(body)
self.validate_response(schema.list_server_metadata, resp, body)
- return service_client.ResponseBody(resp, body['metadata'])
+ return service_client.ResponseBody(resp, body)
def set_server_metadata(self, server_id, meta, no_metadata_field=False):
if no_metadata_field:
@@ -258,7 +226,7 @@
post_body)
body = json.loads(body)
self.validate_response(schema.set_server_metadata, resp, body)
- return service_client.ResponseBody(resp, body['metadata'])
+ return service_client.ResponseBody(resp, body)
def update_server_metadata(self, server_id, meta):
post_body = json.dumps({'metadata': meta})
@@ -267,14 +235,14 @@
body = json.loads(body)
self.validate_response(schema.update_server_metadata,
resp, body)
- return service_client.ResponseBody(resp, body['metadata'])
+ return service_client.ResponseBody(resp, body)
def get_server_metadata_item(self, server_id, key):
resp, body = self.get("servers/%s/metadata/%s" % (server_id, key))
body = json.loads(body)
self.validate_response(schema.set_get_server_metadata_item,
resp, body)
- return service_client.ResponseBody(resp, body['meta'])
+ return service_client.ResponseBody(resp, body)
def set_server_metadata_item(self, server_id, key, meta):
post_body = json.dumps({'meta': meta})
@@ -283,7 +251,7 @@
body = json.loads(body)
self.validate_response(schema.set_get_server_metadata_item,
resp, body)
- return service_client.ResponseBody(resp, body['meta'])
+ return service_client.ResponseBody(resp, body)
def delete_server_metadata_item(self, server_id, key):
resp, body = self.delete("servers/%s/metadata/%s" %
@@ -293,10 +261,10 @@
return service_client.ResponseBody(resp, body)
def stop_server(self, server_id, **kwargs):
- return self.action(server_id, 'os-stop', None, **kwargs)
+ return self.action(server_id, 'os-stop', **kwargs)
def start_server(self, server_id, **kwargs):
- return self.action(server_id, 'os-start', None, **kwargs)
+ return self.action(server_id, 'os-start', **kwargs)
def attach_volume(self, server_id, **kwargs):
"""Attaches a volume to a server instance."""
@@ -305,7 +273,7 @@
post_body)
body = json.loads(body)
self.validate_response(schema.attach_volume, resp, body)
- return service_client.ResponseBody(resp, body['volumeAttachment'])
+ return service_client.ResponseBody(resp, body)
def detach_volume(self, server_id, volume_id):
"""Detaches a volume from a server instance."""
@@ -320,7 +288,7 @@
server_id, attach_id))
body = json.loads(body)
self.validate_response(schema.get_volume_attachment, resp, body)
- return service_client.ResponseBody(resp, body['volumeAttachment'])
+ return service_client.ResponseBody(resp, body)
def list_volume_attachments(self, server_id):
"""Returns the list of volume attachments for a given instance."""
@@ -328,15 +296,15 @@
server_id))
body = json.loads(body)
self.validate_response(schema.list_volume_attachments, resp, body)
- return service_client.ResponseBodyList(resp, body['volumeAttachments'])
+ return service_client.ResponseBody(resp, body)
def add_security_group(self, server_id, name):
"""Adds a security group to the server."""
- return self.action(server_id, 'addSecurityGroup', None, name=name)
+ return self.action(server_id, 'addSecurityGroup', name=name)
def remove_security_group(self, server_id, name):
"""Removes a security group from the server."""
- return self.action(server_id, 'removeSecurityGroup', None, name=name)
+ return self.action(server_id, 'removeSecurityGroup', name=name)
def live_migrate_server(self, server_id, **kwargs):
"""This should be called with administrator privileges ."""
@@ -350,53 +318,52 @@
def migrate_server(self, server_id, **kwargs):
"""Migrates a server to a new host."""
- return self.action(server_id, 'migrate', None, **kwargs)
+ return self.action(server_id, 'migrate', **kwargs)
def lock_server(self, server_id, **kwargs):
"""Locks the given server."""
- return self.action(server_id, 'lock', None, **kwargs)
+ return self.action(server_id, 'lock', **kwargs)
def unlock_server(self, server_id, **kwargs):
"""UNlocks the given server."""
- return self.action(server_id, 'unlock', None, **kwargs)
+ return self.action(server_id, 'unlock', **kwargs)
def suspend_server(self, server_id, **kwargs):
"""Suspends the provided server."""
- return self.action(server_id, 'suspend', None, **kwargs)
+ return self.action(server_id, 'suspend', **kwargs)
def resume_server(self, server_id, **kwargs):
"""Un-suspends the provided server."""
- return self.action(server_id, 'resume', None, **kwargs)
+ return self.action(server_id, 'resume', **kwargs)
def pause_server(self, server_id, **kwargs):
"""Pauses the provided server."""
- return self.action(server_id, 'pause', None, **kwargs)
+ return self.action(server_id, 'pause', **kwargs)
def unpause_server(self, server_id, **kwargs):
"""Un-pauses the provided server."""
- return self.action(server_id, 'unpause', None, **kwargs)
+ return self.action(server_id, 'unpause', **kwargs)
def reset_state(self, server_id, state='error'):
"""Resets the state of a server to active/error."""
- return self.action(server_id, 'os-resetState', None, state=state)
+ return self.action(server_id, 'os-resetState', state=state)
def shelve_server(self, server_id, **kwargs):
"""Shelves the provided server."""
- return self.action(server_id, 'shelve', None, **kwargs)
+ return self.action(server_id, 'shelve', **kwargs)
def unshelve_server(self, server_id, **kwargs):
"""Un-shelves the provided server."""
- return self.action(server_id, 'unshelve', None, **kwargs)
+ return self.action(server_id, 'unshelve', **kwargs)
def shelve_offload_server(self, server_id, **kwargs):
"""Shelve-offload the provided server."""
- return self.action(server_id, 'shelveOffload', None, **kwargs)
+ return self.action(server_id, 'shelveOffload', **kwargs)
def get_console_output(self, server_id, length):
kwargs = {'length': length} if length else {}
- return self.action(server_id, 'os-getConsoleOutput', 'output',
+ return self.action(server_id, 'os-getConsoleOutput',
schema.get_console_output,
- response_class=service_client.ResponseBodyData,
**kwargs)
def list_virtual_interfaces(self, server_id):
@@ -411,14 +378,13 @@
def rescue_server(self, server_id, **kwargs):
"""Rescue the provided server."""
- return self.action(server_id, 'rescue', 'adminPass',
+ return self.action(server_id, 'rescue',
schema.rescue_server,
- response_class=service_client.ResponseBodyData,
**kwargs)
def unrescue_server(self, server_id):
"""Unrescue the provided server."""
- return self.action(server_id, 'unrescue', None)
+ return self.action(server_id, 'unrescue')
def get_server_diagnostics(self, server_id):
"""Get the usage data for a server."""
@@ -431,7 +397,7 @@
server_id)
body = json.loads(body)
self.validate_response(schema.list_instance_actions, resp, body)
- return service_client.ResponseBodyList(resp, body['instanceActions'])
+ return service_client.ResponseBody(resp, body)
def get_instance_action(self, server_id, request_id):
"""Returns the action details of the provided server."""
@@ -439,26 +405,34 @@
(server_id, request_id))
body = json.loads(body)
self.validate_response(schema.get_instance_action, resp, body)
- return service_client.ResponseBody(resp, body['instanceAction'])
+ return service_client.ResponseBody(resp, body)
def force_delete_server(self, server_id, **kwargs):
"""Force delete a server."""
- return self.action(server_id, 'forceDelete', None, **kwargs)
+ return self.action(server_id, 'forceDelete', **kwargs)
def restore_soft_deleted_server(self, server_id, **kwargs):
"""Restore a soft-deleted server."""
- return self.action(server_id, 'restore', None, **kwargs)
+ return self.action(server_id, 'restore', **kwargs)
def reset_network(self, server_id, **kwargs):
"""Resets the Network of a server"""
- return self.action(server_id, 'resetNetwork', None, **kwargs)
+ return self.action(server_id, 'resetNetwork', **kwargs)
def inject_network_info(self, server_id, **kwargs):
"""Inject the Network Info into server"""
- return self.action(server_id, 'injectNetworkInfo', None, **kwargs)
+ return self.action(server_id, 'injectNetworkInfo', **kwargs)
def get_vnc_console(self, server_id, console_type):
"""Get URL of VNC console."""
return self.action(server_id, "os-getVNCConsole",
- "console", schema.get_vnc_console,
+ schema.get_vnc_console,
type=console_type)
+
+ def add_fixed_ip(self, server_id, **kwargs):
+ """Add a fixed IP to input server instance."""
+ return self.action(server_id, 'addFixedIp', **kwargs)
+
+ def remove_fixed_ip(self, server_id, **kwargs):
+ """Remove input fixed IP from input server instance."""
+ return self.action(server_id, 'removeFixedIp', **kwargs)
diff --git a/tempest/services/compute/json/snapshots_extensions_client.py b/tempest/services/compute/json/snapshots_extensions_client.py
new file mode 100644
index 0000000..6902a39
--- /dev/null
+++ b/tempest/services/compute/json/snapshots_extensions_client.py
@@ -0,0 +1,71 @@
+# Copyright 2015 Fujitsu(fnst) Corporation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+from tempest_lib import exceptions as lib_exc
+
+from tempest.api_schema.response.compute.v2_1 import snapshots as schema
+from tempest.common import service_client
+
+
+class SnapshotsExtensionsClient(service_client.ServiceClient):
+
+ def create_snapshot(self, volume_id, **kwargs):
+ post_body = {
+ 'volume_id': volume_id
+ }
+ post_body.update(kwargs)
+ post_body = json.dumps({'snapshot': post_body})
+ resp, body = self.post('os-snapshots', post_body)
+ body = json.loads(body)
+ self.validate_response(schema.create_get_snapshot, resp, body)
+ return service_client.ResponseBody(resp, body)
+
+ def show_snapshot(self, snapshot_id):
+ url = "os-snapshots/%s" % snapshot_id
+ resp, body = self.get(url)
+ body = json.loads(body)
+ self.validate_response(schema.create_get_snapshot, resp, body)
+ return service_client.ResponseBody(resp, body)
+
+ def list_snapshots(self, detail=False, params=None):
+ url = 'os-snapshots'
+
+ if detail:
+ url += '/detail'
+ if params:
+ url += '?%s' % urllib.urlencode(params)
+ resp, body = self.get(url)
+ body = json.loads(body)
+ self.validate_response(schema.list_snapshots, resp, body)
+ return service_client.ResponseBody(resp, body)
+
+ def delete_snapshot(self, snapshot_id):
+ resp, body = self.delete("os-snapshots/%s" % snapshot_id)
+ self.validate_response(schema.delete_snapshot, resp, body)
+ return service_client.ResponseBody(resp, body)
+
+ def is_resource_deleted(self, id):
+ try:
+ self.show_snapshot(id)
+ except lib_exc.NotFound:
+ return True
+ return False
+
+ @property
+ def resource_type(self):
+ """Returns the primary type of resource this client works with."""
+ return 'snapshot'
diff --git a/tempest/services/compute/json/versions_client.py b/tempest/services/compute/json/versions_client.py
index cbad02c..48c0e8d 100644
--- a/tempest/services/compute/json/versions_client.py
+++ b/tempest/services/compute/json/versions_client.py
@@ -21,7 +21,7 @@
class VersionsClient(service_client.ServiceClient):
- def list_versions(self):
+ def _get_base_version_url(self):
# NOTE: The URL which is gotten from keystone's catalog contains
# API version and project-id like "v2/{project-id}", but we need
# to access the URL which doesn't contain them for getting API
@@ -29,9 +29,27 @@
# get().
endpoint = self.base_url
url = urllib.parse.urlparse(endpoint)
- version_url = '%s://%s/' % (url.scheme, url.netloc)
+ return '%s://%s/' % (url.scheme, url.netloc)
+ def list_versions(self):
+ version_url = self._get_base_version_url()
resp, body = self.raw_request(version_url, 'GET')
body = json.loads(body)
self.validate_response(schema.list_versions, resp, body)
return service_client.ResponseBody(resp, body)
+
+ def get_version_by_url(self, version_url):
+ """Get the version document by url.
+
+ This gets the version document for a url, useful in testing
+ the contents of things like /v2/ or /v2.1/ in Nova. That
+ controller needs authenticated access, so we have to get
+ ourselves a token before making the request.
+
+ """
+ # we need a token for this request
+ resp, body = self.raw_request(version_url, 'GET',
+ {'X-Auth-Token': self.token})
+ body = json.loads(body)
+ self.validate_response(schema.get_one_version, resp, body)
+ return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/volumes_extensions_client.py b/tempest/services/compute/json/volumes_extensions_client.py
index c86aaff..db92351 100644
--- a/tempest/services/compute/json/volumes_extensions_client.py
+++ b/tempest/services/compute/json/volumes_extensions_client.py
@@ -35,7 +35,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.list_volumes, resp, body)
- return service_client.ResponseBodyList(resp, body['volumes'])
+ return service_client.ResponseBody(resp, body)
def show_volume(self, volume_id):
"""Returns the details of a single volume."""
@@ -43,7 +43,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.create_get_volume, resp, body)
- return service_client.ResponseBody(resp, body['volume'])
+ return service_client.ResponseBody(resp, body)
def create_volume(self, **kwargs):
"""
@@ -57,7 +57,7 @@
resp, body = self.post('os-volumes', post_body)
body = json.loads(body)
self.validate_response(schema.create_get_volume, resp, body)
- return service_client.ResponseBody(resp, body['volume'])
+ return service_client.ResponseBody(resp, body)
def delete_volume(self, volume_id):
"""Deletes the Specified Volume."""
diff --git a/tempest/services/database/json/flavors_client.py b/tempest/services/database/json/flavors_client.py
index 4fe5a46..88feb17 100644
--- a/tempest/services/database/json/flavors_client.py
+++ b/tempest/services/database/json/flavors_client.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from oslo_serialization import jsonutils as json
import urllib
from tempest.common import service_client
@@ -27,9 +28,11 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
- return service_client.ResponseBodyList(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
def get_db_flavor_details(self, db_flavor_id):
resp, body = self.get("flavors/%s" % str(db_flavor_id))
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, self._parse_resp(body))
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v2/json/identity_client.py b/tempest/services/identity/v2/json/identity_client.py
index 8eeefe7..81e967d 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -323,7 +323,19 @@
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, self._parse_resp(body))
+ def delete_user_ec2_credentials(self, user_id, access):
+ resp, body = self.delete('/users/%s/credentials/OS-EC2/%s' %
+ (user_id, access))
+ self.expected_success(204, resp.status)
+ return service_client.ResponseBody(resp, body)
+
def list_user_ec2_credentials(self, user_id):
resp, body = self.get('/users/%s/credentials/OS-EC2' % user_id)
self.expected_success(200, resp.status)
return service_client.ResponseBodyList(resp, self._parse_resp(body))
+
+ def show_user_ec2_credentials(self, user_id, access):
+ resp, body = self.get('/users/%s/credentials/OS-EC2/%s' %
+ (user_id, access))
+ self.expected_success(200, resp.status)
+ return service_client.ResponseBody(resp, self._parse_resp(body))
diff --git a/tempest/services/network/json/base.py b/tempest/services/network/json/base.py
new file mode 100644
index 0000000..fe150df
--- /dev/null
+++ b/tempest/services/network/json/base.py
@@ -0,0 +1,70 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+
+from tempest.common import service_client
+
+
+class BaseNetworkClient(service_client.ServiceClient):
+
+ """
+ Base class for Tempest REST clients for Neutron. Child classes use v2 of
+ the Neutron API, since the V1 API has been removed from the code base.
+ """
+
+ version = '2.0'
+ uri_prefix = "v2.0"
+
+ def list_resources(self, uri, **filters):
+ req_uri = self.uri_prefix + uri
+ if filters:
+ req_uri += '?' + urllib.urlencode(filters, doseq=1)
+ resp, body = self.get(req_uri)
+ body = json.loads(body)
+ self.expected_success(200, resp.status)
+ return service_client.ResponseBody(resp, body)
+
+ def delete_resource(self, uri):
+ req_uri = self.uri_prefix + uri
+ resp, body = self.delete(req_uri)
+ self.expected_success(204, resp.status)
+ return service_client.ResponseBody(resp, body)
+
+ def show_resource(self, uri, **fields):
+ # fields is a dict which key is 'fields' and value is a
+ # list of field's name. An example:
+ # {'fields': ['id', 'name']}
+ req_uri = self.uri_prefix + uri
+ if fields:
+ req_uri += '?' + urllib.urlencode(fields, doseq=1)
+ resp, body = self.get(req_uri)
+ body = json.loads(body)
+ self.expected_success(200, resp.status)
+ return service_client.ResponseBody(resp, body)
+
+ def create_resource(self, uri, post_data):
+ req_uri = self.uri_prefix + uri
+ req_post_data = json.dumps(post_data)
+ resp, body = self.post(req_uri, req_post_data)
+ body = json.loads(body)
+ self.expected_success(201, resp.status)
+ return service_client.ResponseBody(resp, body)
+
+ def update_resource(self, uri, post_data):
+ req_uri = self.uri_prefix + uri
+ req_post_data = json.dumps(post_data)
+ resp, body = self.put(req_uri, req_post_data)
+ body = json.loads(body)
+ self.expected_success(200, resp.status)
+ return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index ce200d2..a345d56 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -12,16 +12,14 @@
import time
-from oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
from tempest_lib.common.utils import misc
from tempest_lib import exceptions as lib_exc
-from tempest.common import service_client
from tempest import exceptions
+from tempest.services.network.json import base
-class NetworkClient(service_client.ServiceClient):
+class NetworkClient(base.BaseNetworkClient):
"""
Tempest REST client for Neutron. Uses v2 of the Neutron API, since the
@@ -36,236 +34,190 @@
quotas
"""
- version = '2.0'
- uri_prefix = "v2.0"
-
- def _list_resources(self, uri, **filters):
- req_uri = self.uri_prefix + uri
- if filters:
- req_uri += '?' + urllib.urlencode(filters, doseq=1)
- resp, body = self.get(req_uri)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def _delete_resource(self, uri):
- req_uri = self.uri_prefix + uri
- resp, body = self.delete(req_uri)
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def _show_resource(self, uri, **fields):
- # fields is a dict which key is 'fields' and value is a
- # list of field's name. An example:
- # {'fields': ['id', 'name']}
- req_uri = self.uri_prefix + uri
- if fields:
- req_uri += '?' + urllib.urlencode(fields, doseq=1)
- resp, body = self.get(req_uri)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def _create_resource(self, uri, post_data):
- req_uri = self.uri_prefix + uri
- req_post_data = json.dumps(post_data)
- resp, body = self.post(req_uri, req_post_data)
- body = json.loads(body)
- self.expected_success(201, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def _update_resource(self, uri, post_data):
- req_uri = self.uri_prefix + uri
- req_post_data = json.dumps(post_data)
- resp, body = self.put(req_uri, req_post_data)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
-
def create_network(self, **kwargs):
uri = '/networks'
post_data = {'network': kwargs}
- return self._create_resource(uri, post_data)
+ return self.create_resource(uri, post_data)
def update_network(self, network_id, **kwargs):
uri = '/networks/%s' % network_id
post_data = {'network': kwargs}
- return self._update_resource(uri, post_data)
+ return self.update_resource(uri, post_data)
def show_network(self, network_id, **fields):
uri = '/networks/%s' % network_id
- return self._show_resource(uri, **fields)
+ return self.show_resource(uri, **fields)
def delete_network(self, network_id):
uri = '/networks/%s' % network_id
- return self._delete_resource(uri)
+ return self.delete_resource(uri)
def list_networks(self, **filters):
uri = '/networks'
- return self._list_resources(uri, **filters)
+ return self.list_resources(uri, **filters)
def create_subnet(self, **kwargs):
uri = '/subnets'
post_data = {'subnet': kwargs}
- return self._create_resource(uri, post_data)
+ return self.create_resource(uri, post_data)
def update_subnet(self, subnet_id, **kwargs):
uri = '/subnets/%s' % subnet_id
post_data = {'subnet': kwargs}
- return self._update_resource(uri, post_data)
+ return self.update_resource(uri, post_data)
def show_subnet(self, subnet_id, **fields):
uri = '/subnets/%s' % subnet_id
- return self._show_resource(uri, **fields)
+ return self.show_resource(uri, **fields)
def delete_subnet(self, subnet_id):
uri = '/subnets/%s' % subnet_id
- return self._delete_resource(uri)
+ return self.delete_resource(uri)
def list_subnets(self, **filters):
uri = '/subnets'
- return self._list_resources(uri, **filters)
+ return self.list_resources(uri, **filters)
def create_port(self, **kwargs):
uri = '/ports'
post_data = {'port': kwargs}
- return self._create_resource(uri, post_data)
+ return self.create_resource(uri, post_data)
def update_port(self, port_id, **kwargs):
uri = '/ports/%s' % port_id
post_data = {'port': kwargs}
- return self._update_resource(uri, post_data)
+ return self.update_resource(uri, post_data)
def show_port(self, port_id, **fields):
uri = '/ports/%s' % port_id
- return self._show_resource(uri, **fields)
+ return self.show_resource(uri, **fields)
def delete_port(self, port_id):
uri = '/ports/%s' % port_id
- return self._delete_resource(uri)
+ return self.delete_resource(uri)
def list_ports(self, **filters):
uri = '/ports'
- return self._list_resources(uri, **filters)
+ return self.list_resources(uri, **filters)
def create_floatingip(self, **kwargs):
uri = '/floatingips'
post_data = {'floatingip': kwargs}
- return self._create_resource(uri, post_data)
+ return self.create_resource(uri, post_data)
def update_floatingip(self, floatingip_id, **kwargs):
uri = '/floatingips/%s' % floatingip_id
post_data = {'floatingip': kwargs}
- return self._update_resource(uri, post_data)
+ return self.update_resource(uri, post_data)
def show_floatingip(self, floatingip_id, **fields):
uri = '/floatingips/%s' % floatingip_id
- return self._show_resource(uri, **fields)
+ return self.show_resource(uri, **fields)
def delete_floatingip(self, floatingip_id):
uri = '/floatingips/%s' % floatingip_id
- return self._delete_resource(uri)
+ return self.delete_resource(uri)
def list_floatingips(self, **filters):
uri = '/floatingips'
- return self._list_resources(uri, **filters)
+ return self.list_resources(uri, **filters)
def create_metering_label(self, **kwargs):
uri = '/metering/metering-labels'
post_data = {'metering_label': kwargs}
- return self._create_resource(uri, post_data)
+ return self.create_resource(uri, post_data)
def show_metering_label(self, metering_label_id, **fields):
uri = '/metering/metering-labels/%s' % metering_label_id
- return self._show_resource(uri, **fields)
+ return self.show_resource(uri, **fields)
def delete_metering_label(self, metering_label_id):
uri = '/metering/metering-labels/%s' % metering_label_id
- return self._delete_resource(uri)
+ return self.delete_resource(uri)
def list_metering_labels(self, **filters):
uri = '/metering/metering-labels'
- return self._list_resources(uri, **filters)
+ return self.list_resources(uri, **filters)
def create_metering_label_rule(self, **kwargs):
uri = '/metering/metering-label-rules'
post_data = {'metering_label_rule': kwargs}
- return self._create_resource(uri, post_data)
+ return self.create_resource(uri, post_data)
def show_metering_label_rule(self, metering_label_rule_id, **fields):
uri = '/metering/metering-label-rules/%s' % metering_label_rule_id
- return self._show_resource(uri, **fields)
+ return self.show_resource(uri, **fields)
def delete_metering_label_rule(self, metering_label_rule_id):
uri = '/metering/metering-label-rules/%s' % metering_label_rule_id
- return self._delete_resource(uri)
+ return self.delete_resource(uri)
def list_metering_label_rules(self, **filters):
uri = '/metering/metering-label-rules'
- return self._list_resources(uri, **filters)
+ return self.list_resources(uri, **filters)
def create_security_group(self, **kwargs):
uri = '/security-groups'
post_data = {'security_group': kwargs}
- return self._create_resource(uri, post_data)
+ return self.create_resource(uri, post_data)
def update_security_group(self, security_group_id, **kwargs):
uri = '/security-groups/%s' % security_group_id
post_data = {'security_group': kwargs}
- return self._update_resource(uri, post_data)
+ return self.update_resource(uri, post_data)
def show_security_group(self, security_group_id, **fields):
uri = '/security-groups/%s' % security_group_id
- return self._show_resource(uri, **fields)
+ return self.show_resource(uri, **fields)
def delete_security_group(self, security_group_id):
uri = '/security-groups/%s' % security_group_id
- return self._delete_resource(uri)
+ return self.delete_resource(uri)
def list_security_groups(self, **filters):
uri = '/security-groups'
- return self._list_resources(uri, **filters)
+ return self.list_resources(uri, **filters)
def create_security_group_rule(self, **kwargs):
uri = '/security-group-rules'
post_data = {'security_group_rule': kwargs}
- return self._create_resource(uri, post_data)
+ return self.create_resource(uri, post_data)
def show_security_group_rule(self, security_group_rule_id, **fields):
uri = '/security-group-rules/%s' % security_group_rule_id
- return self._show_resource(uri, **fields)
+ return self.show_resource(uri, **fields)
def delete_security_group_rule(self, security_group_rule_id):
uri = '/security-group-rules/%s' % security_group_rule_id
- return self._delete_resource(uri)
+ return self.delete_resource(uri)
def list_security_group_rules(self, **filters):
uri = '/security-group-rules'
- return self._list_resources(uri, **filters)
+ return self.list_resources(uri, **filters)
def show_extension(self, ext_alias, **fields):
uri = '/extensions/%s' % ext_alias
- return self._show_resource(uri, **fields)
+ return self.show_resource(uri, **fields)
def list_extensions(self, **filters):
uri = '/extensions'
- return self._list_resources(uri, **filters)
+ return self.list_resources(uri, **filters)
def create_bulk_network(self, names):
network_list = [{'name': name} for name in names]
post_data = {'networks': network_list}
uri = '/networks'
- return self._create_resource(uri, post_data)
+ return self.create_resource(uri, post_data)
def create_bulk_subnet(self, subnet_list):
post_data = {'subnets': subnet_list}
uri = '/subnets'
- return self._create_resource(uri, post_data)
+ return self.create_resource(uri, post_data)
def create_bulk_port(self, port_list):
post_data = {'ports': port_list}
uri = '/ports'
- return self._create_resource(uri, post_data)
+ return self.create_resource(uri, post_data)
def wait_for_resource_deletion(self, resource_type, id):
"""Waits for a resource to be deleted."""
@@ -327,30 +279,30 @@
def update_quotas(self, tenant_id, **kwargs):
put_body = {'quota': kwargs}
uri = '/quotas/%s' % tenant_id
- return self._update_resource(uri, put_body)
+ return self.update_resource(uri, put_body)
def reset_quotas(self, tenant_id):
uri = '/quotas/%s' % tenant_id
- return self._delete_resource(uri)
+ return self.delete_resource(uri)
def show_quotas(self, tenant_id, **fields):
uri = '/quotas/%s' % tenant_id
- return self._show_resource(uri, **fields)
+ return self.show_resource(uri, **fields)
def list_quotas(self, **filters):
uri = '/quotas'
- return self._list_resources(uri, **filters)
+ return self.list_resources(uri, **filters)
def create_router(self, name, admin_state_up=True, **kwargs):
post_body = {'router': kwargs}
post_body['router']['name'] = name
post_body['router']['admin_state_up'] = admin_state_up
uri = '/routers'
- return self._create_resource(uri, post_body)
+ return self.create_resource(uri, post_body)
def _update_router(self, router_id, set_enable_snat, **kwargs):
uri = '/routers/%s' % router_id
- body = self._show_resource(uri)
+ body = self.show_resource(uri)
update_body = {}
update_body['name'] = kwargs.get('name', body['router']['name'])
update_body['admin_state_up'] = kwargs.get(
@@ -369,7 +321,7 @@
if 'distributed' in kwargs:
update_body['distributed'] = kwargs['distributed']
update_body = dict(router=update_body)
- return self._update_resource(uri, update_body)
+ return self.update_resource(uri, update_body)
def update_router(self, router_id, **kwargs):
"""Update a router leaving enable_snat to its default value."""
@@ -382,15 +334,15 @@
def show_router(self, router_id, **fields):
uri = '/routers/%s' % router_id
- return self._show_resource(uri, **fields)
+ return self.show_resource(uri, **fields)
def delete_router(self, router_id):
uri = '/routers/%s' % router_id
- return self._delete_resource(uri)
+ return self.delete_resource(uri)
def list_routers(self, **filters):
uri = '/routers'
- return self._list_resources(uri, **filters)
+ return self.list_resources(uri, **filters)
def update_router_with_snat_gw_info(self, router_id, **kwargs):
"""Update a router passing also the enable_snat attribute.
@@ -403,26 +355,26 @@
def add_router_interface_with_subnet_id(self, router_id, subnet_id):
uri = '/routers/%s/add_router_interface' % router_id
update_body = {"subnet_id": subnet_id}
- return self._update_resource(uri, update_body)
+ return self.update_resource(uri, update_body)
def add_router_interface_with_port_id(self, router_id, port_id):
uri = '/routers/%s/add_router_interface' % router_id
update_body = {"port_id": port_id}
- return self._update_resource(uri, update_body)
+ return self.update_resource(uri, update_body)
def remove_router_interface_with_subnet_id(self, router_id, subnet_id):
uri = '/routers/%s/remove_router_interface' % router_id
update_body = {"subnet_id": subnet_id}
- return self._update_resource(uri, update_body)
+ return self.update_resource(uri, update_body)
def remove_router_interface_with_port_id(self, router_id, port_id):
uri = '/routers/%s/remove_router_interface' % router_id
update_body = {"port_id": port_id}
- return self._update_resource(uri, update_body)
+ return self.update_resource(uri, update_body)
def list_router_interfaces(self, uuid):
uri = '/ports?device_id=%s' % uuid
- return self._list_resources(uri)
+ return self.list_resources(uri)
def update_agent(self, agent_id, agent_info):
"""
@@ -431,45 +383,45 @@
"""
uri = '/agents/%s' % agent_id
agent = {"agent": agent_info}
- return self._update_resource(uri, agent)
+ return self.update_resource(uri, agent)
def show_agent(self, agent_id, **fields):
uri = '/agents/%s' % agent_id
- return self._show_resource(uri, **fields)
+ return self.show_resource(uri, **fields)
def list_agents(self, **filters):
uri = '/agents'
- return self._list_resources(uri, **filters)
+ return self.list_resources(uri, **filters)
def list_routers_on_l3_agent(self, agent_id):
uri = '/agents/%s/l3-routers' % agent_id
- return self._list_resources(uri)
+ return self.list_resources(uri)
def list_l3_agents_hosting_router(self, router_id):
uri = '/routers/%s/l3-agents' % router_id
- return self._list_resources(uri)
+ return self.list_resources(uri)
def add_router_to_l3_agent(self, agent_id, router_id):
uri = '/agents/%s/l3-routers' % agent_id
post_body = {"router_id": router_id}
- return self._create_resource(uri, post_body)
+ return self.create_resource(uri, post_body)
def remove_router_from_l3_agent(self, agent_id, router_id):
uri = '/agents/%s/l3-routers/%s' % (agent_id, router_id)
- return self._delete_resource(uri)
+ return self.delete_resource(uri)
def list_dhcp_agent_hosting_network(self, network_id):
uri = '/networks/%s/dhcp-agents' % network_id
- return self._list_resources(uri)
+ return self.list_resources(uri)
def list_networks_hosted_by_one_dhcp_agent(self, agent_id):
uri = '/agents/%s/dhcp-networks' % agent_id
- return self._list_resources(uri)
+ return self.list_resources(uri)
def remove_network_from_dhcp_agent(self, agent_id, network_id):
uri = '/agents/%s/dhcp-networks/%s' % (agent_id,
network_id)
- return self._delete_resource(uri)
+ return self.delete_resource(uri)
def update_extra_routes(self, router_id, routes):
uri = '/routers/%s' % router_id
@@ -478,7 +430,7 @@
'routes': routes
}
}
- return self._update_resource(uri, put_body)
+ return self.update_resource(uri, put_body)
def delete_extra_routes(self, router_id):
uri = '/routers/%s' % router_id
@@ -487,9 +439,9 @@
'routes': None
}
}
- return self._update_resource(uri, put_body)
+ return self.update_resource(uri, put_body)
def add_dhcp_agent_to_network(self, agent_id, network_id):
post_body = {'network_id': network_id}
uri = '/agents/%s/dhcp-networks' % agent_id
- return self._create_resource(uri, post_body)
+ return self.create_resource(uri, post_body)
diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py
index 1f181e3..fc8951e 100644
--- a/tempest/services/telemetry/json/telemetry_client.py
+++ b/tempest/services/telemetry/json/telemetry_client.py
@@ -140,3 +140,10 @@
self.expected_success(200, resp.status)
body = self.deserialize(body)
return service_client.ResponseBodyData(resp, body)
+
+ def show_alarm_history(self, alarm_id):
+ uri = "%s/alarms/%s/history" % (self.uri_prefix, alarm_id)
+ resp, body = self.get(uri)
+ self.expected_success(200, resp.status)
+ body = self.deserialize(body)
+ return service_client.ResponseBodyList(resp, body)
diff --git a/tempest/stress/actions/server_create_destroy.py b/tempest/stress/actions/server_create_destroy.py
index 17f4bc9..44b6f62 100644
--- a/tempest/stress/actions/server_create_destroy.py
+++ b/tempest/stress/actions/server_create_destroy.py
@@ -30,7 +30,7 @@
name = data_utils.rand_name("instance")
self.logger.info("creating %s" % name)
server = self.manager.servers_client.create_server(
- name, self.image, self.flavor)
+ name=name, imageRef=self.image, flavorRef=self.flavor)['server']
server_id = server['id']
waiters.wait_for_server_status(self.manager.servers_client, server_id,
'ACTIVE')
diff --git a/tempest/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
index 2505a77..d912b25 100644
--- a/tempest/stress/actions/ssh_floating.py
+++ b/tempest/stress/actions/ssh_floating.py
@@ -75,9 +75,9 @@
self.logger.info("creating %s" % name)
vm_args = self.vm_extra_args.copy()
vm_args['security_groups'] = [self.sec_grp]
- server = servers_client.create_server(name, self.image,
- self.flavor,
- **vm_args)
+ server = servers_client.create_server(name=name, imageRef=self.image,
+ flavorRef=self.flavor,
+ **vm_args)['server']
self.server_id = server['id']
if self.wait_after_vm_create:
waiters.wait_for_server_status(self.manager.servers_client,
diff --git a/tempest/stress/actions/volume_attach_delete.py b/tempest/stress/actions/volume_attach_delete.py
index b35f587..847f342 100644
--- a/tempest/stress/actions/volume_attach_delete.py
+++ b/tempest/stress/actions/volume_attach_delete.py
@@ -39,7 +39,7 @@
vm_name = data_utils.rand_name("instance")
self.logger.info("creating vm: %s" % vm_name)
server = self.manager.servers_client.create_server(
- vm_name, self.image, self.flavor)
+ name=vm_name, imageRef=self.image, flavorRef=self.flavor)['server']
server_id = server['id']
waiters.wait_for_server_status(self.manager.servers_client, server_id,
'ACTIVE')
diff --git a/tempest/stress/actions/volume_attach_verify.py b/tempest/stress/actions/volume_attach_verify.py
index fe481c4..95841a9 100644
--- a/tempest/stress/actions/volume_attach_verify.py
+++ b/tempest/stress/actions/volume_attach_verify.py
@@ -39,9 +39,9 @@
vm_args = self.vm_extra_args.copy()
vm_args['security_groups'] = [self.sec_grp]
vm_args['key_name'] = self.key['name']
- server = servers_client.create_server(name, self.image,
- self.flavor,
- **vm_args)
+ server = servers_client.create_server(name=name, imageRef=self.image,
+ flavorRef=self.flavor,
+ **vm_args)['server']
self.server_id = server['id']
waiters.wait_for_server_status(self.manager.servers_client,
self.server_id, 'ACTIVE')
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index bdb39d8..7634d2c 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -25,7 +25,7 @@
from tempest import clients
-from tempest.common import isolated_creds
+from tempest.common import cred_client
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
@@ -155,7 +155,7 @@
identity_client = admin_manager.identity_client
else:
identity_client = admin_manager.identity_v3_client
- credentials_client = isolated_creds.get_creds_client(
+ credentials_client = cred_client.get_creds_client(
identity_client)
project = credentials_client.create_project(
name=tenant_name, description=tenant_name)
diff --git a/tempest/test.py b/tempest/test.py
index df6b30d..142488c 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -31,6 +31,7 @@
import testtools
from tempest import clients
+from tempest.common import cred_client
from tempest.common import credentials
from tempest.common import fixed_network
import tempest.common.generator.valid_generator as valid
@@ -182,6 +183,7 @@
'volume': CONF.volume_feature_enabled.api_extensions,
'network': CONF.network_feature_enabled.api_extensions,
'object': CONF.object_storage_feature_enabled.discoverable_apis,
+ 'identity': CONF.identity_feature_enabled.api_extensions
}
if len(config_dict[service]) == 0:
return False
@@ -432,6 +434,25 @@
def credentials_provider(self):
return self._get_credentials_provider()
+ @property
+ def identity_utils(self):
+ """A client that abstracts v2 and v3 identity operations.
+
+ This can be used for creating and tearing down projects in tests. It
+ should not be used for testing identity features.
+ """
+ if CONF.identity.auth_version == 'v2':
+ client = self.os_admin.identity_client
+ else:
+ client = self.os_admin.identity_v3_client
+
+ try:
+ domain = client.auth_provider.credentials.project_domain_name
+ except AttributeError:
+ domain = 'Default'
+
+ return cred_client.get_creds_client(client, domain)
+
@classmethod
def _get_credentials_provider(cls):
"""Returns a credentials provider
@@ -530,9 +551,10 @@
else:
floating_ip = False
if security_group is None:
- security_group = True
+ security_group = CONF.validation.security_group
if security_group_rules is None:
- security_group_rules = True
+ security_group_rules = CONF.validation.security_group_rules
+
if not cls.validation_resources:
cls.validation_resources = {
'keypair': keypair,
@@ -568,7 +590,7 @@
:return: network dict including 'id' and 'name'
"""
# Make sure isolated_creds exists and get a network client
- networks_client = cls.get_client_manager().networks_client
+ networks_client = cls.get_client_manager().compute_networks_client
cred_provider = cls._get_credentials_provider()
# In case of nova network, isolated tenants are not able to list the
# network configured in fixed_network_name, even if the can use it
@@ -577,7 +599,8 @@
if (not CONF.service_available.neutron and
credentials.is_admin_available()):
admin_creds = cred_provider.get_admin_creds()
- networks_client = clients.Manager(admin_creds).networks_client
+ admin_manager = clients.Manager(admin_creds)
+ networks_client = admin_manager.compute_networks_client
return fixed_network.get_tenant_network(cred_provider,
networks_client)
diff --git a/tempest/tests/fake_tempest_plugin.py b/tempest/tests/fake_tempest_plugin.py
new file mode 100644
index 0000000..f718d0b
--- /dev/null
+++ b/tempest/tests/fake_tempest_plugin.py
@@ -0,0 +1,40 @@
+# Copyright (c) 2015 Deutsche Telekom AG
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.test_discover import plugins
+
+
+class FakePlugin(plugins.TempestPlugin):
+ expected_load_test = ["my/test/path", "/home/dir"]
+
+ def load_tests(self):
+ return self.expected_load_test
+
+ def register_opts(self, conf):
+ return
+
+ def get_opt_lists(self):
+ return []
+
+
+class FakeStevedoreObj(object):
+ obj = FakePlugin()
+
+ @property
+ def name(self):
+ return self._name
+
+ def __init__(self, name='Test1'):
+ self._name = name
diff --git a/tempest/tests/services/compute/test_agents_client.py b/tempest/tests/services/compute/test_agents_client.py
index 9493a32..31e576e 100644
--- a/tempest/tests/services/compute/test_agents_client.py
+++ b/tempest/tests/services/compute/test_agents_client.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import agents_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
@@ -56,6 +57,12 @@
'tempest.common.service_client.ServiceClient.get',
{"agents": []},
bytes_body)
+ self.check_service_client_function(
+ self.client.list_agents,
+ 'tempest.common.service_client.ServiceClient.get',
+ {"agents": []},
+ bytes_body,
+ hypervisor="kvm")
def _test_create_agent(self, bytes_body=False):
self.check_service_client_function(
diff --git a/tempest/tests/services/compute/test_aggregates_client.py b/tempest/tests/services/compute/test_aggregates_client.py
index 8184a46..e92b76b 100644
--- a/tempest/tests/services/compute/test_aggregates_client.py
+++ b/tempest/tests/services/compute/test_aggregates_client.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import aggregates_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_availability_zone_client.py b/tempest/tests/services/compute/test_availability_zone_client.py
index 715cfd7..e1d94bc 100644
--- a/tempest/tests/services/compute/test_availability_zone_client.py
+++ b/tempest/tests/services/compute/test_availability_zone_client.py
@@ -12,14 +12,17 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
+
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import availability_zone_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
class TestAvailabilityZoneClient(base.BaseComputeServiceTest):
- FAKE_AVAILABIRITY_ZONE_INFO = {
+ FAKE_AZ_INFO = {
"availabilityZoneInfo":
[
{
@@ -32,20 +35,48 @@
]
}
+ FAKE_AZ_DETAILS = {
+ "testhost": {
+ "nova-compute": {
+ "available": True,
+ "active": True,
+ "updated_at": "2015-09-10T07:16:46.000000"
+ }
+ }
+ }
+
def setUp(self):
super(TestAvailabilityZoneClient, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
self.client = availability_zone_client.AvailabilityZoneClient(
fake_auth, 'compute', 'regionOne')
- def test_list_availability_zones_with_str_body(self):
+ def _test_availability_zones(self, to_utf=False):
self.check_service_client_function(
self.client.list_availability_zones,
'tempest.common.service_client.ServiceClient.get',
- self.FAKE_AVAILABIRITY_ZONE_INFO)
+ self.FAKE_AZ_INFO,
+ to_utf)
+
+ def _test_availability_zones_with_details(self, to_utf=False):
+ fake_az_details = copy.deepcopy(self.FAKE_AZ_INFO)
+ fake_az_details['availabilityZoneInfo'][0]['hosts'] = \
+ self.FAKE_AZ_DETAILS
+ self.check_service_client_function(
+ self.client.list_availability_zones,
+ 'tempest.common.service_client.ServiceClient.get',
+ fake_az_details,
+ to_utf,
+ detail=True)
+
+ def test_list_availability_zones_with_str_body(self):
+ self._test_availability_zones()
def test_list_availability_zones_with_bytes_body(self):
- self.check_service_client_function(
- self.client.list_availability_zones,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_AVAILABIRITY_ZONE_INFO, to_utf=True)
+ self._test_availability_zones(True)
+
+ def test_list_availability_zones_with_str_body_and_details(self):
+ self._test_availability_zones_with_details()
+
+ def test_list_availability_zones_with_bytes_body_and_details(self):
+ self._test_availability_zones_with_details(True)
diff --git a/tempest/tests/services/compute/test_baremetal_nodes_client.py b/tempest/tests/services/compute/test_baremetal_nodes_client.py
index edf9014..86c035c 100644
--- a/tempest/tests/services/compute/test_baremetal_nodes_client.py
+++ b/tempest/tests/services/compute/test_baremetal_nodes_client.py
@@ -14,8 +14,9 @@
import copy
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import baremetal_nodes_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_certificates_client.py b/tempest/tests/services/compute/test_certificates_client.py
index c926fce..2ba90d0 100644
--- a/tempest/tests/services/compute/test_certificates_client.py
+++ b/tempest/tests/services/compute/test_certificates_client.py
@@ -14,8 +14,9 @@
import copy
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import certificates_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_extensions_client.py b/tempest/tests/services/compute/test_extensions_client.py
index 86f81f3..21efc52 100644
--- a/tempest/tests/services/compute/test_extensions_client.py
+++ b/tempest/tests/services/compute/test_extensions_client.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import extensions_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_fixedIPs_client.py b/tempest/tests/services/compute/test_fixedIPs_client.py
index d7a9694..5acb422 100644
--- a/tempest/tests/services/compute/test_fixedIPs_client.py
+++ b/tempest/tests/services/compute/test_fixedIPs_client.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import fixed_ips_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_floating_ip_pools_client.py b/tempest/tests/services/compute/test_floating_ip_pools_client.py
index 0d19b7b..1cb4bf3 100644
--- a/tempest/tests/services/compute/test_floating_ip_pools_client.py
+++ b/tempest/tests/services/compute/test_floating_ip_pools_client.py
@@ -12,9 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib.tests import fake_auth_provider
from tempest.services.compute.json import floating_ip_pools_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_floating_ips_bulk_client.py b/tempest/tests/services/compute/test_floating_ips_bulk_client.py
new file mode 100644
index 0000000..600985b
--- /dev/null
+++ b/tempest/tests/services/compute/test_floating_ips_bulk_client.py
@@ -0,0 +1,88 @@
+# Copyright 2015 NEC Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest_lib.tests import fake_auth_provider
+
+from tempest.services.compute.json import floating_ips_bulk_client
+from tempest.tests.services.compute import base
+
+
+class TestFloatingIPsBulkClient(base.BaseComputeServiceTest):
+
+ FAKE_FIP_BULK_LIST = {"floating_ip_info": [{
+ "address": "10.10.10.1",
+ "instance_uuid": None,
+ "fixed_ip": None,
+ "interface": "eth0",
+ "pool": "nova",
+ "project_id": None
+ },
+ {
+ "address": "10.10.10.2",
+ "instance_uuid": None,
+ "fixed_ip": None,
+ "interface": "eth0",
+ "pool": "nova",
+ "project_id": None
+ }]}
+
+ def setUp(self):
+ super(TestFloatingIPsBulkClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = floating_ips_bulk_client.FloatingIPsBulkClient(
+ fake_auth, 'compute', 'regionOne')
+
+ def _test_list_floating_ips_bulk(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_floating_ips_bulk,
+ 'tempest.common.service_client.ServiceClient.get',
+ self.FAKE_FIP_BULK_LIST,
+ to_utf=bytes_body)
+
+ def _test_create_floating_ips_bulk(self, bytes_body=False):
+ fake_fip_create_data = {"floating_ips_bulk_create": {
+ "ip_range": "192.168.1.0/24", "pool": "nova", "interface": "eth0"}}
+ self.check_service_client_function(
+ self.client.create_floating_ips_bulk,
+ 'tempest.common.service_client.ServiceClient.post',
+ fake_fip_create_data,
+ to_utf=bytes_body,
+ ip_range="192.168.1.0/24", pool="nova", interface="eth0")
+
+ def _test_delete_floating_ips_bulk(self, bytes_body=False):
+ fake_fip_delete_data = {"floating_ips_bulk_delete": "192.168.1.0/24"}
+ self.check_service_client_function(
+ self.client.delete_floating_ips_bulk,
+ 'tempest.common.service_client.ServiceClient.put',
+ fake_fip_delete_data,
+ to_utf=bytes_body,
+ ip_range="192.168.1.0/24")
+
+ def test_list_floating_ips_bulk_with_str_body(self):
+ self._test_list_floating_ips_bulk()
+
+ def test_list_floating_ips_bulk_with_bytes_body(self):
+ self._test_list_floating_ips_bulk(True)
+
+ def test_create_floating_ips_bulk_with_str_body(self):
+ self._test_create_floating_ips_bulk()
+
+ def test_create_floating_ips_bulk_with_bytes_body(self):
+ self._test_create_floating_ips_bulk(True)
+
+ def test_delete_floating_ips_bulk_with_str_body(self):
+ self._test_delete_floating_ips_bulk()
+
+ def test_delete_floating_ips_bulk_with_bytes_body(self):
+ self._test_delete_floating_ips_bulk(True)
diff --git a/tempest/tests/services/compute/test_floating_ips_client.py b/tempest/tests/services/compute/test_floating_ips_client.py
new file mode 100644
index 0000000..ee22004
--- /dev/null
+++ b/tempest/tests/services/compute/test_floating_ips_client.py
@@ -0,0 +1,113 @@
+# Copyright 2015 IBM Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from oslotest import mockpatch
+from tempest_lib import exceptions as lib_exc
+
+from tempest.services.compute.json import floating_ips_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestFloatingIpsClient(base.BaseComputeServiceTest):
+
+ floating_ip = {"fixed_ip": None,
+ "id": "46d61064-13ba-4bf0-9557-69de824c3d6f",
+ "instance_id": "a1daa443-a6bb-463e-aea2-104b7d912eb8",
+ "ip": "10.10.10.1",
+ "pool": "nova"}
+
+ def setUp(self):
+ super(TestFloatingIpsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = floating_ips_client.FloatingIPsClient(
+ fake_auth, 'compute', 'regionOne')
+
+ def _test_list_floating_ips(self, bytes_body=False):
+ expected = {'floating_ips': [TestFloatingIpsClient.floating_ip]}
+ self.check_service_client_function(
+ self.client.list_floating_ips,
+ 'tempest.common.service_client.ServiceClient.get',
+ expected,
+ bytes_body)
+
+ def test_list_floating_ips_str_body(self):
+ self._test_list_floating_ips(bytes_body=False)
+
+ def test_list_floating_ips_byte_body(self):
+ self._test_list_floating_ips(bytes_body=True)
+
+ def _test_show_floating_ip(self, bytes_body=False):
+ expected = {"floating_ip": TestFloatingIpsClient.floating_ip}
+ self.check_service_client_function(
+ self.client.show_floating_ip,
+ 'tempest.common.service_client.ServiceClient.get',
+ expected,
+ bytes_body,
+ floating_ip_id='a1daa443-a6bb-463e-aea2-104b7d912eb8')
+
+ def test_show_floating_ip_str_body(self):
+ self._test_show_floating_ip(bytes_body=False)
+
+ def test_show_floating_ip_byte_body(self):
+ self._test_show_floating_ip(bytes_body=True)
+
+ def _test_create_floating_ip(self, bytes_body=False):
+ expected = {"floating_ip": TestFloatingIpsClient.floating_ip}
+ self.check_service_client_function(
+ self.client.create_floating_ip,
+ 'tempest.common.service_client.ServiceClient.post',
+ expected,
+ bytes_body,
+ pool_name='nova')
+
+ def test_create_floating_ip_str_body(self):
+ self._test_create_floating_ip(bytes_body=False)
+
+ def test_create_floating_ip_byte_body(self):
+ self._test_create_floating_ip(bytes_body=True)
+
+ def test_delete_floating_ip(self):
+ self.check_service_client_function(
+ self.client.delete_floating_ip,
+ 'tempest.common.service_client.ServiceClient.delete',
+ {}, status=202, floating_ip_id='fake-id')
+
+ def test_associate_floating_ip_to_server(self):
+ self.check_service_client_function(
+ self.client.associate_floating_ip_to_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {}, status=202, floating_ip='10.10.10.1',
+ server_id='c782b7a9-33cd-45f0-b795-7f87f456408b')
+
+ def test_disassociate_floating_ip_from_server(self):
+ self.check_service_client_function(
+ self.client.disassociate_floating_ip_from_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {}, status=202, floating_ip='10.10.10.1',
+ server_id='c782b7a9-33cd-45f0-b795-7f87f456408b')
+
+ def test_is_resource_deleted_true(self):
+ self.useFixture(mockpatch.Patch(
+ 'tempest.services.compute.json.floating_ips_client.'
+ 'FloatingIPsClient.show_floating_ip',
+ side_effect=lib_exc.NotFound()))
+ self.assertTrue(self.client.is_resource_deleted('fake-id'))
+
+ def test_is_resource_deleted_false(self):
+ self.useFixture(mockpatch.Patch(
+ 'tempest.services.compute.json.floating_ips_client.'
+ 'FloatingIPsClient.show_floating_ip',
+ return_value={"floating_ip": TestFloatingIpsClient.floating_ip}))
+ self.assertFalse(self.client.is_resource_deleted('fake-id'))
diff --git a/tempest/tests/services/compute/test_hypervisor_client.py b/tempest/tests/services/compute/test_hypervisor_client.py
new file mode 100644
index 0000000..441e7e6
--- /dev/null
+++ b/tempest/tests/services/compute/test_hypervisor_client.py
@@ -0,0 +1,167 @@
+# Copyright 2015 IBM Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.services.compute.json import hypervisor_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestHypervisorClient(base.BaseComputeServiceTest):
+
+ hypervisor_id = "1"
+ hypervisor_name = "hyper.hostname.com"
+
+ def setUp(self):
+ super(TestHypervisorClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = hypervisor_client.HypervisorClient(
+ fake_auth, 'compute', 'regionOne')
+
+ def test_list_hypervisor_str_body(self):
+ self._test_list_hypervisor(bytes_body=False)
+
+ def test_list_hypervisor_byte_body(self):
+ self._test_list_hypervisor(bytes_body=True)
+
+ def _test_list_hypervisor(self, bytes_body=False):
+ expected = {"hypervisors": [{
+ "id": 1,
+ "hypervisor_hostname": "hypervisor1.hostname.com"},
+ {
+ "id": 2,
+ "hypervisor_hostname": "hypervisor2.hostname.com"}]}
+ self.check_service_client_function(
+ self.client.list_hypervisors,
+ 'tempest.common.service_client.ServiceClient.get',
+ expected, bytes_body)
+
+ def test_show_hypervisor_str_body(self):
+ self._test_show_hypervisor(bytes_body=False)
+
+ def test_show_hypervisor_byte_body(self):
+ self._test_show_hypervisor(bytes_body=True)
+
+ def _test_show_hypervisor(self, bytes_body=False):
+ expected = {"hypervisor": {
+ "cpu_info": "?",
+ "current_workload": 0,
+ "disk_available_least": 1,
+ "host_ip": "10.10.10.10",
+ "free_disk_gb": 1028,
+ "free_ram_mb": 7680,
+ "hypervisor_hostname": "fake-mini",
+ "hypervisor_type": "fake",
+ "hypervisor_version": 1,
+ "id": 1,
+ "local_gb": 1028,
+ "local_gb_used": 0,
+ "memory_mb": 8192,
+ "memory_mb_used": 512,
+ "running_vms": 0,
+ "service": {
+ "host": "fake_host",
+ "id": 2},
+ "vcpus": 1,
+ "vcpus_used": 0}}
+ self.check_service_client_function(
+ self.client.show_hypervisor,
+ 'tempest.common.service_client.ServiceClient.get',
+ expected, bytes_body,
+ hypervisor_id=self.hypervisor_id)
+
+ def test_list_servers_on_hypervisor_str_body(self):
+ self._test_list_servers_on_hypervisor(bytes_body=False)
+
+ def test_list_servers_on_hypervisor_byte_body(self):
+ self._test_list_servers_on_hypervisor(bytes_body=True)
+
+ def _test_list_servers_on_hypervisor(self, bytes_body=False):
+ expected = {"hypervisors": [{
+ "id": 1,
+ "hypervisor_hostname": "hyper.hostname.com",
+ "servers": [{
+ "uuid": "e1ae8fc4-b72d-4c2f-a427-30dd420b6277",
+ "name": "instance-00000001"},
+ {
+ "uuid": "e1ae8fc4-b72d-4c2f-a427-30dd42066666",
+ "name": "instance-00000002"}
+ ]}
+ ]}
+ self.check_service_client_function(
+ self.client.list_servers_on_hypervisor,
+ 'tempest.common.service_client.ServiceClient.get',
+ expected, bytes_body,
+ hypervisor_name=self.hypervisor_name)
+
+ def test_show_hypervisor_statistics_str_body(self):
+ self._test_show_hypervisor_statistics(bytes_body=False)
+
+ def test_show_hypervisor_statistics_byte_body(self):
+ self._test_show_hypervisor_statistics(bytes_body=True)
+
+ def _test_show_hypervisor_statistics(self, bytes_body=False):
+ expected = {
+ "hypervisor_statistics": {
+ "count": 1,
+ "current_workload": 0,
+ "disk_available_least": 0,
+ "free_disk_gb": 1028,
+ "free_ram_mb": 7680,
+ "local_gb": 1028,
+ "local_gb_used": 0,
+ "memory_mb": 8192,
+ "memory_mb_used": 512,
+ "running_vms": 0,
+ "vcpus": 1,
+ "vcpus_used": 0}}
+ self.check_service_client_function(
+ self.client.show_hypervisor_statistics,
+ 'tempest.common.service_client.ServiceClient.get',
+ expected, bytes_body)
+
+ def test_show_hypervisor_uptime_str_body(self):
+ self._test_show_hypervisor_uptime(bytes_body=False)
+
+ def test_show_hypervisor_uptime_byte_body(self):
+ self._test_show_hypervisor_uptime(bytes_body=True)
+
+ def _test_show_hypervisor_uptime(self, bytes_body=False):
+ expected = {
+ "hypervisor": {
+ "hypervisor_hostname": "fake-mini",
+ "id": 1,
+ "uptime": (" 08:32:11 up 93 days, 18:25, 12 users, "
+ " load average: 0.20, 0.12, 0.14")
+ }}
+ self.check_service_client_function(
+ self.client.show_hypervisor_uptime,
+ 'tempest.common.service_client.ServiceClient.get',
+ expected, bytes_body,
+ hypervisor_id=self.hypervisor_id)
+
+ def test_search_hypervisor_str_body(self):
+ self._test_search_hypervisor(bytes_body=False)
+
+ def test_search_hypervisor_byte_body(self):
+ self._test_search_hypervisor(bytes_body=True)
+
+ def _test_search_hypervisor(self, bytes_body=False):
+ expected = {"hypervisors": [{
+ "id": 2,
+ "hypervisor_hostname": "hyper.hostname.com"}]}
+ self.check_service_client_function(
+ self.client.search_hypervisor,
+ 'tempest.common.service_client.ServiceClient.get',
+ expected, bytes_body,
+ hypervisor_name=self.hypervisor_name)
diff --git a/tempest/tests/services/compute/test_instance_usage_audit_log_client.py b/tempest/tests/services/compute/test_instance_usage_audit_log_client.py
index d4bc889..b4af9d5 100644
--- a/tempest/tests/services/compute/test_instance_usage_audit_log_client.py
+++ b/tempest/tests/services/compute/test_instance_usage_audit_log_client.py
@@ -14,8 +14,9 @@
import datetime
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import instance_usage_audit_log_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_keypairs_client.py b/tempest/tests/services/compute/test_keypairs_client.py
index 6ad187b..8b1a9a8 100644
--- a/tempest/tests/services/compute/test_keypairs_client.py
+++ b/tempest/tests/services/compute/test_keypairs_client.py
@@ -14,8 +14,9 @@
import copy
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import keypairs_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_limits_client.py b/tempest/tests/services/compute/test_limits_client.py
index 0036a3d..733d3d1 100644
--- a/tempest/tests/services/compute/test_limits_client.py
+++ b/tempest/tests/services/compute/test_limits_client.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import limits_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_migrations_client.py b/tempest/tests/services/compute/test_migrations_client.py
index 83fe461..55f2ef2 100644
--- a/tempest/tests/services/compute/test_migrations_client.py
+++ b/tempest/tests/services/compute/test_migrations_client.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import migrations_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_networks_client.py b/tempest/tests/services/compute/test_networks_client.py
index b47430b..cec8262 100644
--- a/tempest/tests/services/compute/test_networks_client.py
+++ b/tempest/tests/services/compute/test_networks_client.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import networks_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_quota_classes_client.py b/tempest/tests/services/compute/test_quota_classes_client.py
index f4fc51a..29800a2 100644
--- a/tempest/tests/services/compute/test_quota_classes_client.py
+++ b/tempest/tests/services/compute/test_quota_classes_client.py
@@ -14,8 +14,9 @@
import copy
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import quota_classes_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_quotas_client.py b/tempest/tests/services/compute/test_quotas_client.py
index 68f74aa..9a9d8fe 100644
--- a/tempest/tests/services/compute/test_quotas_client.py
+++ b/tempest/tests/services/compute/test_quotas_client.py
@@ -14,8 +14,9 @@
import copy
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import quotas_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_security_group_default_rules_client.py b/tempest/tests/services/compute/test_security_group_default_rules_client.py
new file mode 100644
index 0000000..99ab305
--- /dev/null
+++ b/tempest/tests/services/compute/test_security_group_default_rules_client.py
@@ -0,0 +1,89 @@
+# Copyright 2015 NEC Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest_lib.tests import fake_auth_provider
+
+from tempest.services.compute.json import security_group_default_rules_client
+from tempest.tests.services.compute import base
+
+
+class TestSecurityGroupDefaultRulesClient(base.BaseComputeServiceTest):
+ FAKE_RULE = {
+ "from_port": 80,
+ "id": 1,
+ "ip_protocol": "TCP",
+ "ip_range": {
+ "cidr": "10.10.10.0/24"
+ },
+ "to_port": 80
+ }
+
+ def setUp(self):
+ super(TestSecurityGroupDefaultRulesClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = (security_group_default_rules_client.
+ SecurityGroupDefaultRulesClient(fake_auth, 'compute',
+ 'regionOne'))
+
+ def _test_list_security_group_default_rules(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_security_group_default_rules,
+ 'tempest.common.service_client.ServiceClient.get',
+ {"security_group_default_rules": [self.FAKE_RULE]},
+ to_utf=bytes_body)
+
+ def test_list_security_group_default_rules_with_str_body(self):
+ self._test_list_security_group_default_rules()
+
+ def test_list_security_group_default_rules_with_bytes_body(self):
+ self._test_list_security_group_default_rules(bytes_body=True)
+
+ def _test_show_security_group_default_rule(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_security_group_default_rule,
+ 'tempest.common.service_client.ServiceClient.get',
+ {"security_group_default_rule": self.FAKE_RULE},
+ to_utf=bytes_body,
+ security_group_default_rule_id=1)
+
+ def test_show_security_group_default_rule_with_str_body(self):
+ self._test_show_security_group_default_rule()
+
+ def test_show_security_group_default_rule_with_bytes_body(self):
+ self._test_show_security_group_default_rule(bytes_body=True)
+
+ def _test_create_security_default_group_rule(self, bytes_body=False):
+ request_body = {
+ "to_port": 80,
+ "from_port": 80,
+ "ip_protocol": "TCP",
+ "cidr": "10.10.10.0/24"
+ }
+ self.check_service_client_function(
+ self.client.create_security_default_group_rule,
+ 'tempest.common.service_client.ServiceClient.post',
+ {"security_group_default_rule": self.FAKE_RULE},
+ to_utf=bytes_body, **request_body)
+
+ def test_create_security_default_group_rule_with_str_body(self):
+ self._test_create_security_default_group_rule()
+
+ def test_create_security_default_group_rule_with_bytes_body(self):
+ self._test_create_security_default_group_rule(bytes_body=True)
+
+ def test_delete_security_group_default_rule(self):
+ self.check_service_client_function(
+ self.client.delete_security_group_default_rule,
+ 'tempest.common.service_client.ServiceClient.delete',
+ {}, status=204, security_group_default_rule_id=1)
diff --git a/tempest/tests/services/compute/test_security_group_rules_client.py b/tempest/tests/services/compute/test_security_group_rules_client.py
new file mode 100644
index 0000000..c182742
--- /dev/null
+++ b/tempest/tests/services/compute/test_security_group_rules_client.py
@@ -0,0 +1,66 @@
+# Copyright 2015 NEC Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.services.compute.json import security_group_rules_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestSecurityGroupRulesClient(base.BaseComputeServiceTest):
+
+ FAKE_SECURITY_GROUP_RULE = {
+ "security_group_rule": {
+ "id": "2d021cf1-ce4b-4292-994f-7a785d62a144",
+ "ip_range": {
+ "cidr": "0.0.0.0/0"
+ },
+ "parent_group_id": "48700ff3-30b8-4e63-845f-a79c9633e9fb",
+ "to_port": 443,
+ "ip_protocol": "tcp",
+ "group": {},
+ "from_port": 443
+ }
+ }
+
+ def setUp(self):
+ super(TestSecurityGroupRulesClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = security_group_rules_client.SecurityGroupRulesClient(
+ fake_auth, 'compute', 'regionOne')
+
+ def _test_create_security_group_rule(self, bytes_body=False):
+ req_body = {
+ "from_port": "443",
+ "ip_protocol": "tcp",
+ "to_port": "443",
+ "cidr": "0.0.0.0/0",
+ "parent_group_id": "48700ff3-30b8-4e63-845f-a79c9633e9fb"
+ }
+ self.check_service_client_function(
+ self.client.create_security_group_rule,
+ 'tempest.common.service_client.ServiceClient.post',
+ self.FAKE_SECURITY_GROUP_RULE,
+ to_utf=bytes_body, **req_body)
+
+ def test_create_security_group_rule_with_str_body(self):
+ self._test_create_security_group_rule()
+
+ def test_create_security_group_rule_with_bytes_body(self):
+ self._test_create_security_group_rule(bytes_body=True)
+
+ def test_delete_security_group_rule(self):
+ self.check_service_client_function(
+ self.client.delete_security_group_rule,
+ 'tempest.common.service_client.ServiceClient.delete',
+ {}, status=202, group_rule_id='group-id')
diff --git a/tempest/tests/services/compute/test_security_groups_client.py b/tempest/tests/services/compute/test_security_groups_client.py
index 7a39048..9e40b96 100644
--- a/tempest/tests/services/compute/test_security_groups_client.py
+++ b/tempest/tests/services/compute/test_security_groups_client.py
@@ -14,9 +14,9 @@
from oslotest import mockpatch
from tempest_lib import exceptions as lib_exc
+from tempest_lib.tests import fake_auth_provider
from tempest.services.compute.json import security_groups_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_server_groups_client.py b/tempest/tests/services/compute/test_server_groups_client.py
new file mode 100644
index 0000000..5e058d6
--- /dev/null
+++ b/tempest/tests/services/compute/test_server_groups_client.py
@@ -0,0 +1,84 @@
+# Copyright 2015 IBM Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import httplib2
+
+from oslotest import mockpatch
+from tempest_lib.tests import fake_auth_provider
+
+from tempest.services.compute.json import server_groups_client
+from tempest.tests.services.compute import base
+
+
+class TestServerGroupsClient(base.BaseComputeServiceTest):
+
+ server_group = {
+ "id": "5bbcc3c4-1da2-4437-a48a-66f15b1b13f9",
+ "name": "test",
+ "policies": ["anti-affinity"],
+ "members": [],
+ "metadata": {}}
+
+ def setUp(self):
+ super(TestServerGroupsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = server_groups_client.ServerGroupsClient(
+ fake_auth, 'compute', 'regionOne')
+
+ def _test_create_server_group(self, bytes_body=False):
+ expected = {"server_group": TestServerGroupsClient.server_group}
+ self.check_service_client_function(
+ self.client.create_server_group,
+ 'tempest.common.service_client.ServiceClient.post', expected,
+ bytes_body, name='fake-group', policies=['affinity'])
+
+ def test_create_server_group_str_body(self):
+ self._test_create_server_group(bytes_body=False)
+
+ def test_create_server_group_byte_body(self):
+ self._test_create_server_group(bytes_body=True)
+
+ def test_delete_server_group(self):
+ response = (httplib2.Response({'status': 204}), None)
+ self.useFixture(mockpatch.Patch(
+ 'tempest.common.service_client.ServiceClient.delete',
+ return_value=response))
+ self.client.delete_server_group('fake-group')
+
+ def _test_list_server_groups(self, bytes_body=False):
+ expected = {"server_groups": [TestServerGroupsClient.server_group]}
+ self.check_service_client_function(
+ self.client.list_server_groups,
+ 'tempest.common.service_client.ServiceClient.get',
+ expected, bytes_body)
+
+ def test_list_server_groups_str_body(self):
+ self._test_list_server_groups(bytes_body=False)
+
+ def test_list_server_groups_byte_body(self):
+ self._test_list_server_groups(bytes_body=True)
+
+ def _test_get_server_group(self, bytes_body=False):
+ expected = {"server_group": TestServerGroupsClient.server_group}
+ self.check_service_client_function(
+ self.client.get_server_group,
+ 'tempest.common.service_client.ServiceClient.get',
+ expected, bytes_body,
+ server_group_id='5bbcc3c4-1da2-4437-a48a-66f15b1b13f9')
+
+ def test_get_server_group_str_body(self):
+ self._test_get_server_group(bytes_body=False)
+
+ def test_get_server_group_byte_body(self):
+ self._test_get_server_group(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_services_client.py b/tempest/tests/services/compute/test_services_client.py
index fe63de9..fce28e8 100644
--- a/tempest/tests/services/compute/test_services_client.py
+++ b/tempest/tests/services/compute/test_services_client.py
@@ -14,8 +14,9 @@
import copy
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import services_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
@@ -81,14 +82,14 @@
fake_service["service"]["status"] = "disable"
self.check_service_client_function(
- self.client.enable_service,
+ self.client.disable_service,
'tempest.common.service_client.ServiceClient.put',
fake_service,
bytes_body,
host_name="nova-conductor", binary="controller")
def test_disable_service_with_str_body(self):
- self._test_enable_service()
+ self._test_disable_service()
def test_disable_service_with_bytes_body(self):
- self._test_enable_service(bytes_body=True)
+ self._test_disable_service(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_tenant_networks_client.py b/tempest/tests/services/compute/test_tenant_networks_client.py
index dc2de00..691792a 100644
--- a/tempest/tests/services/compute/test_tenant_networks_client.py
+++ b/tempest/tests/services/compute/test_tenant_networks_client.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import tenant_networks_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_tenant_usages_client.py b/tempest/tests/services/compute/test_tenant_usages_client.py
index 8a2c1a4..58e0b7a 100644
--- a/tempest/tests/services/compute/test_tenant_usages_client.py
+++ b/tempest/tests/services/compute/test_tenant_usages_client.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib.tests import fake_auth_provider
+
from tempest.services.compute.json import tenant_usages_client
-from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
diff --git a/tempest/tests/services/compute/test_volumes_extensions_client.py b/tempest/tests/services/compute/test_volumes_extensions_client.py
new file mode 100644
index 0000000..2fe8497
--- /dev/null
+++ b/tempest/tests/services/compute/test_volumes_extensions_client.py
@@ -0,0 +1,114 @@
+# Copyright 2015 NEC Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import copy
+
+from oslotest import mockpatch
+from tempest_lib import exceptions as lib_exc
+
+from tempest.services.compute.json import volumes_extensions_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestVolumesExtensionsClient(base.BaseComputeServiceTest):
+
+ FAKE_VOLUME = {
+ "id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+ "displayName": u"v\u12345ol-001",
+ "displayDescription": u"Another \u1234volume.",
+ "size": 30,
+ "status": "Active",
+ "volumeType": "289da7f8-6440-407c-9fb4-7db01ec49164",
+ "metadata": {
+ "contents": "junk"
+ },
+ "availabilityZone": "us-east1",
+ "snapshotId": None,
+ "attachments": [],
+ "createdAt": "2012-02-14T20:53:07Z"
+ }
+
+ FAKE_VOLUMES = {"volumes": [FAKE_VOLUME]}
+
+ def setUp(self):
+ super(TestVolumesExtensionsClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = volumes_extensions_client.VolumesExtensionsClient(
+ fake_auth, 'compute', 'regionOne')
+
+ def _test_list_volumes(self, bytes_body=False, **params):
+ self.check_service_client_function(
+ self.client.list_volumes,
+ 'tempest.common.service_client.ServiceClient.get',
+ self.FAKE_VOLUMES, to_utf=bytes_body, **params)
+
+ def test_list_volumes_with_str_body(self):
+ self._test_list_volumes()
+
+ def test_list_volumes_with_byte_body(self):
+ self._test_list_volumes(bytes_body=True)
+
+ def test_list_volumes_with_params(self):
+ self._test_list_volumes(name='fake')
+
+ def _test_show_volume(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_volume,
+ 'tempest.common.service_client.ServiceClient.get',
+ {"volume": self.FAKE_VOLUME},
+ to_utf=bytes_body, volume_id=self.FAKE_VOLUME['id'])
+
+ def test_show_volume_with_str_body(self):
+ self._test_show_volume()
+
+ def test_show_volume_with_bytes_body(self):
+ self._test_show_volume(bytes_body=True)
+
+ def _test_create_volume(self, bytes_body=False):
+ post_body = copy.deepcopy(self.FAKE_VOLUME)
+ del post_body['id']
+ del post_body['createdAt']
+ del post_body['status']
+ self.check_service_client_function(
+ self.client.create_volume,
+ 'tempest.common.service_client.ServiceClient.post',
+ {"volume": self.FAKE_VOLUME},
+ to_utf=bytes_body, status=200, **post_body)
+
+ def test_create_volume_with_str_body(self):
+ self._test_create_volume()
+
+ def test_create_volume_with_bytes_body(self):
+ self._test_create_volume(bytes_body=True)
+
+ def test_delete_volume(self):
+ self.check_service_client_function(
+ self.client.delete_volume,
+ 'tempest.common.service_client.ServiceClient.delete',
+ {}, status=202, volume_id=self.FAKE_VOLUME['id'])
+
+ def test_is_resource_deleted_true(self):
+ module = ('tempest.services.compute.json.volumes_extensions_client.'
+ 'VolumesExtensionsClient.show_volume')
+ self.useFixture(mockpatch.Patch(
+ module, side_effect=lib_exc.NotFound))
+ self.assertTrue(self.client.is_resource_deleted('fake-id'))
+
+ def test_is_resource_deleted_false(self):
+ module = ('tempest.services.compute.json.volumes_extensions_client.'
+ 'VolumesExtensionsClient.show_volume')
+ self.useFixture(mockpatch.Patch(
+ module, return_value={}))
+ self.assertFalse(self.client.is_resource_deleted('fake-id'))
diff --git a/tempest/tests/test_tempest_plugin.py b/tempest/tests/test_tempest_plugin.py
new file mode 100644
index 0000000..c07e98c
--- /dev/null
+++ b/tempest/tests/test_tempest_plugin.py
@@ -0,0 +1,44 @@
+# Copyright (c) 2015 Deutsche Telekom AG
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.test_discover import plugins
+from tempest.tests import base
+from tempest.tests import fake_tempest_plugin as fake_plugin
+
+
+class TestPluginDiscovery(base.TestCase):
+ def test_load_tests_with_one_plugin(self):
+ # we can't mock stevedore since it's a singleton and already executed
+ # during test discovery. So basically this test covers the plugin loop
+ # and the abstract plugin interface.
+ manager = plugins.TempestTestPluginManager()
+ fake_obj = fake_plugin.FakeStevedoreObj()
+ manager.ext_plugins = [fake_obj]
+ result = manager.get_plugin_load_tests_tuple()
+
+ self.assertEqual(fake_plugin.FakePlugin.expected_load_test,
+ result[fake_obj.name])
+
+ def test_load_tests_with_two_plugins(self):
+ manager = plugins.TempestTestPluginManager()
+ obj1 = fake_plugin.FakeStevedoreObj('fake01')
+ obj2 = fake_plugin.FakeStevedoreObj('fake02')
+ manager.ext_plugins = [obj1, obj2]
+ result = manager.get_plugin_load_tests_tuple()
+
+ self.assertEqual(fake_plugin.FakePlugin.expected_load_test,
+ result['fake01'])
+ self.assertEqual(fake_plugin.FakePlugin.expected_load_test,
+ result['fake02'])