Merge "Set default value for tempest log file"
diff --git a/HACKING.rst b/HACKING.rst
index 9f7487d..0962f80 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -330,24 +330,25 @@
# The created server should be in the detailed list of all servers
...
-Tempest includes a ``check_uuid.py`` tool that will test for the existence
-and uniqueness of idempotent_id metadata for every test. By default the
-tool runs against the Tempest package by calling::
+Tempest-lib includes a ``check-uuid`` tool that will test for the existence
+and uniqueness of idempotent_id metadata for every test. If you have
+tempest-lib installed you run the tool against Tempest by calling from the
+tempest repo::
- python check_uuid.py
+ check-uuid
It can be invoked against any test suite by passing a package name::
- python check_uuid.py --package <package_name>
+ check-uuid --package <package_name>
Tests without an ``idempotent_id`` can be automatically fixed by running
the command with the ``--fix`` flag, which will modify the source package
by inserting randomly generated uuids for every test that does not have
one::
- python check_uuid.py --fix
+ check-uuid --fix
-The ``check_uuid.py`` tool is used as part of the tempest gate job
+The ``check-uuid`` tool is used as part of the tempest gate job
to ensure that all tests have an ``idempotent_id`` decorator.
Branchless Tempest Considerations
diff --git a/requirements.txt b/requirements.txt
index 370bb65..d470c30 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,7 +2,7 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
pbr>=1.6
-cliff>=1.14.0 # Apache-2.0
+cliff>=1.15.0 # Apache-2.0
anyjson>=0.3.3
httplib2>=0.7.5
jsonschema!=2.5.0,<3.0.0,>=2.0.0
@@ -13,15 +13,15 @@
testrepository>=0.0.18
pyOpenSSL>=0.14
oslo.concurrency>=2.3.0 # Apache-2.0
-oslo.config>=2.6.0 # Apache-2.0
+oslo.config>=2.7.0 # Apache-2.0
oslo.i18n>=1.5.0 # Apache-2.0
oslo.log>=1.12.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
-oslo.utils!=2.6.0,>=2.4.0 # Apache-2.0
+oslo.utils>=2.8.0 # Apache-2.0
six>=1.9.0
iso8601>=0.1.9
fixtures>=1.3.1
testscenarios>=0.4
-tempest-lib>=0.10.0
+tempest-lib>=0.11.0
PyYAML>=3.1.0
stevedore>=1.5.0 # Apache-2.0
diff --git a/run_tempest.sh b/run_tempest.sh
index 0f32045..a704684 100755
--- a/run_tempest.sh
+++ b/run_tempest.sh
@@ -104,9 +104,9 @@
fi
if [ $serial -eq 1 ]; then
- ${wrapper} testr run --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
+ ${wrapper} testr run --subunit $testrargs | ${wrapper} subunit-trace -n -f
else
- ${wrapper} testr run --parallel --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
+ ${wrapper} testr run --parallel --subunit $testrargs | ${wrapper} subunit-trace -n -f
fi
}
diff --git a/run_tests.sh b/run_tests.sh
index 9a158e4..908056f 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -90,9 +90,9 @@
fi
if [ $serial -eq 1 ]; then
- ${wrapper} testr run --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
+ ${wrapper} testr run --subunit $testrargs | ${wrapper} subunit-trace -n -f
else
- ${wrapper} testr run --parallel --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
+ ${wrapper} testr run --parallel --subunit $testrargs | ${wrapper} subunit-trace -n -f
fi
}
diff --git a/setup.cfg b/setup.cfg
index ee61788..4415063 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -35,6 +35,7 @@
tempest.cm =
init = tempest.cmd.init:TempestInit
cleanup = tempest.cmd.cleanup:TempestCleanup
+ run-stress = tempest.cmd.run_stress:TempestRunStress
oslo.config.opts =
tempest.config = tempest.config:list_opts
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index fa1c666..2907e26 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -111,7 +111,7 @@
# 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')
+ password = data_utils.rand_password()
email = user_name + '@testmail.tm'
user = self.identity_utils.create_user(username=user_name,
password=password,
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index b0a3086..e31129b 100644
--- a/tempest/api/compute/admin/test_security_groups.py
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -28,7 +28,7 @@
@classmethod
def setup_clients(cls):
super(SecurityGroupsTestAdminJSON, cls).setup_clients()
- cls.adm_client = cls.os_adm.security_groups_client
+ cls.adm_client = cls.os_adm.compute_security_groups_client
cls.client = cls.security_groups_client
def _delete_security_group(self, securitygroup_id, admin=True):
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index 993d39e..fd6f105 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -130,7 +130,7 @@
@test.idempotent_id('ee8ae470-db70-474d-b752-690b7892cab1')
def test_reset_state_server(self):
# Reset server's state to 'error'
- self.client.reset_state(self.s1_id)
+ self.client.reset_state(self.s1_id, state='error')
# Verify server's state
server = self.client.show_server(self.s1_id)['server']
@@ -147,7 +147,7 @@
@test.idempotent_id('31ff3486-b8a0-4f56-a6c0-aab460531db3')
def test_get_server_diagnostics_by_admin(self):
# Retrieve server diagnostics by admin user
- diagnostic = self.client.get_server_diagnostics(self.s1_id)
+ diagnostic = self.client.show_server_diagnostics(self.s1_id)
basic_attrs = ['rx_packets', 'rx_errors', 'rx_drop',
'tx_packets', 'tx_errors', 'tx_drop',
'read_req', 'write_req', 'cpu', 'memory']
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index 3d0ce35..055dc1b 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -123,14 +123,14 @@
@test.idempotent_id('e741298b-8df2-46f0-81cb-8f814ff2504c')
def test_reset_state_server_nonexistent_server(self):
self.assertRaises(lib_exc.NotFound,
- self.client.reset_state, '999')
+ self.client.reset_state, '999', state='error')
@test.attr(type=['negative'])
@test.idempotent_id('e84e2234-60d2-42fa-8b30-e2d3049724ac')
def test_get_server_diagnostics_by_non_admin(self):
# Non-admin user can not view server diagnostics according to policy
self.assertRaises(lib_exc.Forbidden,
- self.non_adm_client.get_server_diagnostics,
+ self.non_adm_client.show_server_diagnostics,
self.s1_id)
@test.attr(type=['negative'])
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index a5c0600..2321b4e 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -18,6 +18,7 @@
from oslo_log import log as logging
from tempest_lib import exceptions as lib_exc
+from tempest.common import api_version_utils
from tempest.common import compute
from tempest.common.utils import data_utils
from tempest.common import waiters
@@ -29,7 +30,8 @@
LOG = logging.getLogger(__name__)
-class BaseV2ComputeTest(tempest.test.BaseTestCase):
+class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
+ tempest.test.BaseTestCase):
"""Base test case class for all Compute API tests."""
force_tenant_isolation = False
@@ -43,6 +45,12 @@
super(BaseV2ComputeTest, cls).skip_checks()
if not CONF.service_available.nova:
raise cls.skipException("Nova is not available")
+ cfg_min_version = CONF.compute_feature_enabled.min_microversion
+ cfg_max_version = CONF.compute_feature_enabled.max_microversion
+ api_version_utils.check_skip_with_microversion(cls.min_microversion,
+ cls.max_microversion,
+ cfg_min_version,
+ cfg_max_version)
@classmethod
def setup_credentials(cls):
@@ -61,7 +69,7 @@
cls.floating_ips_client = cls.os.compute_floating_ips_client
cls.keypairs_client = cls.os.keypairs_client
cls.security_group_rules_client = cls.os.security_group_rules_client
- cls.security_groups_client = cls.os.security_groups_client
+ cls.security_groups_client = cls.os.compute_security_groups_client
cls.quotas_client = cls.os.quotas_client
cls.quota_classes_client = cls.os.quota_classes_client
cls.compute_networks_client = cls.os.compute_networks_client
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
index 64aac80..0223c0d 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
@@ -60,7 +60,7 @@
# to a project should fail
self.assertRaises(lib_exc.NotFound,
self.client.create_floating_ip,
- "non_exist_pool")
+ pool="non_exist_pool")
@test.attr(type=['negative'])
@test.idempotent_id('ae1c55a8-552b-44d4-bfb6-2a115a15d0ba')
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index dbbeb70..81a02be 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -100,7 +100,7 @@
server_id = server['id']
waiters.wait_for_server_status(self.servers_client, server_id,
'ACTIVE')
- self.servers_client.add_security_group(server_id, sg['name'])
+ self.servers_client.add_security_group(server_id, name=sg['name'])
# Check that we are not able to delete the security
# group since it is in use by an active server
@@ -109,10 +109,10 @@
sg['id'])
# Reboot and add the other security group
- self.servers_client.reboot_server(server_id, 'HARD')
+ self.servers_client.reboot_server(server_id, type='HARD')
waiters.wait_for_server_status(self.servers_client, server_id,
'ACTIVE')
- self.servers_client.add_security_group(server_id, sg2['name'])
+ self.servers_client.add_security_group(server_id, name=sg2['name'])
# Check that we are not able to delete the other security
# group since it is in use by an active server
diff --git a/tempest/api/compute/servers/test_instance_actions.py b/tempest/api/compute/servers/test_instance_actions.py
index 97d47fd..1367629 100644
--- a/tempest/api/compute/servers/test_instance_actions.py
+++ b/tempest/api/compute/servers/test_instance_actions.py
@@ -35,7 +35,7 @@
@test.idempotent_id('77ca5cc5-9990-45e0-ab98-1de8fead201a')
def test_list_instance_actions(self):
# List actions of the provided server
- self.client.reboot_server(self.server_id, 'HARD')
+ self.client.reboot_server(self.server_id, type='HARD')
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
body = (self.client.list_instance_actions(self.server_id)
@@ -47,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(
+ body = self.client.show_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_instance_actions_negative.py b/tempest/api/compute/servers/test_instance_actions_negative.py
index 6567da1..ac66d05 100644
--- a/tempest/api/compute/servers/test_instance_actions_negative.py
+++ b/tempest/api/compute/servers/test_instance_actions_negative.py
@@ -46,5 +46,5 @@
@test.idempotent_id('0269f40a-6f18-456c-b336-c03623c897f1')
def test_get_instance_action_invalid_request(self):
# Get the action details of the provided server with invalid request
- self.assertRaises(lib_exc.NotFound, self.client.get_instance_action,
+ self.assertRaises(lib_exc.NotFound, self.client.show_instance_action,
self.server_id, '999')
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 0754d27..71dfd96 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -81,7 +81,7 @@
def test_change_server_password(self):
# The server's password should be set to the provided password
new_password = 'Newpass1234'
- self.client.change_password(self.server_id, new_password)
+ self.client.change_password(self.server_id, adminPass=new_password)
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
if CONF.validation.run_validation:
@@ -104,7 +104,7 @@
self.validation_resources['keypair']['private_key'])
boot_time = linux_client.get_boot_time()
- self.client.reboot_server(self.server_id, reboot_type)
+ self.client.reboot_server(self.server_id, type=reboot_type)
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
if CONF.validation.run_validation:
@@ -279,9 +279,9 @@
# create the first and the second backup
backup1 = data_utils.rand_name('backup-1')
resp = self.client.create_backup(self.server_id,
- 'daily',
- 2,
- backup1).response
+ backup_type='daily',
+ rotation=2,
+ name=backup1).response
oldest_backup_exist = True
# the oldest one should be deleted automatically in this test
@@ -303,9 +303,9 @@
backup2 = data_utils.rand_name('backup-2')
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
resp = self.client.create_backup(self.server_id,
- 'daily',
- 2,
- backup2).response
+ backup_type='daily',
+ rotation=2,
+ name=backup2).response
image2_id = data_utils.parse_image_id(resp['location'])
self.addCleanup(self.os.image_client.delete_image, image2_id)
self.os.image_client.wait_for_image_status(image2_id, 'active')
@@ -331,9 +331,9 @@
backup3 = data_utils.rand_name('backup-3')
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
resp = self.client.create_backup(self.server_id,
- 'daily',
- 2,
- backup3).response
+ backup_type='daily',
+ rotation=2,
+ name=backup3).response
image3_id = data_utils.parse_image_id(resp['location'])
self.addCleanup(self.os.image_client.delete_image, image3_id)
# the first back up should be deleted
@@ -356,7 +356,7 @@
def _get_output(self):
output = self.client.get_console_output(
- self.server_id, 10)['output']
+ self.server_id, length=10)['output']
self.assertTrue(output, "Console output was empty.")
lines = len(output.split('\n'))
self.assertEqual(lines, 10)
@@ -373,7 +373,7 @@
# log file is truncated and we cannot get any console log through
# "console-log" API.
# The detail is https://bugs.launchpad.net/nova/+bug/1251920
- self.client.reboot_server(self.server_id, 'HARD')
+ self.client.reboot_server(self.server_id, type='HARD')
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
self.wait_for(self._get_output)
@@ -384,8 +384,7 @@
server = self.create_test_server(wait_until='ACTIVE')
def _check_full_length_console_log():
- output = self.client.get_console_output(server['id'],
- None)['output']
+ output = self.client.get_console_output(server['id'])['output']
self.assertTrue(output, "Console output was empty.")
lines = len(output.split('\n'))
@@ -499,7 +498,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_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_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index 77ddb3b..9c07677 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -87,8 +87,8 @@
@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']
+ meta = self.client.show_server_metadata_item(self.server_id,
+ 'key2')['meta']
self.assertEqual('value2', meta['key2'])
@test.idempotent_id('58c02d4f-5c67-40be-8744-d3fa5982eb1c')
diff --git a/tempest/api/compute/servers/test_server_metadata_negative.py b/tempest/api/compute/servers/test_server_metadata_negative.py
index cee60fb..18d80be 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.py
@@ -67,7 +67,7 @@
# GET on a non-existent server should not succeed
non_existent_server_id = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound,
- self.client.get_server_metadata_item,
+ self.client.show_server_metadata_item,
non_existent_server_id,
'test2')
diff --git a/tempest/api/compute/servers/test_server_password.py b/tempest/api/compute/servers/test_server_password.py
index 35c2cfd..9b41708 100644
--- a/tempest/api/compute/servers/test_server_password.py
+++ b/tempest/api/compute/servers/test_server_password.py
@@ -32,7 +32,7 @@
@test.idempotent_id('f83b582f-62a8-4f22-85b0-0dee50ff783a')
def test_get_server_password(self):
- self.client.get_password(self.server['id'])
+ self.client.show_password(self.server['id'])
@test.idempotent_id('f8229e8b-b625-4493-800a-bde86ac611ea')
def test_delete_server_password(self):
diff --git a/tempest/api/compute/servers/test_server_personality.py b/tempest/api/compute/servers/test_server_personality.py
index 77af509..58d26d3 100644
--- a/tempest/api/compute/servers/test_server_personality.py
+++ b/tempest/api/compute/servers/test_server_personality.py
@@ -17,6 +17,8 @@
from tempest_lib import exceptions as lib_exc
from tempest.api.compute import base
+from tempest.common.utils.linux import remote_client
+from tempest.common import waiters
from tempest import config
from tempest import test
@@ -26,6 +28,16 @@
class ServerPersonalityTestJSON(base.BaseV2ComputeTest):
@classmethod
+ def setup_credentials(cls):
+ cls.prepare_instance_network()
+ super(ServerPersonalityTestJSON, cls).setup_credentials()
+
+ @classmethod
+ def resource_setup(cls):
+ cls.set_validation_resources()
+ super(ServerPersonalityTestJSON, cls).resource_setup()
+
+ @classmethod
def skip_checks(cls):
super(ServerPersonalityTestJSON, cls).skip_checks()
if not CONF.compute_feature_enabled.personality:
@@ -40,18 +52,34 @@
@test.idempotent_id('3cfe87fd-115b-4a02-b942-7dc36a337fdf')
def test_create_server_with_personality(self):
file_contents = 'This is a test file.'
- personality = [{'path': '/test.txt',
+ file_path = '/test.txt'
+ personality = [{'path': file_path,
'contents': base64.b64encode(file_contents)}]
- self.create_test_server(personality=personality)
+ server = self.create_test_server(personality=personality,
+ wait_until='ACTIVE',
+ validatable=True)
+ if CONF.validation.run_validation:
+ linux_client = remote_client.RemoteClient(
+ self.get_server_ip(server),
+ self.ssh_user, server['adminPass'],
+ self.validation_resources['keypair']['private_key'])
+ self.assertEqual(file_contents,
+ linux_client.exec_command(
+ 'sudo cat %s' % file_path))
@test.idempotent_id('128966d8-71fc-443c-8cab-08e24114ecc9')
def test_rebuild_server_with_personality(self):
- server_id = self.rebuild_server(None)
+ server = self.create_test_server(wait_until='ACTIVE', validatable=True)
+ server_id = server['id']
file_contents = 'Test server rebuild.'
personality = [{'path': 'rebuild.txt',
'contents': base64.b64encode(file_contents)}]
- self.client.rebuild_server(server_id, self.image_ref_alt,
- personality=personality)
+ rebuilt_server = self.client.rebuild_server(server_id,
+ self.image_ref_alt,
+ personality=personality)
+ waiters.wait_for_server_status(self.client, server_id, 'ACTIVE')
+ self.assertEqual(self.image_ref_alt,
+ rebuilt_server['server']['image']['id'])
@test.idempotent_id('176cd8c9-b9e8-48ee-a480-180beab292bf')
def test_personality_files_exceed_limit(self):
@@ -83,9 +111,20 @@
raise self.skipException("No limit for personality files")
person = []
for i in range(0, int(max_file_limit)):
- path = 'etc/test' + str(i) + '.txt'
+ path = '/etc/test' + str(i) + '.txt'
person.append({
'path': path,
'contents': base64.b64encode(file_contents),
})
- self.create_test_server(personality=person)
+ server = self.create_test_server(personality=person,
+ wait_until='ACTIVE',
+ validatable=True)
+ if CONF.validation.run_validation:
+ linux_client = remote_client.RemoteClient(
+ self.get_server_ip(server),
+ self.ssh_user, server['adminPass'],
+ self.validation_resources['keypair']['private_key'])
+ for i in person:
+ self.assertEqual(base64.b64decode(i['contents']),
+ linux_client.exec_command(
+ 'sudo cat %s' % i['path']))
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 96ce45e..2296980 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -116,8 +116,9 @@
self.addCleanup(self._unrescue, self.server_id)
# Add Security group
- self.servers_client.add_security_group(self.server_id, self.sg_name)
+ self.servers_client.add_security_group(self.server_id,
+ name=self.sg_name)
# Delete Security group
self.servers_client.remove_security_group(self.server_id,
- self.sg_name)
+ name=self.sg_name)
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index f8567cf..65ad2f5 100644
--- a/tempest/api/compute/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/servers/test_server_rescue_negative.py
@@ -101,7 +101,7 @@
@test.idempotent_id('db22b618-f157-4566-a317-1b6d467a8094')
def test_rescued_vm_reboot(self):
self.assertRaises(lib_exc.Conflict, self.servers_client.reboot_server,
- self.rescue_id, 'HARD')
+ self.rescue_id, type='HARD')
@test.attr(type=['negative'])
@test.idempotent_id('6dfc0a55-3a77-4564-a144-1587b7971dde')
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index d2fb652..8e2fbf1 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -71,9 +71,10 @@
server = self.client.show_server(server['id'])['server']
self.assertEqual(key_name, server['key_name'])
- def _update_server_name(self, server_id, status):
+ def _update_server_name(self, server_id, status, prefix_name='server'):
# The server name should be changed to the the provided value
- new_name = data_utils.rand_name('server')
+ new_name = data_utils.rand_name(prefix_name)
+
# Update the server with a new name
self.client.update_server(server_id,
name=new_name)
@@ -88,8 +89,9 @@
def test_update_server_name(self):
# The server name should be changed to the the provided value
server = self.create_test_server(wait_until='ACTIVE')
-
- self._update_server_name(server['id'], 'ACTIVE')
+ # Update instance name with non-ASCII characters
+ prefix_name = u'\u00CD\u00F1st\u00E1\u00F1c\u00E9'
+ self._update_server_name(server['id'], 'ACTIVE', prefix_name)
@test.idempotent_id('6ac19cb1-27a3-40ec-b350-810bdc04c08e')
def test_update_server_name_in_stop_state(self):
@@ -97,7 +99,11 @@
server = self.create_test_server(wait_until='ACTIVE')
self.client.stop_server(server['id'])
waiters.wait_for_server_status(self.client, server['id'], 'SHUTOFF')
- updated_server = self._update_server_name(server['id'], 'SHUTOFF')
+ # Update instance name with non-ASCII characters
+ prefix_name = u'\u00CD\u00F1st\u00E1\u00F1c\u00E9'
+ updated_server = self._update_server_name(server['id'],
+ 'SHUTOFF',
+ prefix_name)
self.assertNotIn('progress', updated_server)
@test.idempotent_id('89b90870-bc13-4b73-96af-f9d4f2b70077')
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 98b292a..ed8484e 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -152,7 +152,7 @@
# Reboot a non existent server
nonexistent_server = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound, self.client.reboot_server,
- nonexistent_server, 'SOFT')
+ nonexistent_server, type='SOFT')
@test.idempotent_id('d1417e7f-a509-41b5-a102-d5eed8613369')
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
@@ -169,8 +169,8 @@
@test.attr(type=['negative'])
@test.idempotent_id('98fa0458-1485-440f-873b-fe7f0d714930')
- def test_rebuild_reboot_deleted_server(self):
- # Rebuild and Reboot a deleted server
+ def test_rebuild_deleted_server(self):
+ # Rebuild a deleted server
server = self.create_test_server()
self.client.delete_server(server['id'])
waiters.wait_for_server_termination(self.client, server['id'])
@@ -178,8 +178,17 @@
self.assertRaises(lib_exc.NotFound,
self.client.rebuild_server,
server['id'], self.image_ref_alt)
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('581a397d-5eab-486f-9cf9-1014bbd4c984')
+ def test_reboot_deleted_server(self):
+ # Reboot a deleted server
+ server = self.create_test_server()
+ self.client.delete_server(server['id'])
+ waiters.wait_for_server_termination(self.client, server['id'])
+
self.assertRaises(lib_exc.NotFound, self.client.reboot_server,
- server['id'], 'SOFT')
+ server['id'], type='SOFT')
@test.attr(type=['negative'])
@test.idempotent_id('d86141a7-906e-4731-b187-d64a2ea61422')
@@ -421,7 +430,7 @@
nonexistent_server = data_utils.rand_uuid()
self.assertRaises(lib_exc.NotFound,
self.client.get_console_output,
- nonexistent_server, 10)
+ nonexistent_server, length=10)
@test.attr(type=['negative'])
@test.idempotent_id('6f47992b-5144-4250-9f8b-f00aa33950f3')
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index f8d0cca..e363fc4 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -51,13 +51,14 @@
cls.images_client = cls.os.images_client
cls.glance_client = cls.os.image_client
cls.keypairs_client = cls.os.keypairs_client
- cls.security_client = cls.os.security_groups_client
+ cls.security_client = cls.os.compute_security_groups_client
cls.rule_client = cls.os.security_group_rules_client
cls.alt_client = cls.alt_manager.servers_client
cls.alt_images_client = cls.alt_manager.images_client
cls.alt_keypairs_client = cls.alt_manager.keypairs_client
- cls.alt_security_client = cls.alt_manager.security_groups_client
+ cls.alt_security_client = (
+ cls.alt_manager.compute_security_groups_client)
cls.alt_rule_client = cls.alt_manager.security_group_rules_client
@classmethod
@@ -150,13 +151,13 @@
def test_change_password_for_alt_account_fails(self):
# A change password request for another user's server should fail
self.assertRaises(lib_exc.NotFound, self.alt_client.change_password,
- self.server['id'], 'newpass')
+ self.server['id'], adminPass='newpass')
@test.idempotent_id('14cb5ff5-f646-45ca-8f51-09081d6c0c24')
def test_reboot_server_for_alt_account_fails(self):
# A reboot request for another user's server should fail
self.assertRaises(lib_exc.NotFound, self.alt_client.reboot_server,
- self.server['id'], 'HARD')
+ self.server['id'], type='HARD')
@test.idempotent_id('8a0bce51-cd00-480b-88ba-dbc7d8408a37')
def test_rebuild_server_for_alt_account_fails(self):
@@ -400,7 +401,7 @@
self.addCleanup(self.client.delete_server_metadata_item,
self.server['id'], 'meta1')
self.assertRaises(lib_exc.NotFound,
- self.alt_client.get_server_metadata_item,
+ self.alt_client.show_server_metadata_item,
self.server['id'], 'meta1')
@test.idempotent_id('16b2d724-0d3b-4216-a9fa-97bd4d9cf670')
@@ -443,4 +444,4 @@
# A Get Console Output for another user's server should fail
self.assertRaises(lib_exc.NotFound,
self.alt_client.get_console_output,
- self.server['id'], 10)
+ self.server['id'], length=10)
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index ab4ddf7..b4837f7 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -144,7 +144,7 @@
self.assertIn(self.attachment, body)
# Get Volume attachment of the server
- body = self.servers_client.get_volume_attachment(
+ body = self.servers_client.show_volume_attachment(
self.server['id'],
self.attachment['id'])['volumeAttachment']
self.assertEqual(self.server['id'], body['serverId'])
diff --git a/tempest/api/database/flavors/test_flavors.py b/tempest/api/database/flavors/test_flavors.py
index 62c1e05..f75b867 100644
--- a/tempest/api/database/flavors/test_flavors.py
+++ b/tempest/api/database/flavors/test_flavors.py
@@ -28,7 +28,7 @@
@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.show_db_flavor(self.db_flavor_ref)
['flavor'])
self.assertEqual(self.db_flavor_ref, str(flavor['id']))
self.assertIn('ram', flavor)
@@ -38,7 +38,7 @@
@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.show_db_flavor(self.db_flavor_ref)
['flavor'])
# List of all flavors should contain the expected flavor
flavors = self.client.list_db_flavors()['flavors']
@@ -67,7 +67,7 @@
(os_flavors, db_flavors))
for os_flavor in os_flavors:
db_flavor =\
- self.client.get_db_flavor_details(os_flavor['id'])['flavor']
+ self.client.show_db_flavor(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/database/flavors/test_flavors_negative.py b/tempest/api/database/flavors/test_flavors_negative.py
index 68cb7d6..3dee96f 100644
--- a/tempest/api/database/flavors/test_flavors_negative.py
+++ b/tempest/api/database/flavors/test_flavors_negative.py
@@ -31,4 +31,4 @@
def test_get_non_existent_db_flavor(self):
# flavor details are not returned for non-existent flavors
self.assertRaises(lib_exc.NotFound,
- self.client.get_db_flavor_details, -1)
+ self.client.show_db_flavor, -1)
diff --git a/tempest/api/identity/admin/v2/test_roles.py b/tempest/api/identity/admin/v2/test_roles.py
index 657d72e..8702db7 100644
--- a/tempest/api/identity/admin/v2/test_roles.py
+++ b/tempest/api/identity/admin/v2/test_roles.py
@@ -95,7 +95,7 @@
user_role = self.client.assign_user_role(tenant['id'],
user['id'],
role['id'])['role']
- self.client.remove_user_role(tenant['id'], user['id'],
+ self.client.delete_user_role(tenant['id'], user['id'],
user_role['id'])
@test.idempotent_id('262e1e3e-ed71-4edd-a0e5-d64e83d66d05')
diff --git a/tempest/api/identity/admin/v2/test_roles_negative.py b/tempest/api/identity/admin/v2/test_roles_negative.py
index 5932aba..45c95df 100644
--- a/tempest/api/identity/admin/v2/test_roles_negative.py
+++ b/tempest/api/identity/admin/v2/test_roles_negative.py
@@ -177,7 +177,7 @@
user['id'],
role['id'])
self.assertRaises(lib_exc.Forbidden,
- self.non_admin_client.remove_user_role,
+ self.non_admin_client.delete_user_role,
tenant['id'], user['id'], role['id'])
@test.attr(type=['negative'])
@@ -191,7 +191,7 @@
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
self.assertRaises(lib_exc.Unauthorized,
- self.client.remove_user_role, tenant['id'],
+ self.client.delete_user_role, tenant['id'],
user['id'], role['id'])
self.client.auth_provider.clear_auth()
@@ -204,7 +204,7 @@
user['id'],
role['id'])
non_existent_role = str(uuid.uuid4().hex)
- self.assertRaises(lib_exc.NotFound, self.client.remove_user_role,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_user_role,
tenant['id'], user['id'], non_existent_role)
@test.attr(type=['negative'])
@@ -216,7 +216,7 @@
user['id'],
role['id'])
non_existent_tenant = str(uuid.uuid4().hex)
- self.assertRaises(lib_exc.NotFound, self.client.remove_user_role,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_user_role,
non_existent_tenant, user['id'], role['id'])
@test.attr(type=['negative'])
diff --git a/tempest/api/identity/admin/v2/test_tenant_negative.py b/tempest/api/identity/admin/v2/test_tenant_negative.py
index 74558d1..a02dbc1 100644
--- a/tempest/api/identity/admin/v2/test_tenant_negative.py
+++ b/tempest/api/identity/admin/v2/test_tenant_negative.py
@@ -29,7 +29,7 @@
def test_list_tenants_by_unauthorized_user(self):
# Non-administrator user should not be able to list tenants
self.assertRaises(lib_exc.Forbidden,
- self.non_admin_client.list_tenants)
+ self.non_admin_tenants_client.list_tenants)
@test.attr(type=['negative'])
@test.idempotent_id('df33926c-1c96-4d8d-a762-79cc6b0c3cf4')
@@ -37,7 +37,8 @@
# Request to list tenants without a valid token should fail
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(lib_exc.Unauthorized, self.client.list_tenants)
+ self.assertRaises(lib_exc.Unauthorized,
+ self.tenants_client.list_tenants)
self.client.auth_provider.clear_auth()
@test.attr(type=['negative'])
@@ -45,21 +46,23 @@
def test_tenant_delete_by_unauthorized_user(self):
# Non-administrator user should not be able to delete a tenant
tenant_name = data_utils.rand_name(name='tenant')
- tenant = self.client.create_tenant(tenant_name)['tenant']
+ tenant = self.tenants_client.create_tenant(tenant_name)['tenant']
self.data.tenants.append(tenant)
self.assertRaises(lib_exc.Forbidden,
- self.non_admin_client.delete_tenant, tenant['id'])
+ self.non_admin_tenants_client.delete_tenant,
+ tenant['id'])
@test.attr(type=['negative'])
@test.idempotent_id('e450db62-2e9d-418f-893a-54772d6386b1')
def test_tenant_delete_request_without_token(self):
# Request to delete a tenant without a valid token should fail
tenant_name = data_utils.rand_name(name='tenant')
- tenant = self.client.create_tenant(tenant_name)['tenant']
+ tenant = self.tenants_client.create_tenant(tenant_name)['tenant']
self.data.tenants.append(tenant)
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(lib_exc.Unauthorized, self.client.delete_tenant,
+ self.assertRaises(lib_exc.Unauthorized,
+ self.tenants_client.delete_tenant,
tenant['id'])
self.client.auth_provider.clear_auth()
@@ -67,7 +70,7 @@
@test.idempotent_id('9c9a2aed-6e3c-467a-8f5c-89da9d1b516b')
def test_delete_non_existent_tenant(self):
# Attempt to delete a non existent tenant should fail
- self.assertRaises(lib_exc.NotFound, self.client.delete_tenant,
+ self.assertRaises(lib_exc.NotFound, self.tenants_client.delete_tenant,
str(uuid.uuid4().hex))
@test.attr(type=['negative'])
@@ -75,14 +78,14 @@
def test_tenant_create_duplicate(self):
# Tenant names should be unique
tenant_name = data_utils.rand_name(name='tenant')
- body = self.client.create_tenant(tenant_name)['tenant']
+ body = self.tenants_client.create_tenant(tenant_name)['tenant']
tenant = body
self.data.tenants.append(tenant)
tenant1_id = body.get('id')
- self.addCleanup(self.client.delete_tenant, tenant1_id)
+ self.addCleanup(self.tenants_client.delete_tenant, tenant1_id)
self.addCleanup(self.data.tenants.remove, tenant)
- self.assertRaises(lib_exc.Conflict, self.client.create_tenant,
+ self.assertRaises(lib_exc.Conflict, self.tenants_client.create_tenant,
tenant_name)
@test.attr(type=['negative'])
@@ -91,7 +94,8 @@
# Non-administrator user should not be authorized to create a tenant
tenant_name = data_utils.rand_name(name='tenant')
self.assertRaises(lib_exc.Forbidden,
- self.non_admin_client.create_tenant, tenant_name)
+ self.non_admin_tenants_client.create_tenant,
+ tenant_name)
@test.attr(type=['negative'])
@test.idempotent_id('a3ee9d7e-6920-4dd5-9321-d4b2b7f0a638')
@@ -100,7 +104,8 @@
tenant_name = data_utils.rand_name(name='tenant')
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(lib_exc.Unauthorized, self.client.create_tenant,
+ self.assertRaises(lib_exc.Unauthorized,
+ self.tenants_client.create_tenant,
tenant_name)
self.client.auth_provider.clear_auth()
@@ -108,7 +113,8 @@
@test.idempotent_id('5a2e4ca9-b0c0-486c-9c48-64a94fba2395')
def test_create_tenant_with_empty_name(self):
# Tenant name should not be empty
- self.assertRaises(lib_exc.BadRequest, self.client.create_tenant,
+ self.assertRaises(lib_exc.BadRequest,
+ self.tenants_client.create_tenant,
name='')
@test.attr(type=['negative'])
@@ -116,14 +122,15 @@
def test_create_tenants_name_length_over_64(self):
# Tenant name length should not be greater than 64 characters
tenant_name = 'a' * 65
- self.assertRaises(lib_exc.BadRequest, self.client.create_tenant,
+ self.assertRaises(lib_exc.BadRequest,
+ self.tenants_client.create_tenant,
tenant_name)
@test.attr(type=['negative'])
@test.idempotent_id('bd20dc2a-9557-4db7-b755-f48d952ad706')
def test_update_non_existent_tenant(self):
# Attempt to update a non existent tenant should fail
- self.assertRaises(lib_exc.NotFound, self.client.update_tenant,
+ self.assertRaises(lib_exc.NotFound, self.tenants_client.update_tenant,
str(uuid.uuid4().hex))
@test.attr(type=['negative'])
@@ -131,20 +138,22 @@
def test_tenant_update_by_unauthorized_user(self):
# Non-administrator user should not be able to update a tenant
tenant_name = data_utils.rand_name(name='tenant')
- tenant = self.client.create_tenant(tenant_name)['tenant']
+ tenant = self.tenants_client.create_tenant(tenant_name)['tenant']
self.data.tenants.append(tenant)
self.assertRaises(lib_exc.Forbidden,
- self.non_admin_client.update_tenant, tenant['id'])
+ self.non_admin_tenants_client.update_tenant,
+ tenant['id'])
@test.attr(type=['negative'])
@test.idempotent_id('7a421573-72c7-4c22-a98e-ce539219c657')
def test_tenant_update_request_without_token(self):
# Request to update a tenant without a valid token should fail
tenant_name = data_utils.rand_name(name='tenant')
- tenant = self.client.create_tenant(tenant_name)['tenant']
+ tenant = self.tenants_client.create_tenant(tenant_name)['tenant']
self.data.tenants.append(tenant)
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(lib_exc.Unauthorized, self.client.update_tenant,
+ self.assertRaises(lib_exc.Unauthorized,
+ self.tenants_client.update_tenant,
tenant['id'])
self.client.auth_provider.clear_auth()
diff --git a/tempest/api/identity/admin/v2/test_tenants.py b/tempest/api/identity/admin/v2/test_tenants.py
index 4632b1e..8d0b9b1 100644
--- a/tempest/api/identity/admin/v2/test_tenants.py
+++ b/tempest/api/identity/admin/v2/test_tenants.py
@@ -28,19 +28,19 @@
tenants = []
for _ in moves.xrange(3):
tenant_name = data_utils.rand_name(name='tenant-new')
- tenant = self.client.create_tenant(tenant_name)['tenant']
+ tenant = self.tenants_client.create_tenant(tenant_name)['tenant']
self.data.tenants.append(tenant)
tenants.append(tenant)
tenant_ids = map(lambda x: x['id'], tenants)
- body = self.client.list_tenants()['tenants']
+ body = self.tenants_client.list_tenants()['tenants']
found = [t for t in body if t['id'] in tenant_ids]
self.assertEqual(len(found), len(tenants), 'Tenants not created')
for tenant in tenants:
- self.client.delete_tenant(tenant['id'])
+ self.tenants_client.delete_tenant(tenant['id'])
self.data.tenants.remove(tenant)
- body = self.client.list_tenants()['tenants']
+ body = self.tenants_client.list_tenants()['tenants']
found = [tenant for tenant in body if tenant['id'] in tenant_ids]
self.assertFalse(any(found), 'Tenants failed to delete')
@@ -49,60 +49,60 @@
# Create tenant with a description
tenant_name = data_utils.rand_name(name='tenant')
tenant_desc = data_utils.rand_name(name='desc')
- body = self.client.create_tenant(tenant_name,
- description=tenant_desc)['tenant']
- tenant = body
+ body = self.tenants_client.create_tenant(tenant_name,
+ description=tenant_desc)
+ tenant = body['tenant']
self.data.tenants.append(tenant)
- tenant_id = body['id']
- desc1 = body['description']
+ tenant_id = tenant['id']
+ desc1 = tenant['description']
self.assertEqual(desc1, tenant_desc, 'Description should have '
'been sent in response for create')
- body = self.client.show_tenant(tenant_id)['tenant']
+ body = self.tenants_client.show_tenant(tenant_id)['tenant']
desc2 = body['description']
self.assertEqual(desc2, tenant_desc, 'Description does not appear'
'to be set')
- self.client.delete_tenant(tenant_id)
+ self.tenants_client.delete_tenant(tenant_id)
self.data.tenants.remove(tenant)
@test.idempotent_id('670bdddc-1cd7-41c7-b8e2-751cfb67df50')
def test_tenant_create_enabled(self):
# Create a tenant that is enabled
tenant_name = data_utils.rand_name(name='tenant')
- body = self.client.create_tenant(tenant_name, enabled=True)['tenant']
- tenant = body
+ body = self.tenants_client.create_tenant(tenant_name, enabled=True)
+ tenant = body['tenant']
self.data.tenants.append(tenant)
- tenant_id = body['id']
- en1 = body['enabled']
+ tenant_id = tenant['id']
+ en1 = tenant['enabled']
self.assertTrue(en1, 'Enable should be True in response')
- body = self.client.show_tenant(tenant_id)['tenant']
+ body = self.tenants_client.show_tenant(tenant_id)['tenant']
en2 = body['enabled']
self.assertTrue(en2, 'Enable should be True in lookup')
- self.client.delete_tenant(tenant_id)
+ self.tenants_client.delete_tenant(tenant_id)
self.data.tenants.remove(tenant)
@test.idempotent_id('3be22093-b30f-499d-b772-38340e5e16fb')
def test_tenant_create_not_enabled(self):
# Create a tenant that is not enabled
tenant_name = data_utils.rand_name(name='tenant')
- body = self.client.create_tenant(tenant_name, enabled=False)['tenant']
- tenant = body
+ body = self.tenants_client.create_tenant(tenant_name, enabled=False)
+ tenant = body['tenant']
self.data.tenants.append(tenant)
- tenant_id = body['id']
- en1 = body['enabled']
+ tenant_id = tenant['id']
+ en1 = tenant['enabled']
self.assertEqual('false', str(en1).lower(),
'Enable should be False in response')
- body = self.client.show_tenant(tenant_id)['tenant']
+ body = self.tenants_client.show_tenant(tenant_id)['tenant']
en2 = body['enabled']
self.assertEqual('false', str(en2).lower(),
'Enable should be False in lookup')
- self.client.delete_tenant(tenant_id)
+ self.tenants_client.delete_tenant(tenant_id)
self.data.tenants.remove(tenant)
@test.idempotent_id('781f2266-d128-47f3-8bdb-f70970add238')
def test_tenant_update_name(self):
# Update name attribute of a tenant
t_name1 = data_utils.rand_name(name='tenant')
- body = self.client.create_tenant(t_name1)['tenant']
+ body = self.tenants_client.create_tenant(t_name1)['tenant']
tenant = body
self.data.tenants.append(tenant)
@@ -110,18 +110,18 @@
resp1_name = body['name']
t_name2 = data_utils.rand_name(name='tenant2')
- body = self.client.update_tenant(t_id, name=t_name2)['tenant']
+ body = self.tenants_client.update_tenant(t_id, name=t_name2)['tenant']
resp2_name = body['name']
self.assertNotEqual(resp1_name, resp2_name)
- body = self.client.show_tenant(t_id)['tenant']
+ body = self.tenants_client.show_tenant(t_id)['tenant']
resp3_name = body['name']
self.assertNotEqual(resp1_name, resp3_name)
self.assertEqual(t_name1, resp1_name)
self.assertEqual(resp2_name, resp3_name)
- self.client.delete_tenant(t_id)
+ self.tenants_client.delete_tenant(t_id)
self.data.tenants.remove(tenant)
@test.idempotent_id('859fcfe1-3a03-41ef-86f9-b19a47d1cd87')
@@ -129,26 +129,27 @@
# Update description attribute of a tenant
t_name = data_utils.rand_name(name='tenant')
t_desc = data_utils.rand_name(name='desc')
- body = self.client.create_tenant(t_name, description=t_desc)['tenant']
- tenant = body
+ body = self.tenants_client.create_tenant(t_name, description=t_desc)
+ tenant = body['tenant']
self.data.tenants.append(tenant)
- t_id = body['id']
- resp1_desc = body['description']
+ t_id = tenant['id']
+ resp1_desc = tenant['description']
t_desc2 = data_utils.rand_name(name='desc2')
- body = self.client.update_tenant(t_id, description=t_desc2)['tenant']
- resp2_desc = body['description']
+ body = self.tenants_client.update_tenant(t_id, description=t_desc2)
+ updated_tenant = body['tenant']
+ resp2_desc = updated_tenant['description']
self.assertNotEqual(resp1_desc, resp2_desc)
- body = self.client.show_tenant(t_id)['tenant']
+ body = self.tenants_client.show_tenant(t_id)['tenant']
resp3_desc = body['description']
self.assertNotEqual(resp1_desc, resp3_desc)
self.assertEqual(t_desc, resp1_desc)
self.assertEqual(resp2_desc, resp3_desc)
- self.client.delete_tenant(t_id)
+ self.tenants_client.delete_tenant(t_id)
self.data.tenants.remove(tenant)
@test.idempotent_id('8fc8981f-f12d-4c66-9972-2bdcf2bc2e1a')
@@ -156,24 +157,25 @@
# Update the enabled attribute of a tenant
t_name = data_utils.rand_name(name='tenant')
t_en = False
- body = self.client.create_tenant(t_name, enabled=t_en)['tenant']
- tenant = body
+ body = self.tenants_client.create_tenant(t_name, enabled=t_en)
+ tenant = body['tenant']
self.data.tenants.append(tenant)
- t_id = body['id']
- resp1_en = body['enabled']
+ t_id = tenant['id']
+ resp1_en = tenant['enabled']
t_en2 = True
- body = self.client.update_tenant(t_id, enabled=t_en2)['tenant']
- resp2_en = body['enabled']
+ body = self.tenants_client.update_tenant(t_id, enabled=t_en2)
+ updated_tenant = body['tenant']
+ resp2_en = updated_tenant['enabled']
self.assertNotEqual(resp1_en, resp2_en)
- body = self.client.show_tenant(t_id)['tenant']
+ body = self.tenants_client.show_tenant(t_id)['tenant']
resp3_en = body['enabled']
self.assertNotEqual(resp1_en, resp3_en)
self.assertEqual('false', str(resp1_en).lower())
self.assertEqual(resp2_en, resp3_en)
- self.client.delete_tenant(t_id)
+ self.tenants_client.delete_tenant(t_id)
self.data.tenants.remove(tenant)
diff --git a/tempest/api/identity/admin/v2/test_tokens.py b/tempest/api/identity/admin/v2/test_tokens.py
index 0e7a480..0daa66d 100644
--- a/tempest/api/identity/admin/v2/test_tokens.py
+++ b/tempest/api/identity/admin/v2/test_tokens.py
@@ -24,10 +24,10 @@
def test_create_get_delete_token(self):
# get a token by username and password
user_name = data_utils.rand_name(name='user')
- user_password = data_utils.rand_name(name='pass')
+ user_password = data_utils.rand_password()
# first:create a tenant
tenant_name = data_utils.rand_name(name='tenant')
- tenant = self.client.create_tenant(tenant_name)['tenant']
+ tenant = self.tenants_client.create_tenant(tenant_name)['tenant']
self.data.tenants.append(tenant)
# second:create a user
user = self.client.create_user(user_name, user_password,
@@ -59,7 +59,7 @@
# Create a user.
user_name = data_utils.rand_name(name='user')
- user_password = data_utils.rand_name(name='pass')
+ user_password = data_utils.rand_password()
tenant_id = None # No default tenant so will get unscoped token.
email = ''
user = self.client.create_user(user_name, user_password,
@@ -68,11 +68,11 @@
# Create a couple tenants.
tenant1_name = data_utils.rand_name(name='tenant')
- tenant1 = self.client.create_tenant(tenant1_name)['tenant']
+ tenant1 = self.tenants_client.create_tenant(tenant1_name)['tenant']
self.data.tenants.append(tenant1)
tenant2_name = data_utils.rand_name(name='tenant')
- tenant2 = self.client.create_tenant(tenant2_name)['tenant']
+ tenant2 = self.tenants_client.create_tenant(tenant2_name)['tenant']
self.data.tenants.append(tenant2)
# Create a role
diff --git a/tempest/api/identity/admin/v2/test_users.py b/tempest/api/identity/admin/v2/test_users.py
index 6341106..9cf1ce0 100644
--- a/tempest/api/identity/admin/v2/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -26,7 +26,7 @@
def resource_setup(cls):
super(UsersTestJSON, cls).resource_setup()
cls.alt_user = data_utils.rand_name('test_user')
- cls.alt_password = data_utils.rand_name('pass')
+ cls.alt_password = data_utils.rand_password()
cls.alt_email = cls.alt_user + '@testmail.tm'
@test.attr(type='smoke')
@@ -132,21 +132,22 @@
self.data.setup_test_tenant()
user_ids = list()
fetched_user_ids = list()
+ password1 = data_utils.rand_password()
alt_tenant_user1 = data_utils.rand_name('tenant_user1')
- user1 = self.client.create_user(alt_tenant_user1, 'password1',
+ user1 = self.client.create_user(alt_tenant_user1, password1,
self.data.tenant['id'],
'user1@123')['user']
user_ids.append(user1['id'])
self.data.users.append(user1)
-
+ password2 = data_utils.rand_password()
alt_tenant_user2 = data_utils.rand_name('tenant_user2')
- user2 = self.client.create_user(alt_tenant_user2, 'password2',
+ user2 = self.client.create_user(alt_tenant_user2, password2,
self.data.tenant['id'],
'user2@123')['user']
user_ids.append(user2['id'])
self.data.users.append(user2)
# List of users for the respective tenant ID
- body = (self.client.list_tenant_users(self.data.tenant['id'])
+ body = (self.tenants_client.list_tenant_users(self.data.tenant['id'])
['users'])
for i in body:
fetched_user_ids.append(i['id'])
@@ -173,7 +174,8 @@
role['id'])['role']
alt_user2 = data_utils.rand_name('second_user')
- second_user = self.client.create_user(alt_user2, 'password1',
+ alt_password2 = data_utils.rand_password()
+ second_user = self.client.create_user(alt_user2, alt_password2,
self.data.tenant['id'],
'user2@123')['user']
user_ids.append(second_user['id'])
@@ -182,7 +184,7 @@
second_user['id'],
role['id'])['role']
# List of users with roles for the respective tenant ID
- body = (self.client.list_tenant_users(self.data.tenant['id'])
+ body = (self.tenants_client.list_tenant_users(self.data.tenant['id'])
['users'])
for i in body:
fetched_user_ids.append(i['id'])
@@ -198,7 +200,7 @@
# Test case to check if updating of user password is successful.
self.data.setup_test_user()
# Updating the user with new password
- new_pass = data_utils.rand_name('pass')
+ new_pass = data_utils.rand_password()
update_user = self.client.update_user_password(
self.data.user['id'], new_pass)['user']
self.assertEqual(update_user['id'], self.data.user['id'])
diff --git a/tempest/api/identity/admin/v2/test_users_negative.py b/tempest/api/identity/admin/v2/test_users_negative.py
index a88053d..8fa5a36 100644
--- a/tempest/api/identity/admin/v2/test_users_negative.py
+++ b/tempest/api/identity/admin/v2/test_users_negative.py
@@ -28,7 +28,7 @@
def resource_setup(cls):
super(UsersNegativeTestJSON, cls).resource_setup()
cls.alt_user = data_utils.rand_name('test_user')
- cls.alt_password = data_utils.rand_name('pass')
+ cls.alt_password = data_utils.rand_password()
cls.alt_email = cls.alt_user + '@testmail.tm'
@test.attr(type=['negative'])
@@ -247,4 +247,4 @@
# List the users with invalid tenant id
for invalid in invalid_id:
self.assertRaises(lib_exc.NotFound,
- self.client.list_tenant_users, invalid)
+ self.tenants_client.list_tenant_users, invalid)
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index 048c53a..b81bff7 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -29,7 +29,7 @@
u_name = data_utils.rand_name('user')
u_desc = '%s description' % u_name
u_email = '%s@testmail.tm' % u_name
- u_password = data_utils.rand_name('pass')
+ u_password = data_utils.rand_password()
for i in range(2):
cls.project = cls.client.create_project(
data_utils.rand_name('project'),
@@ -76,7 +76,7 @@
self.assertEqual(update_body['blob']['access'], new_keys[0])
self.assertEqual(update_body['blob']['secret'], new_keys[1])
- get_body = self.creds_client.get_credential(cred['id'])['credential']
+ get_body = self.creds_client.show_credential(cred['id'])['credential']
for value1 in self.creds_list[0]:
self.assertEqual(update_body[value1],
get_body[value1])
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 5ce6354..e022023 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -24,48 +24,62 @@
def test_group_create_update_get(self):
name = data_utils.rand_name('Group')
description = data_utils.rand_name('Description')
- group = self.client.create_group(name,
- description=description)['group']
- self.addCleanup(self.client.delete_group, group['id'])
+ group = self.groups_client.create_group(
+ name=name, description=description)['group']
+ self.addCleanup(self.groups_client.delete_group, group['id'])
self.assertEqual(group['name'], name)
self.assertEqual(group['description'], description)
new_name = data_utils.rand_name('UpdateGroup')
new_desc = data_utils.rand_name('UpdateDescription')
- updated_group = self.client.update_group(group['id'],
- name=new_name,
- description=new_desc)['group']
+ updated_group = self.groups_client.update_group(
+ group['id'], name=new_name, description=new_desc)['group']
self.assertEqual(updated_group['name'], new_name)
self.assertEqual(updated_group['description'], new_desc)
- new_group = self.client.get_group(group['id'])['group']
+ new_group = self.groups_client.show_group(group['id'])['group']
self.assertEqual(group['id'], new_group['id'])
self.assertEqual(new_name, new_group['name'])
self.assertEqual(new_desc, new_group['description'])
+ @test.idempotent_id('b66eb441-b08a-4a6d-81ab-fef71baeb26c')
+ def test_group_update_with_few_fields(self):
+ name = data_utils.rand_name('Group')
+ old_description = data_utils.rand_name('Description')
+ group = self.groups_client.create_group(
+ name=name, description=old_description)['group']
+ self.addCleanup(self.groups_client.delete_group, group['id'])
+
+ new_name = data_utils.rand_name('UpdateGroup')
+ updated_group = self.groups_client.update_group(
+ group['id'], name=new_name)['group']
+ self.assertEqual(new_name, updated_group['name'])
+ # Verify that 'description' is not being updated or deleted.
+ self.assertEqual(old_description, updated_group['description'])
+
@test.attr(type='smoke')
@test.idempotent_id('1598521a-2f36-4606-8df9-30772bd51339')
def test_group_users_add_list_delete(self):
name = data_utils.rand_name('Group')
- group = self.client.create_group(name)['group']
- self.addCleanup(self.client.delete_group, group['id'])
+ group = self.groups_client.create_group(name=name)['group']
+ self.addCleanup(self.groups_client.delete_group, group['id'])
# add user into group
users = []
for i in range(3):
name = data_utils.rand_name('User')
- user = self.client.create_user(name)['user']
+ password = data_utils.rand_password()
+ user = self.client.create_user(name, password)['user']
users.append(user)
self.addCleanup(self.client.delete_user, user['id'])
- self.client.add_group_user(group['id'], user['id'])
+ self.groups_client.add_group_user(group['id'], user['id'])
# list users in group
- group_users = self.client.list_group_users(group['id'])['users']
+ group_users = self.groups_client.list_group_users(group['id'])['users']
self.assertEqual(sorted(users), sorted(group_users))
# delete user in group
for user in users:
- self.client.delete_group_user(group['id'],
- user['id'])
- group_users = self.client.list_group_users(group['id'])['users']
+ self.groups_client.delete_group_user(group['id'], user['id'])
+ group_users = self.groups_client.list_group_users(group['id'])['users']
self.assertEqual(len(group_users), 0)
@test.idempotent_id('64573281-d26a-4a52-b899-503cb0f4e4ec')
@@ -79,10 +93,10 @@
groups = []
for i in range(2):
name = data_utils.rand_name('Group')
- group = self.client.create_group(name)['group']
+ group = self.groups_client.create_group(name=name)['group']
groups.append(group)
- self.addCleanup(self.client.delete_group, group['id'])
- self.client.add_group_user(group['id'], user['id'])
+ self.addCleanup(self.groups_client.delete_group, group['id'])
+ self.groups_client.add_group_user(group['id'], user['id'])
# list groups which user belongs to
user_groups = self.client.list_user_groups(user['id'])['groups']
self.assertEqual(sorted(groups), sorted(user_groups))
@@ -96,12 +110,12 @@
for _ in range(3):
name = data_utils.rand_name('Group')
description = data_utils.rand_name('Description')
- group = self.client.create_group(name,
- description=description)['group']
- self.addCleanup(self.client.delete_group, group['id'])
+ group = self.groups_client.create_group(
+ name=name, description=description)['group']
+ self.addCleanup(self.groups_client.delete_group, group['id'])
group_ids.append(group['id'])
# List and Verify Groups
- body = self.client.list_groups()['groups']
+ body = self.groups_client.list_groups()['groups']
for g in body:
fetched_ids.append(g['id'])
missing_groups = [g for g in group_ids if g not in fetched_ids]
diff --git a/tempest/api/identity/admin/v3/test_list_users.py b/tempest/api/identity/admin/v3/test_list_users.py
index b7f37d4..ca91ce5 100644
--- a/tempest/api/identity/admin/v3/test_list_users.py
+++ b/tempest/api/identity/admin/v3/test_list_users.py
@@ -34,7 +34,7 @@
def resource_setup(cls):
super(UsersV3TestJSON, cls).resource_setup()
alt_user = data_utils.rand_name('test_user')
- alt_password = data_utils.rand_name('pass')
+ alt_password = data_utils.rand_password()
cls.alt_email = alt_user + '@testmail.tm'
cls.data.setup_test_domain()
# Create user with Domain
diff --git a/tempest/api/identity/admin/v3/test_policies.py b/tempest/api/identity/admin/v3/test_policies.py
index 44e5c7b..f38d25d 100644
--- a/tempest/api/identity/admin/v3/test_policies.py
+++ b/tempest/api/identity/admin/v3/test_policies.py
@@ -64,7 +64,7 @@
policy['id'], type=update_type)['policy']
self.assertIn('type', data)
# Assertion for updated value with fetched value
- fetched_policy = self.policy_client.get_policy(policy['id'])['policy']
+ fetched_policy = self.policy_client.show_policy(policy['id'])['policy']
self.assertIn('id', fetched_policy)
self.assertIn('blob', fetched_policy)
self.assertIn('type', fetched_policy)
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index d39fd5f..af9497c 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -161,7 +161,7 @@
u_name = data_utils.rand_name('user')
u_desc = u_name + 'description'
u_email = u_name + '@testmail.tm'
- u_password = data_utils.rand_name('pass')
+ u_password = data_utils.rand_password()
user = self.client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email, project_id=project['id'])['user']
diff --git a/tempest/api/identity/admin/v3/test_regions.py b/tempest/api/identity/admin/v3/test_regions.py
index 0dbbae0..ec1b12e 100644
--- a/tempest/api/identity/admin/v3/test_regions.py
+++ b/tempest/api/identity/admin/v3/test_regions.py
@@ -46,7 +46,7 @@
def _delete_region(self, region_id):
self.client.delete_region(region_id)
self.assertRaises(lib_exc.NotFound,
- self.client.get_region, region_id)
+ self.client.show_region, region_id)
@test.idempotent_id('56186092-82e4-43f2-b954-91013218ba42')
def test_create_update_get_delete_region(self):
@@ -68,7 +68,7 @@
self.assertEqual(self.setup_regions[1]['id'],
region['parent_region_id'])
# Get the details of region
- region = self.client.get_region(region['id'])['region']
+ region = self.client.show_region(region['id'])['region']
self.assertEqual(r_alt_description, region['description'])
self.assertEqual(self.setup_regions[1]['id'],
region['parent_region_id'])
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index 8595dde..f194d9c 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -31,7 +31,7 @@
u_name = data_utils.rand_name('user')
u_desc = '%s description' % u_name
u_email = '%s@testmail.tm' % u_name
- cls.u_password = data_utils.rand_name('pass')
+ cls.u_password = data_utils.rand_password()
cls.domain = cls.client.create_domain(
data_utils.rand_name('domain'),
description=data_utils.rand_name('domain-desc'))['domain']
@@ -39,8 +39,8 @@
data_utils.rand_name('project'),
description=data_utils.rand_name('project-desc'),
domain_id=cls.domain['id'])['project']
- cls.group_body = cls.client.create_group(
- data_utils.rand_name('Group'), project_id=cls.project['id'],
+ cls.group_body = cls.groups_client.create_group(
+ name=data_utils.rand_name('Group'), project_id=cls.project['id'],
domain_id=cls.domain['id'])['group']
cls.user_body = cls.client.create_user(
u_name, description=u_desc, password=cls.u_password,
@@ -52,7 +52,7 @@
@classmethod
def resource_cleanup(cls):
cls.client.delete_role(cls.role['id'])
- cls.client.delete_group(cls.group_body['id'])
+ cls.groups_client.delete_group(cls.group_body['id'])
cls.client.delete_user(cls.user_body['id'])
cls.client.delete_project(cls.project['id'])
# NOTE(harika-vakadi): It is necessary to disable the domain
@@ -102,7 +102,7 @@
self._list_assertions(roles, self.fetched_role_ids,
self.role['id'])
- self.client.revoke_role_from_user_on_project(
+ self.client.delete_role_from_user_on_project(
self.project['id'], self.user_body['id'], self.role['id'])
@test.idempotent_id('6c9a2940-3625-43a3-ac02-5dcec62ef3bd')
@@ -119,7 +119,7 @@
self._list_assertions(roles, self.fetched_role_ids,
self.role['id'])
- self.client.revoke_role_from_user_on_domain(
+ self.client.delete_role_from_user_on_domain(
self.domain['id'], self.user_body['id'], self.role['id'])
@test.idempotent_id('cbf11737-1904-4690-9613-97bcbb3df1c4')
@@ -137,8 +137,9 @@
self._list_assertions(roles, self.fetched_role_ids,
self.role['id'])
# Add user to group, and insure user has role on project
- self.client.add_group_user(self.group_body['id'], self.user_body['id'])
- self.addCleanup(self.client.delete_group_user,
+ self.groups_client.add_group_user(self.group_body['id'],
+ self.user_body['id'])
+ self.addCleanup(self.groups_client.delete_group_user,
self.group_body['id'], self.user_body['id'])
body = self.token.auth(user_id=self.user_body['id'],
password=self.u_password,
@@ -149,7 +150,7 @@
self.assertEqual(len(roles), 1)
self.assertEqual(roles[0]['id'], self.role['id'])
# Revoke role to group on project
- self.client.revoke_role_from_group_on_project(
+ self.client.delete_role_from_group_on_project(
self.project['id'], self.group_body['id'], self.role['id'])
@test.idempotent_id('4bf8a70b-e785-413a-ad53-9f91ce02faa7')
@@ -166,7 +167,7 @@
self._list_assertions(roles, self.fetched_role_ids,
self.role['id'])
- self.client.revoke_role_from_group_on_domain(
+ self.client.delete_role_from_group_on_domain(
self.domain['id'], self.group_body['id'], self.role['id'])
@test.idempotent_id('f5654bcc-08c4-4f71-88fe-05d64e06de94')
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index 7d33d4a..f5b20d5 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -29,7 +29,7 @@
u_name = data_utils.rand_name('user')
u_desc = '%s-description' % u_name
u_email = '%s@testmail.tm' % u_name
- u_password = data_utils.rand_name('pass')
+ u_password = data_utils.rand_password()
user = self.client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email)['user']
@@ -60,7 +60,7 @@
# Create a user.
user_name = data_utils.rand_name(name='user')
- user_password = data_utils.rand_name(name='pass')
+ user_password = data_utils.rand_password()
user = self.client.create_user(user_name,
password=user_password)['user']
self.addCleanup(self.client.delete_user, user['id'])
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index a8b0af9..bf7ad71 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -55,7 +55,7 @@
self.trustor_username = data_utils.rand_name('user')
u_desc = self.trustor_username + 'description'
u_email = self.trustor_username + '@testmail.xx'
- self.trustor_password = data_utils.rand_name('pass')
+ self.trustor_password = data_utils.rand_password()
user = self.client.create_user(
self.trustor_username,
description=u_desc,
@@ -115,7 +115,7 @@
trustor_user_id=self.trustor_user_id,
trustee_user_id=self.trustee_user_id,
project_id=self.trustor_project_id,
- role_names=[self.delegated_role],
+ roles=[{'name': self.delegated_role}],
impersonation=impersonate,
expires_at=expires)['trust']
self.trust_id = trust_create['id']
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index b56c9e6..6dbd443 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import time
+
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest import test
@@ -27,7 +29,7 @@
u_name = data_utils.rand_name('user')
u_desc = u_name + 'description'
u_email = u_name + '@testmail.tm'
- u_password = data_utils.rand_name('pass')
+ u_password = data_utils.rand_password()
user = self.client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email, enabled=False)['user']
@@ -67,15 +69,23 @@
def test_update_user_password(self):
# Creating User to check password updation
u_name = data_utils.rand_name('user')
- original_password = data_utils.rand_name('pass')
+ original_password = data_utils.rand_password()
user = self.client.create_user(
u_name, password=original_password)['user']
# Delete the User at the end all test methods
self.addCleanup(self.client.delete_user, user['id'])
# Update user with new password
- new_password = data_utils.rand_name('pass1')
- self.client.update_user_password(user['id'], new_password,
- original_password)
+ new_password = data_utils.rand_password()
+ self.client.update_user_password(user['id'], password=new_password,
+ original_password=original_password)
+ # TODO(lbragstad): Sleeping after the response status has been checked
+ # and the body loaded as JSON allows requests to fail-fast. The sleep
+ # is necessary because keystone will err on the side of security and
+ # invalidate tokens within a small margin of error (within the same
+ # wall clock second) after a revocation event is issued (such as a
+ # password change). Remove this once keystone and Fernet support
+ # sub-second precision, see bug 1517697 for more details.
+ time.sleep(1)
resp = self.token.auth(user_id=user['id'],
password=new_password).response
subject_token = resp['x-subject-token']
@@ -99,7 +109,7 @@
u_name = data_utils.rand_name('user')
u_desc = u_name + 'description'
u_email = u_name + '@testmail.tm'
- u_password = data_utils.rand_name('pass')
+ u_password = data_utils.rand_password()
user_body = self.client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email, enabled=False, project_id=u_project['id'])['user']
diff --git a/tempest/api/identity/admin/v3/test_users_negative.py b/tempest/api/identity/admin/v3/test_users_negative.py
new file mode 100644
index 0000000..4c80bda
--- /dev/null
+++ b/tempest/api/identity/admin/v3/test_users_negative.py
@@ -0,0 +1,46 @@
+# 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.common.utils import data_utils
+from tempest import test
+
+
+class UsersNegativeTest(base.BaseIdentityV3AdminTest):
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('e75f006c-89cc-477b-874d-588e4eab4b17')
+ def test_create_user_for_non_existent_domain(self):
+ # Attempt to create a user in a non-existent domain should fail
+ u_name = data_utils.rand_name('user')
+ u_email = u_name + '@testmail.tm'
+ u_password = data_utils.rand_password()
+ self.assertRaises(lib_exc.NotFound, self.client.create_user,
+ u_name, u_password,
+ email=u_email,
+ domain_id=data_utils.rand_uuid_hex())
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('b3c9fccc-4134-46f5-b600-1da6fb0a3b1f')
+ def test_authentication_for_disabled_user(self):
+ # Attempt to authenticate for disabled user should fail
+ self.data.setup_test_v3_user()
+ self.disable_user(self.data.test_user)
+ self.assertRaises(lib_exc.Unauthorized, self.token.auth,
+ username=self.data.test_user,
+ password=self.data.test_password,
+ user_domain_id='default')
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index f9395bc..8359b8f 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -35,7 +35,7 @@
@classmethod
def disable_tenant(cls, tenant_name):
tenant = cls.get_tenant_by_name(tenant_name)
- cls.client.update_tenant(tenant['id'], enabled=False)
+ cls.tenants_client.update_tenant(tenant['id'], enabled=False)
@classmethod
def get_user_by_name(cls, name):
@@ -47,7 +47,7 @@
@classmethod
def get_tenant_by_name(cls, name):
try:
- tenants = cls.client.list_tenants()['tenants']
+ tenants = cls.tenants_client.list_tenants()['tenants']
except AttributeError:
tenants = cls.client.list_projects()['projects']
tenant = [t for t in tenants if t['name'] == name]
@@ -75,6 +75,7 @@
super(BaseIdentityV2Test, cls).setup_clients()
cls.non_admin_client = cls.os.identity_public_client
cls.non_admin_token_client = cls.os.token_client
+ cls.non_admin_tenants_client = cls.os.tenants_public_client
@classmethod
def resource_setup(cls):
@@ -95,11 +96,13 @@
cls.client = cls.os_adm.identity_client
cls.non_admin_client = cls.os.identity_client
cls.token_client = cls.os_adm.token_client
+ cls.tenants_client = cls.os_adm.tenants_client
+ cls.non_admin_tenants_client = cls.os.tenants_client
@classmethod
def resource_setup(cls):
super(BaseIdentityV2AdminTest, cls).resource_setup()
- cls.data = DataGenerator(cls.client)
+ cls.data = DataGenerator(cls.client, cls.tenants_client)
@classmethod
def resource_cleanup(cls):
@@ -120,11 +123,6 @@
super(BaseIdentityV3Test, cls).setup_clients()
cls.non_admin_client = cls.os.identity_v3_client
cls.non_admin_token = cls.os.token_v3_client
- cls.non_admin_endpoints_client = cls.os.endpoints_client
- cls.non_admin_region_client = cls.os.region_client
- cls.non_admin_service_client = cls.os.service_client
- cls.non_admin_policy_client = cls.os.policy_client
- cls.non_admin_creds_client = cls.os.credentials_client
@classmethod
def resource_cleanup(cls):
@@ -142,10 +140,12 @@
cls.token = cls.os_adm.token_v3_client
cls.endpoints_client = cls.os_adm.endpoints_client
cls.region_client = cls.os_adm.region_client
- cls.data = DataGenerator(cls.client)
cls.service_client = cls.os_adm.service_client
cls.policy_client = cls.os_adm.policy_client
cls.creds_client = cls.os_adm.credentials_client
+ cls.groups_client = cls.os_adm.groups_client
+
+ cls.data = DataGenerator(cls.client)
@classmethod
def resource_cleanup(cls):
@@ -173,6 +173,11 @@
if len(role) > 0:
return role[0]
+ @classmethod
+ def disable_user(cls, user_name):
+ user = cls.get_user_by_name(user_name)
+ cls.client.update_user(user['id'], user_name, enabled=False)
+
def delete_domain(self, domain_id):
# NOTE(mpavlase) It is necessary to disable the domain before deleting
# otherwise it raises Forbidden exception
@@ -182,8 +187,10 @@
class DataGenerator(object):
- def __init__(self, client):
+ def __init__(self, client, tenants_client=None):
self.client = client
+ # TODO(dmellado) split Datagenerator for v2 and v3
+ self.tenants_client = tenants_client
self.users = []
self.tenants = []
self.roles = []
@@ -205,7 +212,7 @@
"""Set up a test user."""
self.setup_test_tenant()
self.test_user = data_utils.rand_name('test_user')
- self.test_password = data_utils.rand_name('pass')
+ self.test_password = data_utils.rand_password()
self.test_email = self.test_user + '@testmail.tm'
self.user = self.client.create_user(self.test_user,
self.test_password,
@@ -217,7 +224,7 @@
"""Set up a test tenant."""
self.test_tenant = data_utils.rand_name('test_tenant')
self.test_description = data_utils.rand_name('desc')
- self.tenant = self.client.create_tenant(
+ self.tenant = self.tenants_client.create_tenant(
name=self.test_tenant,
description=self.test_description)['tenant']
self.tenants.append(self.tenant)
@@ -232,7 +239,7 @@
"""Set up a test v3 user."""
self.setup_test_project()
self.test_user = data_utils.rand_name('test_user')
- self.test_password = data_utils.rand_name('pass')
+ self.test_password = data_utils.rand_password()
self.test_email = self.test_user + '@testmail.tm'
self.v3_user = self.client.create_user(
self.test_user,
@@ -285,7 +292,7 @@
for user in self.users:
self._try_wrapper(self.client.delete_user, user)
for tenant in self.tenants:
- self._try_wrapper(self.client.delete_tenant, tenant)
+ self._try_wrapper(self.tenants_client.delete_tenant, tenant)
for role in self.roles:
self._try_wrapper(self.client.delete_role, role)
for v3_user in self.v3_users:
diff --git a/tempest/api/identity/v2/test_ec2_credentials.py b/tempest/api/identity/v2/test_ec2_credentials.py
index 763d8de..88161a3 100644
--- a/tempest/api/identity/v2/test_ec2_credentials.py
+++ b/tempest/api/identity/v2/test_ec2_credentials.py
@@ -38,7 +38,7 @@
"""Create user ec2 credentials."""
resp = self.non_admin_client.create_user_ec2_credentials(
self.creds.credentials.user_id,
- self.creds.credentials.tenant_id)["credential"]
+ tenant_id=self.creds.credentials.tenant_id)["credential"]
access = resp['access']
self.addCleanup(
self.non_admin_client.delete_user_ec2_credentials,
@@ -56,12 +56,12 @@
# create first ec2 credentials
creds1 = self.non_admin_client.create_user_ec2_credentials(
self.creds.credentials.user_id,
- self.creds.credentials.tenant_id)["credential"]
+ tenant_id=self.creds.credentials.tenant_id)["credential"]
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)["credential"]
+ tenant_id=self.creds.credentials.tenant_id)["credential"]
created_creds.append(creds2['access'])
# add credentials to be cleaned up
self.addCleanup(
@@ -86,7 +86,7 @@
"""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)["credential"]
+ tenant_id=self.creds.credentials.tenant_id)["credential"]
self.addCleanup(
self.non_admin_client.delete_user_ec2_credentials,
self.creds.credentials.user_id, resp['access'])
@@ -102,7 +102,7 @@
"""Delete user ec2 credentials."""
resp = self.non_admin_client.create_user_ec2_credentials(
self.creds.credentials.user_id,
- self.creds.credentials.tenant_id)["credential"]
+ tenant_id=self.creds.credentials.tenant_id)["credential"]
access = resp['access']
self.non_admin_client.delete_user_ec2_credentials(
self.creds.credentials.user_id, access)
diff --git a/tempest/api/identity/v2/test_tenants.py b/tempest/api/identity/v2/test_tenants.py
index 1fcff8d..4e31557 100644
--- a/tempest/api/identity/v2/test_tenants.py
+++ b/tempest/api/identity/v2/test_tenants.py
@@ -26,7 +26,7 @@
@test.idempotent_id('ecae2459-243d-4ba1-ad02-65f15dc82b78')
def test_list_tenants_returns_only_authorized_tenants(self):
alt_tenant_name = self.alt_manager.credentials.credentials.tenant_name
- resp = self.non_admin_client.list_tenants()
+ resp = self.non_admin_tenants_client.list_tenants()
# check that user can see only that tenants that he presents in so user
# can successfully authenticate using his credentials and tenant name
diff --git a/tempest/api/identity/v2/test_users.py b/tempest/api/identity/v2/test_users.py
index 50aaa25..5f2a8c4 100644
--- a/tempest/api/identity/v2/test_users.py
+++ b/tempest/api/identity/v2/test_users.py
@@ -55,6 +55,10 @@
new_pass=old_pass,
old_pass=new_pass)
+ # user updates own password
+ self.non_admin_client.update_user_own_password(
+ user_id=user_id, new_pass=new_pass, old_pass=old_pass)
+
# TODO(lbragstad): Sleeping after the response status has been checked
# and the body loaded as JSON allows requests to fail-fast. The sleep
# is necessary because keystone will err on the side of security and
@@ -64,12 +68,6 @@
# sub-second precision.
time.sleep(1)
- # user updates own password
- resp = self.non_admin_client.update_user_own_password(
- user_id=user_id, new_pass=new_pass, old_pass=old_pass)['access']
-
- # check authorization with new token
- self.non_admin_token_client.auth_token(resp['token']['id'])
# check authorization with new password
self.non_admin_token_client.auth(self.username,
new_pass,
diff --git a/tempest/api/identity/v3/test_users.py b/tempest/api/identity/v3/test_users.py
index 14a866f..93814d3 100644
--- a/tempest/api/identity/v3/test_users.py
+++ b/tempest/api/identity/v3/test_users.py
@@ -50,10 +50,14 @@
# to change password back. important for allow_tenant_isolation = false
self.addCleanup(
self.non_admin_client_for_cleanup.update_user_password,
- user_id=user_id,
+ user_id,
password=old_pass,
original_password=new_pass)
+ # user updates own password
+ self.non_admin_client.update_user_password(
+ user_id, password=new_pass, original_password=old_pass)
+
# TODO(lbragstad): Sleeping after the response status has been checked
# and the body loaded as JSON allows requests to fail-fast. The sleep
# is necessary because keystone will err on the side of security and
@@ -63,10 +67,6 @@
# sub-second precision.
time.sleep(1)
- # user updates own password
- self.non_admin_client.update_user_password(
- user_id=user_id, password=new_pass, original_password=old_pass)
-
# check authorization with new password
self.non_admin_token.auth(user_id=self.user_id, password=new_pass)
diff --git a/tempest/api/image/admin/v2/test_images.py b/tempest/api/image/admin/v2/test_images.py
index 01838b6..b171da3 100644
--- a/tempest/api/image/admin/v2/test_images.py
+++ b/tempest/api/image/admin/v2/test_images.py
@@ -49,12 +49,12 @@
body = self.client.show_image(image_id)
self.assertEqual("deactivated", body['status'])
# non-admin user unable to download deactivated image
- self.assertRaises(lib_exc.Forbidden, self.client.load_image_file,
+ self.assertRaises(lib_exc.Forbidden, self.client.show_image_file,
image_id)
# reactivate image
self.admin_client.reactivate_image(image_id)
body = self.client.show_image(image_id)
self.assertEqual("active", body['status'])
# non-admin user able to download image after reactivation by admin
- body = self.client.load_image_file(image_id)
+ body = self.client.show_image_file(image_id)
self.assertEqual(content, body.data)
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 936eadf..2e6c268 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -72,7 +72,7 @@
self.assertEqual(1024, body.get('size'))
# Now try get image file
- body = self.client.load_image_file(image_id)
+ body = self.client.show_image_file(image_id)
self.assertEqual(file_content, body.data)
@test.attr(type='smoke')
diff --git a/tempest/api/image/v2/test_images_member.py b/tempest/api/image/v2/test_images_member.py
index d89803d..bb73318 100644
--- a/tempest/api/image/v2/test_images_member.py
+++ b/tempest/api/image/v2/test_images_member.py
@@ -19,15 +19,15 @@
@test.idempotent_id('5934c6ea-27dc-4d6e-9421-eeb5e045494a')
def test_image_share_accept(self):
image_id = self._create_image()
- member = self.os_img_client.add_image_member(image_id,
- self.alt_tenant_id)
+ member = self.os_img_client.create_image_member(
+ image_id, member=self.alt_tenant_id)
self.assertEqual(member['member_id'], self.alt_tenant_id)
self.assertEqual(member['image_id'], image_id)
self.assertEqual(member['status'], 'pending')
self.assertNotIn(image_id, self._list_image_ids_as_alt())
self.alt_img_client.update_image_member(image_id,
self.alt_tenant_id,
- {'status': 'accepted'})
+ status='accepted')
self.assertIn(image_id, self._list_image_ids_as_alt())
body = self.os_img_client.list_image_members(image_id)
members = body['members']
@@ -40,25 +40,25 @@
@test.idempotent_id('d9e83e5f-3524-4b38-a900-22abcb26e90e')
def test_image_share_reject(self):
image_id = self._create_image()
- member = self.os_img_client.add_image_member(image_id,
- self.alt_tenant_id)
+ member = self.os_img_client.create_image_member(
+ image_id, member=self.alt_tenant_id)
self.assertEqual(member['member_id'], self.alt_tenant_id)
self.assertEqual(member['image_id'], image_id)
self.assertEqual(member['status'], 'pending')
self.assertNotIn(image_id, self._list_image_ids_as_alt())
self.alt_img_client.update_image_member(image_id,
self.alt_tenant_id,
- {'status': 'rejected'})
+ status='rejected')
self.assertNotIn(image_id, self._list_image_ids_as_alt())
@test.idempotent_id('a6ee18b9-4378-465e-9ad9-9a6de58a3287')
def test_get_image_member(self):
image_id = self._create_image()
- self.os_img_client.add_image_member(image_id,
- self.alt_tenant_id)
+ self.os_img_client.create_image_member(
+ image_id, member=self.alt_tenant_id)
self.alt_img_client.update_image_member(image_id,
self.alt_tenant_id,
- {'status': 'accepted'})
+ status='accepted')
self.assertIn(image_id, self._list_image_ids_as_alt())
member = self.os_img_client.show_image_member(image_id,
@@ -70,14 +70,14 @@
@test.idempotent_id('72989bc7-2268-48ed-af22-8821e835c914')
def test_remove_image_member(self):
image_id = self._create_image()
- self.os_img_client.add_image_member(image_id,
- self.alt_tenant_id)
+ self.os_img_client.create_image_member(
+ image_id, member=self.alt_tenant_id)
self.alt_img_client.update_image_member(image_id,
self.alt_tenant_id,
- {'status': 'accepted'})
+ status='accepted')
self.assertIn(image_id, self._list_image_ids_as_alt())
- self.os_img_client.remove_image_member(image_id, self.alt_tenant_id)
+ self.os_img_client.delete_image_member(image_id, self.alt_tenant_id)
self.assertNotIn(image_id, self._list_image_ids_as_alt())
@test.idempotent_id('634dcc3f-f6e2-4409-b8fd-354a0bb25d83')
@@ -93,15 +93,15 @@
@test.idempotent_id('cb961424-3f68-4d21-8e36-30ad66fb6bfb')
def test_get_private_image(self):
image_id = self._create_image()
- member = self.os_img_client.add_image_member(image_id,
- self.alt_tenant_id)
+ member = self.os_img_client.create_image_member(
+ image_id, member=self.alt_tenant_id)
self.assertEqual(member['member_id'], self.alt_tenant_id)
self.assertEqual(member['image_id'], image_id)
self.assertEqual(member['status'], 'pending')
self.assertNotIn(image_id, self._list_image_ids_as_alt())
self.alt_img_client.update_image_member(image_id,
self.alt_tenant_id,
- {'status': 'accepted'})
+ status='accepted')
self.assertIn(image_id, self._list_image_ids_as_alt())
- self.os_img_client.remove_image_member(image_id, self.alt_tenant_id)
+ self.os_img_client.delete_image_member(image_id, self.alt_tenant_id)
self.assertNotIn(image_id, self._list_image_ids_as_alt())
diff --git a/tempest/api/image/v2/test_images_member_negative.py b/tempest/api/image/v2/test_images_member_negative.py
index ae8913c..eb90719 100644
--- a/tempest/api/image/v2/test_images_member_negative.py
+++ b/tempest/api/image/v2/test_images_member_negative.py
@@ -22,23 +22,23 @@
@test.idempotent_id('b79efb37-820d-4cf0-b54c-308b00cf842c')
def test_image_share_invalid_status(self):
image_id = self._create_image()
- member = self.os_img_client.add_image_member(image_id,
- self.alt_tenant_id)
+ member = self.os_img_client.create_image_member(
+ image_id, member=self.alt_tenant_id)
self.assertEqual(member['status'], 'pending')
self.assertRaises(lib_exc.BadRequest,
self.alt_img_client.update_image_member,
image_id, self.alt_tenant_id,
- {'status': 'notavalidstatus'})
+ status='notavalidstatus')
@test.attr(type=['negative'])
@test.idempotent_id('27002f74-109e-4a37-acd0-f91cd4597967')
def test_image_share_owner_cannot_accept(self):
image_id = self._create_image()
- member = self.os_img_client.add_image_member(image_id,
- self.alt_tenant_id)
+ member = self.os_img_client.create_image_member(
+ image_id, member=self.alt_tenant_id)
self.assertEqual(member['status'], 'pending')
self.assertNotIn(image_id, self._list_image_ids_as_alt())
self.assertRaises(lib_exc.Forbidden,
self.os_img_client.update_image_member,
- image_id, self.alt_tenant_id, {'status': 'accepted'})
+ image_id, self.alt_tenant_id, status='accepted')
self.assertNotIn(image_id, self._list_image_ids_as_alt())
diff --git a/tempest/api/image/v2/test_images_metadefs_namespaces.py b/tempest/api/image/v2/test_images_metadefs_namespaces.py
index d089c84..efb7b8b 100644
--- a/tempest/api/image/v2/test_images_metadefs_namespaces.py
+++ b/tempest/api/image/v2/test_images_metadefs_namespaces.py
@@ -29,42 +29,42 @@
resource_name = body['resource_types'][0]['name']
name = [{'name': resource_name}]
namespace_name = data_utils.rand_name('namespace')
- # create the metadef namespaces
- body = self.client.create_namespaces(namespace=namespace_name,
- visibility='public',
- description='Tempest',
- display_name=namespace_name,
- resource_type_associations=name,
- protected=True)
+ # create the metadef namespace
+ body = self.client.create_namespace(namespace=namespace_name,
+ visibility='public',
+ description='Tempest',
+ display_name=namespace_name,
+ resource_type_associations=name,
+ protected=True)
self.addCleanup(self._cleanup_namespace, namespace_name)
- # get namespaces details
- body = self.client.show_namespaces(namespace_name)
+ # get namespace details
+ body = self.client.show_namespace(namespace_name)
self.assertEqual(namespace_name, body['namespace'])
self.assertEqual('public', body['visibility'])
# unable to delete protected namespace
- self.assertRaises(lib_exc.Forbidden, self.client.delete_namespaces,
+ self.assertRaises(lib_exc.Forbidden, self.client.delete_namespace,
namespace_name)
# update the visibility to private and protected to False
- body = self.client.update_namespaces(namespace=namespace_name,
- description='Tempest',
- visibility='private',
- display_name=namespace_name,
- protected=False)
+ body = self.client.update_namespace(namespace=namespace_name,
+ description='Tempest',
+ visibility='private',
+ display_name=namespace_name,
+ protected=False)
self.assertEqual('private', body['visibility'])
self.assertEqual(False, body['protected'])
# now able to delete the non-protected namespace
- self.client.delete_namespaces(namespace_name)
+ self.client.delete_namespace(namespace_name)
def _cleanup_namespace(self, namespace_name):
# this is used to cleanup the resources
try:
- body = self.client.show_namespaces(namespace_name)
+ body = self.client.show_namespace(namespace_name)
self.assertEqual(namespace_name, body['namespace'])
- body = self.client.update_namespaces(namespace=namespace_name,
- description='Tempest',
- visibility='private',
- display_name=namespace_name,
- protected=False)
- self.client.delete_namespaces(namespace_name)
+ body = self.client.update_namespace(namespace=namespace_name,
+ description='Tempest',
+ visibility='private',
+ display_name=namespace_name,
+ protected=False)
+ self.client.delete_namespace(namespace_name)
except lib_exc.NotFound:
pass
diff --git a/tempest/api/messaging/base.py b/tempest/api/messaging/base.py
index 39dc7c3..528fbea 100644
--- a/tempest/api/messaging/base.py
+++ b/tempest/api/messaging/base.py
@@ -146,7 +146,7 @@
@classmethod
def release_claim(cls, claim_uri):
"""Wrapper utility that deletes a claim."""
- resp, body = cls.client.release_claim(claim_uri)
+ resp, body = cls.client.delete_claim(claim_uri)
return resp, body
diff --git a/tempest/api/messaging/test_claims.py b/tempest/api/messaging/test_claims.py
index e54bed1..57b8c7f 100644
--- a/tempest/api/messaging/test_claims.py
+++ b/tempest/api/messaging/test_claims.py
@@ -115,7 +115,7 @@
claim_uri = resp['location']
# Release Claim
- self.client.release_claim(claim_uri)
+ self.client.delete_claim(claim_uri)
# Delete Claimed message
# This will implicitly verify that the claim is deleted.
diff --git a/tempest/api/network/admin/test_external_network_extension.py b/tempest/api/network/admin/test_external_network_extension.py
index fce63ac..a32bfbc 100644
--- a/tempest/api/network/admin/test_external_network_extension.py
+++ b/tempest/api/network/admin/test_external_network_extension.py
@@ -94,8 +94,6 @@
# Verifies external network can be deleted while still holding
# (unassociated) floating IPs
- # Set cls.client to admin to use base.create_subnet()
- client = self.admin_client
body = self.admin_networks_client.create_network(
**{'router:external': True})
external_network = body['network']
@@ -105,19 +103,19 @@
subnet = self.create_subnet(
external_network, client=self.admin_subnets_client,
enable_dhcp=False)
- body = client.create_floatingip(
+ body = self.admin_floating_ips_client.create_floatingip(
floating_network_id=external_network['id'])
created_floating_ip = body['floatingip']
self.addCleanup(self._try_delete_resource,
- client.delete_floatingip,
+ self.admin_floating_ips_client.delete_floatingip,
created_floating_ip['id'])
- floatingip_list = client.list_floatingips(
+ floatingip_list = self.admin_floating_ips_client.list_floatingips(
network=external_network['id'])
self.assertIn(created_floating_ip['id'],
(f['id'] for f in floatingip_list['floatingips']))
self.admin_networks_client.delete_network(external_network['id'])
# Verifies floating ip is deleted
- floatingip_list = client.list_floatingips()
+ floatingip_list = self.admin_floating_ips_client.list_floatingips()
self.assertNotIn(created_floating_ip['id'],
(f['id'] for f in floatingip_list['floatingips']))
# Verifies subnet is deleted
diff --git a/tempest/api/network/admin/test_external_networks_negative.py b/tempest/api/network/admin/test_external_networks_negative.py
index 1e1573e..d031108 100644
--- a/tempest/api/network/admin/test_external_networks_negative.py
+++ b/tempest/api/network/admin/test_external_networks_negative.py
@@ -32,12 +32,11 @@
# pre-created floating-ip should be denied.
# create a floating ip
- client = self.admin_client
- body = client.create_floatingip(
+ body = self.admin_floating_ips_client.create_floatingip(
floating_network_id=CONF.network.public_network_id)
created_floating_ip = body['floatingip']
self.addCleanup(self._try_delete_resource,
- client.delete_floatingip,
+ self.admin_floating_ips_client.delete_floatingip,
created_floating_ip['id'])
floating_ip_address = created_floating_ip['floating_ip_address']
self.assertIsNotNone(floating_ip_address)
diff --git a/tempest/api/network/admin/test_floating_ips_admin_actions.py b/tempest/api/network/admin/test_floating_ips_admin_actions.py
index dfe7307..6ad374b 100644
--- a/tempest/api/network/admin/test_floating_ips_admin_actions.py
+++ b/tempest/api/network/admin/test_floating_ips_admin_actions.py
@@ -29,6 +29,7 @@
def setup_clients(cls):
super(FloatingIPAdminTestJSON, cls).setup_clients()
cls.alt_client = cls.alt_manager.network_client
+ cls.alt_floating_ips_client = cls.alt_manager.floating_ips_client
@classmethod
def resource_setup(cls):
@@ -45,18 +46,18 @@
@test.idempotent_id('64f2100b-5471-4ded-b46c-ddeeeb4f231b')
def test_list_floating_ips_from_admin_and_nonadmin(self):
# Create floating ip from admin user
- floating_ip_admin = self.admin_client.create_floatingip(
+ floating_ip_admin = self.admin_floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id)
- self.addCleanup(self.admin_client.delete_floatingip,
+ self.addCleanup(self.admin_floating_ips_client.delete_floatingip,
floating_ip_admin['floatingip']['id'])
# Create floating ip from alt user
- body = self.alt_client.create_floatingip(
+ body = self.alt_floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id)
floating_ip_alt = body['floatingip']
- self.addCleanup(self.alt_client.delete_floatingip,
+ self.addCleanup(self.alt_floating_ips_client.delete_floatingip,
floating_ip_alt['id'])
# List floating ips from admin
- body = self.admin_client.list_floatingips()
+ body = self.admin_floating_ips_client.list_floatingips()
floating_ip_ids_admin = [f['id'] for f in body['floatingips']]
# Check that admin sees all floating ips
self.assertIn(self.floating_ip['id'], floating_ip_ids_admin)
@@ -64,7 +65,7 @@
floating_ip_ids_admin)
self.assertIn(floating_ip_alt['id'], floating_ip_ids_admin)
# List floating ips from nonadmin
- body = self.client.list_floatingips()
+ body = self.floating_ips_client.list_floatingips()
floating_ip_ids = [f['id'] for f in body['floatingips']]
# Check that nonadmin user doesn't see floating ip created from admin
# and floating ip that is created in another tenant (alt user)
@@ -76,12 +77,12 @@
@test.idempotent_id('32727cc3-abe2-4485-a16e-48f2d54c14f2')
def test_create_list_show_floating_ip_with_tenant_id_by_admin(self):
# Creates a floating IP
- body = self.admin_client.create_floatingip(
+ body = self.admin_floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id,
tenant_id=self.network['tenant_id'],
port_id=self.port['id'])
created_floating_ip = body['floatingip']
- self.addCleanup(self.client.delete_floatingip,
+ self.addCleanup(self.floating_ips_client.delete_floatingip,
created_floating_ip['id'])
self.assertIsNotNone(created_floating_ip['id'])
self.assertIsNotNone(created_floating_ip['tenant_id'])
@@ -93,7 +94,7 @@
self.assertEqual(created_floating_ip['fixed_ip_address'],
port[0]['ip_address'])
# Verifies the details of a floating_ip
- floating_ip = self.admin_client.show_floatingip(
+ floating_ip = self.admin_floating_ips_client.show_floatingip(
created_floating_ip['id'])
shown_floating_ip = floating_ip['floatingip']
self.assertEqual(shown_floating_ip['id'], created_floating_ip['id'])
@@ -105,6 +106,6 @@
created_floating_ip['floating_ip_address'])
self.assertEqual(shown_floating_ip['port_id'], self.port['id'])
# Verify the floating ip exists in the list of all floating_ips
- floating_ips = self.admin_client.list_floatingips()
+ floating_ips = self.admin_floating_ips_client.list_floatingips()
floatingip_id_list = [f['id'] for f in floating_ips['floatingips']]
self.assertIn(created_floating_ip['id'], floatingip_id_list)
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
index d5556b8..36747a3 100644
--- a/tempest/api/network/admin/test_l3_agent_scheduler.py
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -97,7 +97,7 @@
l3_agent_ids = list()
self.admin_client.add_router_to_l3_agent(
self.agent['id'],
- self.router['id'])
+ router_id=self.router['id'])
body = (
self.admin_client.list_l3_agents_hosting_router(self.router['id']))
for agent in body['agents']:
diff --git a/tempest/api/network/admin/test_negative_quotas.py b/tempest/api/network/admin/test_negative_quotas.py
new file mode 100644
index 0000000..47da08c
--- /dev/null
+++ b/tempest/api/network/admin/test_negative_quotas.py
@@ -0,0 +1,69 @@
+# Copyright 2015 Cloudwatt
+# 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.network import base
+from tempest import test
+from tempest_lib import exceptions as lib_exc
+
+
+class QuotasNegativeTest(base.BaseAdminNetworkTest):
+ """Tests the following operations in the Neutron API:
+
+ set network quota and exceed this quota
+
+ v2.0 of the API is assumed.
+ It is also assumed that the per-tenant quota extension API is configured
+ in /etc/neutron/neutron.conf as follows:
+
+ quota_driver = neutron.db.quota_db.DbQuotaDriver
+ """
+ force_tenant_isolation = True
+
+ @classmethod
+ def skip_checks(cls):
+ super(QuotasNegativeTest, cls).skip_checks()
+ if not test.is_extension_enabled('quotas', 'network'):
+ msg = "quotas extension not enabled."
+ raise cls.skipException(msg)
+
+ @classmethod
+ def setup_clients(cls):
+ super(QuotasNegativeTest, cls).setup_clients()
+ cls.identity_admin_client = cls.os_adm.identity_client
+
+ @test.idempotent_id('644f4e1b-1bf9-4af0-9fd8-eb56ac0f51cf')
+ def test_network_quota_exceeding(self):
+ # Set the network quota to two
+ self.admin_quotas_client.update_quotas(self.networks_client.tenant_id,
+ network=2)
+ self.addCleanup(self.admin_quotas_client.reset_quotas,
+ self.networks_client.tenant_id)
+
+ # Create two networks
+ n1 = self.networks_client.create_network()
+ self.addCleanup(self.networks_client.delete_network,
+ n1['network']['id'])
+ n2 = self.networks_client.create_network()
+ self.addCleanup(self.networks_client.delete_network,
+ n2['network']['id'])
+
+ # Try to create a third network while the quota is two
+ with self.assertRaisesRegexp(
+ lib_exc.Conflict,
+ "An object with that identifier already exists\\n" +
+ "Details.*Quota exceeded for resources: \['network'\].*"):
+ n3 = self.networks_client.create_network()
+ self.addCleanup(self.networks_client.delete_network,
+ n3['network']['id'])
diff --git a/tempest/api/network/admin/test_quotas.py b/tempest/api/network/admin/test_quotas.py
index 4a25206..45d35cf 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -57,14 +57,14 @@
self.addCleanup(self.identity_utils.delete_project, project_id)
# Change quotas for tenant
- quota_set = self.admin_client.update_quotas(project_id,
- **new_quotas)['quota']
- self.addCleanup(self.admin_client.reset_quotas, project_id)
+ quota_set = self.admin_quotas_client.update_quotas(
+ project_id, **new_quotas)['quota']
+ self.addCleanup(self.admin_quotas_client.reset_quotas, project_id)
for key, value in six.iteritems(new_quotas):
self.assertEqual(value, quota_set[key])
# Confirm our tenant is listed among tenants with non default quotas
- non_default_quotas = self.admin_client.list_quotas()
+ non_default_quotas = self.admin_quotas_client.list_quotas()
found = False
for qs in non_default_quotas['quotas']:
if qs['tenant_id'] == project_id:
@@ -72,14 +72,14 @@
self.assertTrue(found)
# Confirm from API quotas were changed as requested for tenant
- quota_set = self.admin_client.show_quotas(project_id)
+ quota_set = self.admin_quotas_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(project_id)
- non_default_quotas = self.admin_client.list_quotas()
+ self.admin_quotas_client.reset_quotas(project_id)
+ non_default_quotas = self.admin_quotas_client.list_quotas()
for q in non_default_quotas['quotas']:
self.assertNotEqual(project_id, q['tenant_id'])
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 2c0b981..f1fd3e9 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -74,6 +74,8 @@
cls.networks_client = cls.os.networks_client
cls.subnets_client = cls.os.subnets_client
cls.ports_client = cls.os.ports_client
+ cls.quotas_client = cls.os.network_quotas_client
+ cls.floating_ips_client = cls.os.floating_ips_client
@classmethod
def resource_setup(cls):
@@ -92,18 +94,22 @@
if CONF.service_available.neutron:
# Clean up floating IPs
for floating_ip in cls.floating_ips:
- cls._try_delete_resource(cls.client.delete_floatingip,
- floating_ip['id'])
+ cls._try_delete_resource(
+ cls.floating_ips_client.delete_floatingip,
+ floating_ip['id'])
# Clean up metering label rules
+ # Not all classes in the hierarchy have the client class variable
+ if len(cls.metering_label_rules) > 0:
+ label_rules_client = cls.admin_metering_label_rules_client
for metering_label_rule in cls.metering_label_rules:
cls._try_delete_resource(
- cls.admin_client.delete_metering_label_rule,
+ label_rules_client.delete_metering_label_rule,
metering_label_rule['id'])
# Clean up metering labels
for metering_label in cls.metering_labels:
cls._try_delete_resource(
- cls.admin_client.delete_metering_label,
+ cls.admin_metering_labels_client.delete_metering_label,
metering_label['id'])
# Clean up ports
for port in cls.ports:
@@ -232,7 +238,7 @@
@classmethod
def create_floatingip(cls, external_network_id):
"""Wrapper utility that returns a test floating IP."""
- body = cls.client.create_floatingip(
+ body = cls.floating_ips_client.create_floatingip(
floating_network_id=external_network_id)
fip = body['floatingip']
cls.floating_ips.append(fip)
@@ -269,11 +275,16 @@
cls.admin_networks_client = cls.os_adm.networks_client
cls.admin_subnets_client = cls.os_adm.subnets_client
cls.admin_ports_client = cls.os_adm.ports_client
+ cls.admin_quotas_client = cls.os_adm.network_quotas_client
+ cls.admin_floating_ips_client = cls.os_adm.floating_ips_client
+ cls.admin_metering_labels_client = cls.os_adm.metering_labels_client
+ cls.admin_metering_label_rules_client = (
+ cls.os_adm.metering_label_rules_client)
@classmethod
def create_metering_label(cls, name, description):
"""Wrapper utility that returns a test metering label."""
- body = cls.admin_client.create_metering_label(
+ body = cls.admin_metering_labels_client.create_metering_label(
description=description,
name=data_utils.rand_name("metering-label"))
metering_label = body['metering_label']
@@ -284,7 +295,8 @@
def create_metering_label_rule(cls, remote_ip_prefix, direction,
metering_label_id):
"""Wrapper utility that returns a test metering label rule."""
- body = cls.admin_client.create_metering_label_rule(
+ client = cls.admin_metering_label_rules_client
+ body = client.create_metering_label_rule(
remote_ip_prefix=remote_ip_prefix, direction=direction,
metering_label_id=metering_label_id)
metering_label_rule = body['metering_label_rule']
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index ceb7906..74c1d51 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -126,7 +126,7 @@
):
kwargs = {'ipv6_ra_mode': ra_mode,
'ipv6_address_mode': add_mode}
- kwargs = {k: v for k, v in six.iteritems(kwargs) if v}
+ kwargs = dict((k, v) for k, v in six.iteritems(kwargs) if v)
real_ip, eui_ip = self._get_ips_from_subnet(**kwargs)
self._clean_network()
self.assertEqual(eui_ip, real_ip,
@@ -269,7 +269,7 @@
):
kwargs = {'ipv6_ra_mode': ra_mode,
'ipv6_address_mode': add_mode}
- kwargs = {k: v for k, v in six.iteritems(kwargs) if v}
+ kwargs = dict((k, v) for k, v in six.iteritems(kwargs) if v)
subnet = self.create_subnet(self.network, **kwargs)
port = self.create_port(self.network)
port_ip = next(iter(port['fixed_ips']), None)['ip_address']
@@ -291,7 +291,7 @@
):
kwargs = {'ipv6_ra_mode': ra_mode,
'ipv6_address_mode': add_mode}
- kwargs = {k: v for k, v in six.iteritems(kwargs) if v}
+ kwargs = dict((k, v) for k, v in six.iteritems(kwargs) if v)
subnet = self.create_subnet(self.network, **kwargs)
ip_range = netaddr.IPRange(subnet["allocation_pools"][0]["start"],
subnet["allocation_pools"][0]["end"])
@@ -366,7 +366,7 @@
):
kwargs = {'ipv6_ra_mode': ra_mode,
'ipv6_address_mode': add_mode}
- kwargs = {k: v for k, v in six.iteritems(kwargs) if v}
+ kwargs = dict((k, v) for k, v in six.iteritems(kwargs) if v)
subnet, port = self._create_subnet_router(kwargs)
port_ip = next(iter(port['fixed_ips']), None)['ip_address']
self._clean_network()
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index e9a553a..ce9c4be 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -68,11 +68,11 @@
@test.idempotent_id('62595970-ab1c-4b7f-8fcc-fddfe55e8718')
def test_create_list_show_update_delete_floating_ip(self):
# Creates a floating IP
- body = self.client.create_floatingip(
+ body = self.floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id,
port_id=self.ports[0]['id'])
created_floating_ip = body['floatingip']
- self.addCleanup(self.client.delete_floatingip,
+ self.addCleanup(self.floating_ips_client.delete_floatingip,
created_floating_ip['id'])
self.assertIsNotNone(created_floating_ip['id'])
self.assertIsNotNone(created_floating_ip['tenant_id'])
@@ -83,7 +83,8 @@
self.assertIn(created_floating_ip['fixed_ip_address'],
[ip['ip_address'] for ip in self.ports[0]['fixed_ips']])
# Verifies the details of a floating_ip
- floating_ip = self.client.show_floatingip(created_floating_ip['id'])
+ floating_ip = self.floating_ips_client.show_floatingip(
+ created_floating_ip['id'])
shown_floating_ip = floating_ip['floatingip']
self.assertEqual(shown_floating_ip['id'], created_floating_ip['id'])
self.assertEqual(shown_floating_ip['floating_network_id'],
@@ -95,13 +96,13 @@
self.assertEqual(shown_floating_ip['port_id'], self.ports[0]['id'])
# Verify the floating ip exists in the list of all floating_ips
- floating_ips = self.client.list_floatingips()
+ floating_ips = self.floating_ips_client.list_floatingips()
floatingip_id_list = list()
for f in floating_ips['floatingips']:
floatingip_id_list.append(f['id'])
self.assertIn(created_floating_ip['id'], floatingip_id_list)
# Associate floating IP to the other port
- floating_ip = self.client.update_floatingip(
+ floating_ip = self.floating_ips_client.update_floatingip(
created_floating_ip['id'],
port_id=self.ports[1]['id'])
updated_floating_ip = floating_ip['floatingip']
@@ -111,7 +112,7 @@
self.assertEqual(updated_floating_ip['router_id'], self.router['id'])
# Disassociate floating IP from the port
- floating_ip = self.client.update_floatingip(
+ floating_ip = self.floating_ips_client.update_floatingip(
created_floating_ip['id'],
port_id=None)
updated_floating_ip = floating_ip['floatingip']
@@ -122,21 +123,22 @@
@test.idempotent_id('e1f6bffd-442f-4668-b30e-df13f2705e77')
def test_floating_ip_delete_port(self):
# Create a floating IP
- body = self.client.create_floatingip(
+ body = self.floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id)
created_floating_ip = body['floatingip']
- self.addCleanup(self.client.delete_floatingip,
+ self.addCleanup(self.floating_ips_client.delete_floatingip,
created_floating_ip['id'])
# Create a port
port = self.ports_client.create_port(network_id=self.network['id'])
created_port = port['port']
- floating_ip = self.client.update_floatingip(
+ floating_ip = self.floating_ips_client.update_floatingip(
created_floating_ip['id'],
port_id=created_port['id'])
# Delete port
self.ports_client.delete_port(created_port['id'])
# Verifies the details of the floating_ip
- floating_ip = self.client.show_floatingip(created_floating_ip['id'])
+ floating_ip = self.floating_ips_client.show_floatingip(
+ created_floating_ip['id'])
shown_floating_ip = floating_ip['floatingip']
# Confirm the fields are back to None
self.assertEqual(shown_floating_ip['id'], created_floating_ip['id'])
@@ -147,11 +149,11 @@
@test.idempotent_id('1bb2f731-fe5a-4b8c-8409-799ade1bed4d')
def test_floating_ip_update_different_router(self):
# Associate a floating IP to a port on a router
- body = self.client.create_floatingip(
+ body = self.floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id,
port_id=self.ports[1]['id'])
created_floating_ip = body['floatingip']
- self.addCleanup(self.client.delete_floatingip,
+ self.addCleanup(self.floating_ips_client.delete_floatingip,
created_floating_ip['id'])
self.assertEqual(created_floating_ip['router_id'], self.router['id'])
network2 = self.create_network()
@@ -161,7 +163,7 @@
self.create_router_interface(router2['id'], subnet2['id'])
port_other_router = self.create_port(network2)
# Associate floating IP to the other port on another router
- floating_ip = self.client.update_floatingip(
+ floating_ip = self.floating_ips_client.update_floatingip(
created_floating_ip['id'],
port_id=port_other_router['id'])
updated_floating_ip = floating_ip['floatingip']
@@ -173,17 +175,17 @@
@test.attr(type='smoke')
@test.idempotent_id('36de4bd0-f09c-43e3-a8e1-1decc1ffd3a5')
def test_create_floating_ip_specifying_a_fixed_ip_address(self):
- body = self.client.create_floatingip(
+ body = self.floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id,
port_id=self.ports[1]['id'],
fixed_ip_address=self.ports[1]['fixed_ips'][0]['ip_address'])
created_floating_ip = body['floatingip']
- self.addCleanup(self.client.delete_floatingip,
+ self.addCleanup(self.floating_ips_client.delete_floatingip,
created_floating_ip['id'])
self.assertIsNotNone(created_floating_ip['id'])
self.assertEqual(created_floating_ip['fixed_ip_address'],
self.ports[1]['fixed_ips'][0]['ip_address'])
- floating_ip = self.client.update_floatingip(
+ floating_ip = self.floating_ips_client.update_floatingip(
created_floating_ip['id'],
port_id=None)
self.assertIsNone(floating_ip['floatingip']['port_id'])
@@ -200,18 +202,19 @@
port = body['port']
self.addCleanup(self.ports_client.delete_port, port['id'])
# Create floating ip
- body = self.client.create_floatingip(
+ body = self.floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id,
port_id=port['id'],
fixed_ip_address=list_ips[0])
floating_ip = body['floatingip']
- self.addCleanup(self.client.delete_floatingip, floating_ip['id'])
+ self.addCleanup(self.floating_ips_client.delete_floatingip,
+ floating_ip['id'])
self.assertIsNotNone(floating_ip['id'])
self.assertEqual(floating_ip['fixed_ip_address'], list_ips[0])
# Update floating ip
- body = self.client.update_floatingip(floating_ip['id'],
- port_id=port['id'],
- fixed_ip_address=list_ips[1])
+ body = self.floating_ips_client.update_floatingip(
+ floating_ip['id'], port_id=port['id'],
+ fixed_ip_address=list_ips[1])
update_floating_ip = body['floatingip']
self.assertEqual(update_floating_ip['fixed_ip_address'],
list_ips[1])
diff --git a/tempest/api/network/test_floating_ips_negative.py b/tempest/api/network/test_floating_ips_negative.py
index 5f56fec..f915615 100644
--- a/tempest/api/network/test_floating_ips_negative.py
+++ b/tempest/api/network/test_floating_ips_negative.py
@@ -53,17 +53,17 @@
@test.attr(type=['negative'])
@test.idempotent_id('22996ea8-4a81-4b27-b6e1-fa5df92fa5e8')
def test_create_floatingip_with_port_ext_net_unreachable(self):
- self.assertRaises(lib_exc.NotFound, self.client.create_floatingip,
- floating_network_id=self.ext_net_id,
- port_id=self.port['id'],
- fixed_ip_address=self.port['fixed_ips'][0]
- ['ip_address'])
+ self.assertRaises(
+ lib_exc.NotFound, self.floating_ips_client.create_floatingip,
+ floating_network_id=self.ext_net_id, port_id=self.port['id'],
+ fixed_ip_address=self.port['fixed_ips'][0]
+ ['ip_address'])
@test.attr(type=['negative'])
@test.idempotent_id('50b9aeb4-9f0b-48ee-aa31-fa955a48ff54')
def test_create_floatingip_in_private_network(self):
self.assertRaises(lib_exc.BadRequest,
- self.client.create_floatingip,
+ self.floating_ips_client.create_floatingip,
floating_network_id=self.network['id'],
port_id=self.port['id'],
fixed_ip_address=self.port['fixed_ips'][0]
@@ -73,12 +73,13 @@
@test.idempotent_id('6b3b8797-6d43-4191-985c-c48b773eb429')
def test_associate_floatingip_port_ext_net_unreachable(self):
# Create floating ip
- body = self.client.create_floatingip(
+ body = self.floating_ips_client.create_floatingip(
floating_network_id=self.ext_net_id)
floating_ip = body['floatingip']
- self.addCleanup(self.client.delete_floatingip, floating_ip['id'])
+ self.addCleanup(
+ self.floating_ips_client.delete_floatingip, floating_ip['id'])
# Associate floating IP to the other port
- self.assertRaises(lib_exc.NotFound, self.client.update_floatingip,
- floating_ip['id'], port_id=self.port['id'],
- fixed_ip_address=self.port['fixed_ips'][0]
- ['ip_address'])
+ self.assertRaises(
+ lib_exc.NotFound, self.floating_ips_client.update_floatingip,
+ floating_ip['id'], port_id=self.port['id'],
+ fixed_ip_address=self.port['fixed_ips'][0]['ip_address'])
diff --git a/tempest/api/network/test_metering_extensions.py b/tempest/api/network/test_metering_extensions.py
index a213f92..007ba3b 100644
--- a/tempest/api/network/test_metering_extensions.py
+++ b/tempest/api/network/test_metering_extensions.py
@@ -51,24 +51,25 @@
def _delete_metering_label(self, metering_label_id):
# Deletes a label and verifies if it is deleted or not
- self.admin_client.delete_metering_label(metering_label_id)
+ self.admin_metering_labels_client.delete_metering_label(
+ metering_label_id)
# Asserting that the label is not found in list after deletion
- labels = self.admin_client.list_metering_labels(id=metering_label_id)
+ labels = self.admin_metering_labels_client.list_metering_labels(
+ id=metering_label_id)
self.assertEqual(len(labels['metering_labels']), 0)
def _delete_metering_label_rule(self, metering_label_rule_id):
+ client = self.admin_metering_label_rules_client
# Deletes a rule and verifies if it is deleted or not
- self.admin_client.delete_metering_label_rule(
- metering_label_rule_id)
+ client.delete_metering_label_rule(metering_label_rule_id)
# Asserting that the rule is not found in list after deletion
- rules = (self.admin_client.list_metering_label_rules(
- id=metering_label_rule_id))
+ rules = client.list_metering_label_rules(id=metering_label_rule_id)
self.assertEqual(len(rules['metering_label_rules']), 0)
@test.idempotent_id('e2fb2f8c-45bf-429a-9f17-171c70444612')
def test_list_metering_labels(self):
# Verify label filtering
- body = self.admin_client.list_metering_labels(id=33)
+ body = self.admin_metering_labels_client.list_metering_labels(id=33)
metering_labels = body['metering_labels']
self.assertEqual(0, len(metering_labels))
@@ -77,21 +78,22 @@
# Creates a label
name = data_utils.rand_name('metering-label-')
description = "label created by tempest"
- body = self.admin_client.create_metering_label(name=name,
- description=description)
+ body = self.admin_metering_labels_client.create_metering_label(
+ name=name, description=description)
metering_label = body['metering_label']
self.addCleanup(self._delete_metering_label,
metering_label['id'])
# Assert whether created labels are found in labels list or fail
# if created labels are not found in labels list
- labels = (self.admin_client.list_metering_labels(
+ labels = (self.admin_metering_labels_client.list_metering_labels(
id=metering_label['id']))
self.assertEqual(len(labels['metering_labels']), 1)
@test.idempotent_id('30abb445-0eea-472e-bd02-8649f54a5968')
def test_show_metering_label(self):
# Verifies the details of a label
- body = self.admin_client.show_metering_label(self.metering_label['id'])
+ body = self.admin_metering_labels_client.show_metering_label(
+ self.metering_label['id'])
metering_label = body['metering_label']
self.assertEqual(self.metering_label['id'], metering_label['id'])
self.assertEqual(self.metering_label['tenant_id'],
@@ -102,8 +104,9 @@
@test.idempotent_id('cc832399-6681-493b-9d79-0202831a1281')
def test_list_metering_label_rules(self):
+ client = self.admin_metering_label_rules_client
# Verify rule filtering
- body = self.admin_client.list_metering_label_rules(id=33)
+ body = client.list_metering_label_rules(id=33)
metering_label_rules = body['metering_label_rules']
self.assertEqual(0, len(metering_label_rules))
@@ -112,7 +115,8 @@
# Creates a rule
remote_ip_prefix = ("10.0.1.0/24" if self._ip_version == 4
else "fd03::/64")
- body = (self.admin_client.create_metering_label_rule(
+ client = self.admin_metering_label_rules_client
+ body = (client.create_metering_label_rule(
remote_ip_prefix=remote_ip_prefix,
direction="ingress",
metering_label_id=self.metering_label['id']))
@@ -121,14 +125,14 @@
metering_label_rule['id'])
# Assert whether created rules are found in rules list or fail
# if created rules are not found in rules list
- rules = (self.admin_client.list_metering_label_rules(
- id=metering_label_rule['id']))
+ rules = client.list_metering_label_rules(id=metering_label_rule['id'])
self.assertEqual(len(rules['metering_label_rules']), 1)
@test.idempotent_id('b7354489-96ea-41f3-9452-bace120fb4a7')
def test_show_metering_label_rule(self):
# Verifies the details of a rule
- body = (self.admin_client.show_metering_label_rule(
+ client = self.admin_metering_label_rules_client
+ body = (client.show_metering_label_rule(
self.metering_label_rule['id']))
metering_label_rule = body['metering_label_rule']
self.assertEqual(self.metering_label_rule['id'],
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index a614c76..8466e11 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -89,7 +89,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)['output']
+ server_id)['output']
LOG.debug(output)
raise e
diff --git a/tempest/api/telemetry/base.py b/tempest/api/telemetry/base.py
index 81f00ec..bbd01f0 100644
--- a/tempest/api/telemetry/base.py
+++ b/tempest/api/telemetry/base.py
@@ -61,18 +61,9 @@
cls.glance_v2_notifications = ['image.download', 'image.serve']
cls.server_ids = []
- cls.alarm_ids = []
cls.image_ids = []
@classmethod
- def create_alarm(cls, **kwargs):
- body = cls.telemetry_client.create_alarm(
- name=data_utils.rand_name('telemetry_alarm'),
- type='threshold', **kwargs)
- cls.alarm_ids.append(body['alarm_id'])
- return body
-
- @classmethod
def create_server(cls):
tenant_network = cls.get_tenant_network()
body, server = compute.create_test_server(
@@ -106,7 +97,6 @@
@classmethod
def resource_cleanup(cls):
- cls.cleanup_resources(cls.telemetry_client.delete_alarm, cls.alarm_ids)
cls.cleanup_resources(cls.servers_client.delete_server, cls.server_ids)
cls.cleanup_resources(cls.image_client.delete_image, cls.image_ids)
super(BaseTelemetryTest, cls).resource_cleanup()
@@ -153,3 +143,46 @@
raise exceptions.TimeoutException(
'Event with query:%s has not been added to the '
'database within %d seconds' % (query, CONF.compute.build_timeout))
+
+
+class BaseAlarmingTest(tempest.test.BaseTestCase):
+ """Base test case class for all Alarming API tests."""
+
+ credentials = ['primary']
+
+ @classmethod
+ def skip_checks(cls):
+ super(BaseAlarmingTest, cls).skip_checks()
+ if not CONF.service_available.aodh:
+ raise cls.skipException("Aodh support is required")
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseAlarmingTest, cls).setup_clients()
+ cls.alarming_client = cls.os.alarming_client
+
+ @classmethod
+ def resource_setup(cls):
+ super(BaseAlarmingTest, cls).resource_setup()
+ cls.alarm_ids = []
+
+ @classmethod
+ def create_alarm(cls, **kwargs):
+ body = cls.alarming_client.create_alarm(
+ name=data_utils.rand_name('telemetry_alarm'),
+ type='threshold', **kwargs)
+ cls.alarm_ids.append(body['alarm_id'])
+ return body
+
+ @staticmethod
+ def cleanup_resources(method, list_of_ids):
+ for resource_id in list_of_ids:
+ try:
+ method(resource_id)
+ except lib_exc.NotFound:
+ pass
+
+ @classmethod
+ def resource_cleanup(cls):
+ cls.cleanup_resources(cls.alarming_client.delete_alarm, cls.alarm_ids)
+ super(BaseAlarmingTest, cls).resource_cleanup()
diff --git a/tempest/api/telemetry/test_telemetry_alarming_api.py b/tempest/api/telemetry/test_alarming_api.py
similarity index 80%
rename from tempest/api/telemetry/test_telemetry_alarming_api.py
rename to tempest/api/telemetry/test_alarming_api.py
index 6c84b98..daa0939 100644
--- a/tempest/api/telemetry/test_telemetry_alarming_api.py
+++ b/tempest/api/telemetry/test_alarming_api.py
@@ -17,7 +17,7 @@
from tempest import test
-class TelemetryAlarmingAPITestJSON(base.BaseTelemetryTest):
+class TelemetryAlarmingAPITestJSON(base.BaseAlarmingTest):
@classmethod
def resource_setup(cls):
@@ -32,7 +32,7 @@
@test.idempotent_id('1c918e06-210b-41eb-bd45-14676dd77cd6')
def test_alarm_list(self):
# List alarms
- alarm_list = self.telemetry_client.list_alarms()
+ alarm_list = self.alarming_client.list_alarms()
# Verify created alarm in the list
fetched_ids = [a['alarm_id'] for a in alarm_list]
@@ -46,7 +46,7 @@
def test_create_update_get_delete_alarm(self):
# Create an alarm
alarm_name = data_utils.rand_name('telemetry_alarm')
- body = self.telemetry_client.create_alarm(
+ body = self.alarming_client.create_alarm(
name=alarm_name, type='threshold', threshold_rule=self.rule)
self.assertEqual(alarm_name, body['name'])
alarm_id = body['alarm_id']
@@ -57,7 +57,7 @@
'threshold': 70.0,
'period': 60}
alarm_name_updated = data_utils.rand_name('telemetry-alarm-update')
- body = self.telemetry_client.update_alarm(
+ body = self.alarming_client.update_alarm(
alarm_id,
threshold_rule=new_rule,
name=alarm_name_updated,
@@ -65,19 +65,19 @@
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)
+ body = self.alarming_client.show_alarm(alarm_id)
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)
+ body = self.alarming_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.alarming_client.delete_alarm(alarm_id)
self.assertRaises(lib_exc.NotFound,
- self.telemetry_client.show_alarm, alarm_id)
+ self.alarming_client.show_alarm, alarm_id)
@test.idempotent_id('aca49486-70bb-4016-87e0-f6131374f741')
def test_set_get_alarm_state(self):
@@ -86,11 +86,11 @@
# Set alarm state and verify
new_state =\
[elem for elem in alarm_states if elem != alarm['state']][0]
- state = self.telemetry_client.alarm_set_state(alarm['alarm_id'],
- new_state)
+ state = self.alarming_client.alarm_set_state(alarm['alarm_id'],
+ new_state)
self.assertEqual(new_state, state.data)
# Get alarm state and verify
- state = self.telemetry_client.show_alarm_state(alarm['alarm_id'])
+ state = self.alarming_client.show_alarm_state(alarm['alarm_id'])
self.assertEqual(new_state, state.data)
@test.idempotent_id('08d7e45a-1344-4e5c-ba6f-f6cbb77f55b9')
@@ -99,13 +99,13 @@
"operator": "or"}
# Verifies alarm create
alarm_name = data_utils.rand_name('combination_alarm')
- body = self.telemetry_client.create_alarm(name=alarm_name,
- combination_rule=rule,
- type='combination')
+ body = self.alarming_client.create_alarm(name=alarm_name,
+ combination_rule=rule,
+ type='combination')
self.assertEqual(alarm_name, body['name'])
alarm_id = body['alarm_id']
self.assertDictContainsSubset(rule, body['combination_rule'])
# Verify alarm delete
- self.telemetry_client.delete_alarm(alarm_id)
+ self.alarming_client.delete_alarm(alarm_id)
self.assertRaises(lib_exc.NotFound,
- self.telemetry_client.show_alarm, alarm_id)
+ self.alarming_client.show_alarm, alarm_id)
diff --git a/tempest/api/telemetry/test_alarming_api_negative.py b/tempest/api/telemetry/test_alarming_api_negative.py
index 06753b0..e945556 100644
--- a/tempest/api/telemetry/test_alarming_api_negative.py
+++ b/tempest/api/telemetry/test_alarming_api_negative.py
@@ -20,7 +20,7 @@
import uuid
-class TelemetryAlarmingNegativeTest(base.BaseTelemetryTest):
+class TelemetryAlarmingNegativeTest(base.BaseAlarmingTest):
"""Negative tests for show_alarm, update_alarm, show_alarm_history tests
** show non-existent alarm
@@ -34,7 +34,7 @@
def test_get_non_existent_alarm(self):
# get the non-existent alarm
non_existent_id = str(uuid.uuid4())
- self.assertRaises(lib_exc.NotFound, self.telemetry_client.show_alarm,
+ self.assertRaises(lib_exc.NotFound, self.alarming_client.show_alarm,
non_existent_id)
@test.attr(type=['negative'])
@@ -46,14 +46,14 @@
'comparison_operator': 'eq',
'threshold': 100.0,
'period': 90}
- body = self.telemetry_client.create_alarm(
+ body = self.alarming_client.create_alarm(
name=alarm_name,
type='threshold',
threshold_rule=rule)
alarm_id = body['alarm_id']
- self.telemetry_client.delete_alarm(alarm_id)
+ self.alarming_client.delete_alarm(alarm_id)
# get the deleted alarm
- self.assertRaises(lib_exc.NotFound, self.telemetry_client.show_alarm,
+ self.assertRaises(lib_exc.NotFound, self.alarming_client.show_alarm,
alarm_id)
# update the deleted alarm
@@ -62,10 +62,10 @@
'comparison_operator': 'eq',
'threshold': 70,
'period': 50}
- self.assertRaises(lib_exc.NotFound, self.telemetry_client.update_alarm,
+ self.assertRaises(lib_exc.NotFound, self.alarming_client.update_alarm,
alarm_id, threshold_rule=updated_rule,
name=updated_alarm_name,
type='threshold')
# delete the deleted alarm
- self.assertRaises(lib_exc.NotFound, self.telemetry_client.delete_alarm,
+ self.assertRaises(lib_exc.NotFound, self.alarming_client.delete_alarm,
alarm_id)
diff --git a/tempest/api/telemetry/test_telemetry_notification_api.py b/tempest/api/telemetry/test_telemetry_notification_api.py
index 31eff9d..7511505 100644
--- a/tempest/api/telemetry/test_telemetry_notification_api.py
+++ b/tempest/api/telemetry/test_telemetry_notification_api.py
@@ -58,7 +58,7 @@
body = self.create_image(self.image_client_v2)
self.image_client_v2.store_image_file(body['id'], "file")
- self.image_client_v2.load_image_file(body['id'])
+ self.image_client_v2.show_image_file(body['id'])
query = 'resource', 'eq', body['id']
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index 4337922..6d2aaea 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -11,7 +11,7 @@
# under the License.
from oslo_log import log as logging
-
+import six
from tempest.api.volume import base
from tempest.common.utils import data_utils
from tempest import config
@@ -34,9 +34,14 @@
@classmethod
def resource_setup(cls):
super(VolumeMultiBackendV2Test, cls).resource_setup()
-
- cls.backend1_name = CONF.volume.backend1_name
- cls.backend2_name = CONF.volume.backend2_name
+ # support 2 backends names, deprecated_for_removal.
+ # keep support 2 backend names, in case they are not empty
+ if CONF.volume.backend1_name and CONF.volume.backend2_name:
+ cls.backend_names = {CONF.volume.backend1_name,
+ CONF.volume.backend2_name}
+ else:
+ # read backend name from a list .
+ cls.backend_names = set(CONF.volume.backend_names)
cls.name_field = cls.special_fields['name_field']
cls.volume_type_id_list = []
@@ -44,15 +49,15 @@
cls.volume_id_list_without_prefix = []
# Volume/Type creation (uses volume_backend_name)
- cls._create_type_and_volume(cls.backend1_name, False)
- # Volume/Type creation (uses capabilities:volume_backend_name)
- cls._create_type_and_volume(cls.backend1_name, True)
-
- if cls.backend1_name != cls.backend2_name:
- # Volume/Type creation (uses backend2_name)
- cls._create_type_and_volume(cls.backend2_name, False)
+ # It is not allowed to create the same backend name twice
+ if len(cls.backend_names) < 2:
+ raise cls.skipException("Requires at least two different "
+ "backend names")
+ for backend_name in cls.backend_names:
+ # Volume/Type creation (uses backend_name)
+ cls._create_type_and_volume(backend_name, False)
# Volume/Type creation (uses capabilities:volume_backend_name)
- cls._create_type_and_volume(cls.backend2_name, True)
+ cls._create_type_and_volume(backend_name, True)
@classmethod
def _create_type_and_volume(self, backend_name_key, with_prefix):
@@ -104,32 +109,28 @@
@test.idempotent_id('c1a41f3f-9dad-493e-9f09-3ff197d477cc')
def test_backend_name_reporting(self):
# get volume id which created by type without prefix
- volume_id = self.volume_id_list_without_prefix[0]
- self._test_backend_name_reporting_by_volume_id(volume_id)
+ for volume_id in self.volume_id_list_without_prefix:
+ self._test_backend_name_reporting_by_volume_id(volume_id)
@test.idempotent_id('f38e647f-ab42-4a31-a2e7-ca86a6485215')
def test_backend_name_reporting_with_prefix(self):
# get volume id which created by type with prefix
- volume_id = self.volume_id_list_with_prefix[0]
- self._test_backend_name_reporting_by_volume_id(volume_id)
+ for volume_id in self.volume_id_list_with_prefix:
+ self._test_backend_name_reporting_by_volume_id(volume_id)
@test.idempotent_id('46435ab1-a0af-4401-8373-f14e66b0dd58')
def test_backend_name_distinction(self):
- if self.backend1_name == self.backend2_name:
- raise self.skipException("backends configured with same name")
- # get volume id which created by type without prefix
- volume1_id = self.volume_id_list_without_prefix[0]
- volume2_id = self.volume_id_list_without_prefix[1]
- self._test_backend_name_distinction(volume1_id, volume2_id)
+ # get volume ids which created by type without prefix
+ self._test_backend_name_distinction(self.volume_id_list_without_prefix)
@test.idempotent_id('4236305b-b65a-4bfc-a9d2-69cb5b2bf2ed')
def test_backend_name_distinction_with_prefix(self):
- if self.backend1_name == self.backend2_name:
- raise self.skipException("backends configured with same name")
- # get volume id which created by type without prefix
- volume1_id = self.volume_id_list_with_prefix[0]
- volume2_id = self.volume_id_list_with_prefix[1]
- self._test_backend_name_distinction(volume1_id, volume2_id)
+ # get volume ids which created by type without prefix
+ self._test_backend_name_distinction(self.volume_id_list_with_prefix)
+
+ def _get_volume_host(self, volume_id):
+ return self.admin_volume_client.show_volume(
+ volume_id)['volume']['os-vol-host-attr:host']
def _test_backend_name_reporting_by_volume_id(self, volume_id):
# this test checks if os-vol-attr:host is populated correctly after
@@ -143,19 +144,16 @@
volume_id)
self.assertTrue(len(volume1_host.split("@")) > 1, msg)
- def _test_backend_name_distinction(self, volume1_id, volume2_id):
- # this test checks that the two volumes created at setUp don't
+ def _test_backend_name_distinction(self, volume_id_list):
+ # this test checks that the volumes created at setUp don't
# belong to the same backend (if they are, than the
# volume backend distinction is not working properly)
- volume = self.admin_volume_client.show_volume(volume1_id)['volume']
- volume1_host = volume['os-vol-host-attr:host']
-
- volume = self.admin_volume_client.show_volume(volume2_id)['volume']
- volume2_host = volume['os-vol-host-attr:host']
-
- msg = ("volumes %s and %s were created in the same backend" %
- (volume1_id, volume2_id))
- self.assertNotEqual(volume1_host, volume2_host, msg)
+ volume_hosts = [self._get_volume_host(volume) for volume in
+ volume_id_list]
+ # assert that volumes are each created on separate hosts:
+ msg = ("volumes %s were created in the same backend" % ", "
+ .join(volume_hosts))
+ six.assertCountEqual(self, volume_hosts, set(volume_hosts), msg)
class VolumeMultiBackendV1Test(VolumeMultiBackendV2Test):
diff --git a/tempest/api/volume/admin/test_volume_services.py b/tempest/api/volume/admin/test_volume_services.py
index 6692594..2b7ee45 100644
--- a/tempest/api/volume/admin/test_volume_services.py
+++ b/tempest/api/volume/admin/test_volume_services.py
@@ -39,9 +39,8 @@
@test.idempotent_id('63a3e1ca-37ee-4983-826d-83276a370d25')
def test_get_service_by_service_binary_name(self):
- params = {'binary': self.binary_name}
- services = (self.admin_volume_services_client.list_services(params)
- ['services'])
+ services = (self.admin_volume_services_client.list_services(
+ binary=self.binary_name)['services'])
self.assertNotEqual(0, len(services))
for service in services:
self.assertEqual(self.binary_name, service['binary'])
@@ -50,10 +49,9 @@
def test_get_service_by_host_name(self):
services_on_host = [service for service in self.services if
service['host'] == self.host_name]
- params = {'host': self.host_name}
- services = (self.admin_volume_services_client.list_services(params)
- ['services'])
+ services = (self.admin_volume_services_client.list_services(
+ host=self.host_name)['services'])
# we could have a periodic job checkin between the 2 service
# lookups, so only compare binary lists.
@@ -65,10 +63,10 @@
@test.idempotent_id('ffa6167c-4497-4944-a464-226bbdb53908')
def test_get_service_by_service_and_host_name(self):
- params = {'host': self.host_name, 'binary': self.binary_name}
- services = (self.admin_volume_services_client.list_services(params)
- ['services'])
+ services = (self.admin_volume_services_client.list_services(
+ host=self.host_name, binary=self.binary_name))['services']
+
self.assertEqual(1, len(services))
self.assertEqual(self.host_name, services[0]['host'])
self.assertEqual(self.binary_name, services[0]['binary'])
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index 0399413..ed34a9b 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -48,7 +48,7 @@
# Create backup
backup_name = data_utils.rand_name('Backup')
create_backup = self.backups_adm_client.create_backup
- backup = create_backup(self.volume['id'],
+ backup = create_backup(volume_id=self.volume['id'],
name=backup_name)['backup']
self.addCleanup(self.backups_adm_client.delete_backup,
backup['id'])
@@ -85,9 +85,8 @@
def test_volume_backup_export_import(self):
# Create backup
backup_name = data_utils.rand_name('Backup')
- backup = (self.backups_adm_client.create_backup(self.volume['id'],
- name=backup_name)
- ['backup'])
+ backup = (self.backups_adm_client.create_backup(
+ volume_id=self.volume['id'], name=backup_name)['backup'])
self.addCleanup(self._delete_backup, backup['id'])
self.assertEqual(backup_name, backup['name'])
self.backups_adm_client.wait_for_backup_status(backup['id'],
diff --git a/tempest/api_schema/response/compute/v2_1/agents.py b/tempest/api_schema/response/compute/v2_1/agents.py
deleted file mode 100644
index da38198..0000000
--- a/tempest/api_schema/response/compute/v2_1/agents.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright 2014 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.
-
-common_agent_info = {
- 'type': 'object',
- 'properties': {
- 'agent_id': {'type': ['integer', 'string']},
- 'hypervisor': {'type': 'string'},
- 'os': {'type': 'string'},
- 'architecture': {'type': 'string'},
- 'version': {'type': 'string'},
- 'url': {'type': 'string', 'format': 'uri'},
- 'md5hash': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['agent_id', 'hypervisor', 'os', 'architecture',
- 'version', 'url', 'md5hash']
-}
-
-list_agents = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'agents': {
- 'type': 'array',
- 'items': common_agent_info
- }
- },
- 'additionalProperties': False,
- 'required': ['agents']
- }
-}
-
-create_agent = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'agent': common_agent_info
- },
- 'additionalProperties': False,
- 'required': ['agent']
- }
-}
-
-delete_agent = {
- 'status_code': [200]
-}
diff --git a/tempest/api_schema/response/compute/v2_1/images.py b/tempest/api_schema/response/compute/v2_1/images.py
deleted file mode 100644
index a513dcb..0000000
--- a/tempest/api_schema/response/compute/v2_1/images.py
+++ /dev/null
@@ -1,154 +0,0 @@
-# Copyright 2014 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 tempest.api_schema.response.compute.v2_1 import parameter_types
-
-image_links = copy.deepcopy(parameter_types.links)
-image_links['items']['properties'].update({'type': {'type': 'string'}})
-
-common_image_schema = {
- 'type': 'object',
- 'properties': {
- 'id': {'type': 'string'},
- 'status': {'type': 'string'},
- 'updated': {'type': 'string'},
- 'links': image_links,
- 'name': {'type': 'string'},
- 'created': {'type': 'string'},
- 'minDisk': {'type': 'integer'},
- 'minRam': {'type': 'integer'},
- 'progress': {'type': 'integer'},
- 'metadata': {'type': 'object'},
- 'server': {
- 'type': 'object',
- 'properties': {
- 'id': {'type': 'string'},
- 'links': parameter_types.links
- },
- 'additionalProperties': False,
- 'required': ['id', 'links']
- },
- 'OS-EXT-IMG-SIZE:size': {'type': 'integer'},
- 'OS-DCF:diskConfig': {'type': 'string'}
- },
- 'additionalProperties': False,
- # 'server' attributes only comes in response body if image is
- # associated with any server. 'OS-EXT-IMG-SIZE:size' & 'OS-DCF:diskConfig'
- # are API extension, So those are not defined as 'required'.
- 'required': ['id', 'status', 'updated', 'links', 'name',
- 'created', 'minDisk', 'minRam', 'progress',
- 'metadata']
-}
-
-get_image = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'image': common_image_schema
- },
- 'additionalProperties': False,
- 'required': ['image']
- }
-}
-
-list_images = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'images': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'id': {'type': 'string'},
- 'links': image_links,
- 'name': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['id', 'links', 'name']
- }
- },
- 'images_links': parameter_types.links
- },
- 'additionalProperties': False,
- # NOTE(gmann): images_links attribute is not necessary to be
- # present always So it is not 'required'.
- 'required': ['images']
- }
-}
-
-create_image = {
- 'status_code': [202],
- 'response_header': {
- 'type': 'object',
- 'properties': parameter_types.response_header
- }
-}
-create_image['response_header']['properties'].update(
- {'location': {
- 'type': 'string',
- 'format': 'uri'}
- }
-)
-create_image['response_header']['required'] = ['location']
-
-delete = {
- 'status_code': [204]
-}
-
-image_metadata = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'metadata': {'type': 'object'}
- },
- 'additionalProperties': False,
- 'required': ['metadata']
- }
-}
-
-image_meta_item = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'meta': {'type': 'object'}
- },
- 'additionalProperties': False,
- 'required': ['meta']
- }
-}
-
-list_images_details = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'images': {
- 'type': 'array',
- 'items': common_image_schema
- },
- 'images_links': parameter_types.links
- },
- 'additionalProperties': False,
- # NOTE(gmann): images_links attribute is not necessary to be
- # present always So it is not 'required'.
- 'required': ['images']
- }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/instance_usage_audit_logs.py b/tempest/api_schema/response/compute/v2_1/instance_usage_audit_logs.py
deleted file mode 100644
index c6c4deb..0000000
--- a/tempest/api_schema/response/compute/v2_1/instance_usage_audit_logs.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright 2014 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.
-
-common_instance_usage_audit_log = {
- 'type': 'object',
- 'properties': {
- 'hosts_not_run': {
- 'type': 'array',
- 'items': {'type': 'string'}
- },
- 'log': {'type': 'object'},
- 'num_hosts': {'type': 'integer'},
- 'num_hosts_done': {'type': 'integer'},
- 'num_hosts_not_run': {'type': 'integer'},
- 'num_hosts_running': {'type': 'integer'},
- 'overall_status': {'type': 'string'},
- 'period_beginning': {'type': 'string'},
- 'period_ending': {'type': 'string'},
- 'total_errors': {'type': 'integer'},
- 'total_instances': {'type': 'integer'}
- },
- 'additionalProperties': False,
- 'required': ['hosts_not_run', 'log', 'num_hosts', 'num_hosts_done',
- 'num_hosts_not_run', 'num_hosts_running', 'overall_status',
- 'period_beginning', 'period_ending', 'total_errors',
- 'total_instances']
-}
-
-get_instance_usage_audit_log = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'instance_usage_audit_log': common_instance_usage_audit_log
- },
- 'additionalProperties': False,
- 'required': ['instance_usage_audit_log']
- }
-}
-
-list_instance_usage_audit_log = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'instance_usage_audit_logs': common_instance_usage_audit_log
- },
- 'additionalProperties': False,
- 'required': ['instance_usage_audit_logs']
- }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/interfaces.py b/tempest/api_schema/response/compute/v2_1/interfaces.py
deleted file mode 100644
index 130775b..0000000
--- a/tempest/api_schema/response/compute/v2_1/interfaces.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright 2014 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.api_schema.response.compute.v2_1 import parameter_types
-
-interface_common_info = {
- 'type': 'object',
- 'properties': {
- 'port_state': {'type': 'string'},
- 'fixed_ips': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'subnet_id': {
- 'type': 'string',
- 'format': 'uuid'
- },
- 'ip_address': parameter_types.ip_address
- },
- 'additionalProperties': False,
- 'required': ['subnet_id', 'ip_address']
- }
- },
- 'port_id': {'type': 'string', 'format': 'uuid'},
- 'net_id': {'type': 'string', 'format': 'uuid'},
- 'mac_addr': parameter_types.mac_address
- },
- 'additionalProperties': False,
- 'required': ['port_state', 'fixed_ips', 'port_id', 'net_id', 'mac_addr']
-}
-
-get_create_interfaces = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'interfaceAttachment': interface_common_info
- },
- 'additionalProperties': False,
- 'required': ['interfaceAttachment']
- }
-}
-
-list_interfaces = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'interfaceAttachments': {
- 'type': 'array',
- 'items': interface_common_info
- }
- },
- 'additionalProperties': False,
- 'required': ['interfaceAttachments']
- }
-}
-
-delete_interface = {
- 'status_code': [202]
-}
diff --git a/tempest/api_schema/response/compute/v2_1/limits.py b/tempest/api_schema/response/compute/v2_1/limits.py
deleted file mode 100644
index 81f175f..0000000
--- a/tempest/api_schema/response/compute/v2_1/limits.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# Copyright 2014 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.
-
-get_limit = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'limits': {
- 'type': 'object',
- 'properties': {
- 'absolute': {
- 'type': 'object',
- 'properties': {
- 'maxTotalRAMSize': {'type': 'integer'},
- 'totalCoresUsed': {'type': 'integer'},
- 'maxTotalInstances': {'type': 'integer'},
- 'maxTotalFloatingIps': {'type': 'integer'},
- 'totalSecurityGroupsUsed': {'type': 'integer'},
- 'maxTotalCores': {'type': 'integer'},
- 'totalFloatingIpsUsed': {'type': 'integer'},
- 'maxSecurityGroups': {'type': 'integer'},
- 'maxServerMeta': {'type': 'integer'},
- 'maxPersonality': {'type': 'integer'},
- 'maxImageMeta': {'type': 'integer'},
- 'maxPersonalitySize': {'type': 'integer'},
- 'maxSecurityGroupRules': {'type': 'integer'},
- 'maxTotalKeypairs': {'type': 'integer'},
- 'totalRAMUsed': {'type': 'integer'},
- 'totalInstancesUsed': {'type': 'integer'},
- 'maxServerGroupMembers': {'type': 'integer'},
- 'maxServerGroups': {'type': 'integer'},
- 'totalServerGroupsUsed': {'type': 'integer'}
- },
- 'additionalProperties': False,
- # NOTE(gmann): maxServerGroupMembers, maxServerGroups
- # and totalServerGroupsUsed are API extension,
- # and some environments return a response without these
- # attributes.So they are not 'required'.
- 'required': ['maxImageMeta',
- 'maxPersonality',
- 'maxPersonalitySize',
- 'maxSecurityGroupRules',
- 'maxSecurityGroups',
- 'maxServerMeta',
- 'maxTotalCores',
- 'maxTotalFloatingIps',
- 'maxTotalInstances',
- 'maxTotalKeypairs',
- 'maxTotalRAMSize',
- 'totalCoresUsed',
- 'totalFloatingIpsUsed',
- 'totalInstancesUsed',
- 'totalRAMUsed',
- 'totalSecurityGroupsUsed']
- },
- 'rate': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'limit': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'next-available':
- {'type': 'string'},
- 'remaining':
- {'type': 'integer'},
- 'unit':
- {'type': 'string'},
- 'value':
- {'type': 'integer'},
- 'verb':
- {'type': 'string'}
- },
- 'additionalProperties': False,
- }
- },
- 'regex': {'type': 'string'},
- 'uri': {'type': 'string'}
- },
- 'additionalProperties': False,
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['absolute', 'rate']
- }
- },
- 'additionalProperties': False,
- 'required': ['limits']
- }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/migrations.py b/tempest/api_schema/response/compute/v2_1/migrations.py
deleted file mode 100644
index b7d66ea..0000000
--- a/tempest/api_schema/response/compute/v2_1/migrations.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2014 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.
-
-list_migrations = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'migrations': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'id': {'type': 'integer'},
- 'status': {'type': ['string', 'null']},
- 'instance_uuid': {'type': ['string', 'null']},
- 'source_node': {'type': ['string', 'null']},
- 'source_compute': {'type': ['string', 'null']},
- 'dest_node': {'type': ['string', 'null']},
- 'dest_compute': {'type': ['string', 'null']},
- 'dest_host': {'type': ['string', 'null']},
- 'old_instance_type_id': {'type': ['integer', 'null']},
- 'new_instance_type_id': {'type': ['integer', 'null']},
- 'created_at': {'type': 'string'},
- 'updated_at': {'type': ['string', 'null']}
- },
- 'additionalProperties': False,
- 'required': [
- 'id', 'status', 'instance_uuid', 'source_node',
- 'source_compute', 'dest_node', 'dest_compute',
- 'dest_host', 'old_instance_type_id',
- 'new_instance_type_id', 'created_at', 'updated_at'
- ]
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['migrations']
- }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/quota_classes.py b/tempest/api_schema/response/compute/v2_1/quota_classes.py
deleted file mode 100644
index a0cdaf5..0000000
--- a/tempest/api_schema/response/compute/v2_1/quota_classes.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2014 IBM 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 tempest.api_schema.response.compute.v2_1 import quotas
-
-# NOTE(mriedem): os-quota-class-sets responses are the same as os-quota-sets
-# except for the key in the response body is quota_class_set instead of
-# quota_set, so update this copy of the schema from os-quota-sets.
-get_quota_class_set = copy.deepcopy(quotas.get_quota_set)
-get_quota_class_set['response_body']['properties']['quota_class_set'] = (
- get_quota_class_set['response_body']['properties'].pop('quota_set'))
-get_quota_class_set['response_body']['required'] = ['quota_class_set']
-
-update_quota_class_set = copy.deepcopy(quotas.update_quota_set)
-update_quota_class_set['response_body']['properties']['quota_class_set'] = (
- update_quota_class_set['response_body']['properties'].pop('quota_set'))
-update_quota_class_set['response_body']['required'] = ['quota_class_set']
diff --git a/tempest/api_schema/response/compute/v2_1/quotas.py b/tempest/api_schema/response/compute/v2_1/quotas.py
deleted file mode 100644
index 7953983..0000000
--- a/tempest/api_schema/response/compute/v2_1/quotas.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright 2014 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
-
-update_quota_set = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'quota_set': {
- 'type': 'object',
- 'properties': {
- 'instances': {'type': 'integer'},
- 'cores': {'type': 'integer'},
- 'ram': {'type': 'integer'},
- 'floating_ips': {'type': 'integer'},
- 'fixed_ips': {'type': 'integer'},
- 'metadata_items': {'type': 'integer'},
- 'key_pairs': {'type': 'integer'},
- 'security_groups': {'type': 'integer'},
- 'security_group_rules': {'type': 'integer'},
- 'server_group_members': {'type': 'integer'},
- 'server_groups': {'type': 'integer'},
- 'injected_files': {'type': 'integer'},
- 'injected_file_content_bytes': {'type': 'integer'},
- 'injected_file_path_bytes': {'type': 'integer'}
- },
- 'additionalProperties': False,
- # NOTE: server_group_members and server_groups are represented
- # when enabling quota_server_group extension. So they should
- # not be required.
- 'required': ['instances', 'cores', 'ram',
- 'floating_ips', 'fixed_ips',
- 'metadata_items', 'key_pairs',
- 'security_groups', 'security_group_rules',
- 'injected_files', 'injected_file_content_bytes',
- 'injected_file_path_bytes']
- }
- },
- 'additionalProperties': False,
- 'required': ['quota_set']
- }
-}
-
-get_quota_set = copy.deepcopy(update_quota_set)
-get_quota_set['response_body']['properties']['quota_set']['properties'][
- 'id'] = {'type': 'string'}
-get_quota_set['response_body']['properties']['quota_set']['required'].extend([
- 'id'])
-
-delete_quota = {
- 'status_code': [202]
-}
diff --git a/tempest/api_schema/response/compute/v2_1/security_group_default_rule.py b/tempest/api_schema/response/compute/v2_1/security_group_default_rule.py
deleted file mode 100644
index 2ec2826..0000000
--- a/tempest/api_schema/response/compute/v2_1/security_group_default_rule.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright 2014 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.
-
-common_security_group_default_rule_info = {
- 'type': 'object',
- 'properties': {
- 'from_port': {'type': 'integer'},
- 'id': {'type': 'integer'},
- 'ip_protocol': {'type': 'string'},
- 'ip_range': {
- 'type': 'object',
- 'properties': {
- 'cidr': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['cidr'],
- },
- 'to_port': {'type': 'integer'},
- },
- 'additionalProperties': False,
- 'required': ['from_port', 'id', 'ip_protocol', 'ip_range', 'to_port'],
-}
-
-create_get_security_group_default_rule = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'security_group_default_rule':
- common_security_group_default_rule_info
- },
- 'additionalProperties': False,
- 'required': ['security_group_default_rule']
- }
-}
-
-delete_security_group_default_rule = {
- 'status_code': [204]
-}
-
-list_security_group_default_rules = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'security_group_default_rules': {
- 'type': 'array',
- 'items': common_security_group_default_rule_info
- }
- },
- 'additionalProperties': False,
- 'required': ['security_group_default_rules']
- }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/servers.py b/tempest/api_schema/response/compute/v2_1/servers.py
index 9593f3c..38f7c82 100644
--- a/tempest/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/api_schema/response/compute/v2_1/servers.py
@@ -291,8 +291,8 @@
'status_code': [202]
}
-get_volume_attachment = copy.deepcopy(attach_volume)
-get_volume_attachment['response_body']['properties'][
+show_volume_attachment = copy.deepcopy(attach_volume)
+show_volume_attachment['response_body']['properties'][
'volumeAttachment']['properties'].update({'serverId': {'type': 'string'}})
list_volume_attachments = {
@@ -436,7 +436,7 @@
# 'events' does not come in response body always so it is not
# defined as 'required'
-get_instance_action = {
+show_instance_action = {
'status_code': [200],
'response_body': {
'type': 'object',
@@ -448,7 +448,7 @@
}
}
-get_password = {
+show_password = {
'status_code': [200],
'response_body': {
'type': 'object',
@@ -520,7 +520,7 @@
'status_code': [204]
}
-set_get_server_metadata_item = {
+set_show_server_metadata_item = {
'status_code': [200],
'response_body': {
'type': 'object',
diff --git a/tempest/api_schema/response/compute/v2_1/services.py b/tempest/api_schema/response/compute/v2_1/services.py
deleted file mode 100644
index ddef7b2..0000000
--- a/tempest/api_schema/response/compute/v2_1/services.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright 2014 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.
-
-list_services = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'services': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'id': {'type': ['integer', 'string'],
- 'pattern': '^[a-zA-Z!]*@[0-9]+$'},
- 'zone': {'type': 'string'},
- 'host': {'type': 'string'},
- 'state': {'type': 'string'},
- 'binary': {'type': 'string'},
- 'status': {'type': 'string'},
- 'updated_at': {'type': ['string', 'null']},
- 'disabled_reason': {'type': ['string', 'null']}
- },
- 'additionalProperties': False,
- 'required': ['id', 'zone', 'host', 'state', 'binary',
- 'status', 'updated_at', 'disabled_reason']
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['services']
- }
-}
-
-enable_disable_service = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'service': {
- 'type': 'object',
- 'properties': {
- 'status': {'type': 'string'},
- 'binary': {'type': 'string'},
- 'host': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['status', 'binary', 'host']
- }
- },
- 'additionalProperties': False,
- 'required': ['service']
- }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/snapshots.py b/tempest/api_schema/response/compute/v2_1/snapshots.py
deleted file mode 100644
index 01a524b..0000000
--- a/tempest/api_schema/response/compute/v2_1/snapshots.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# 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/tenant_networks.py b/tempest/api_schema/response/compute/v2_1/tenant_networks.py
deleted file mode 100644
index ddfab96..0000000
--- a/tempest/api_schema/response/compute/v2_1/tenant_networks.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# 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.
-
-param_network = {
- 'type': 'object',
- 'properties': {
- 'id': {'type': 'string'},
- 'cidr': {'type': ['string', 'null']},
- 'label': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['id', 'cidr', 'label']
-}
-
-
-list_tenant_networks = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'networks': {
- 'type': 'array',
- 'items': param_network
- }
- },
- 'additionalProperties': False,
- 'required': ['networks']
- }
-}
-
-
-get_tenant_network = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'network': param_network
- },
- 'additionalProperties': False,
- 'required': ['network']
- }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/tenant_usages.py b/tempest/api_schema/response/compute/v2_1/tenant_usages.py
deleted file mode 100644
index d51ef12..0000000
--- a/tempest/api_schema/response/compute/v2_1/tenant_usages.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# Copyright 2014 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
-
-_server_usages = {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'ended_at': {
- 'oneOf': [
- {'type': 'string'},
- {'type': 'null'}
- ]
- },
- 'flavor': {'type': 'string'},
- 'hours': {'type': 'number'},
- 'instance_id': {'type': 'string'},
- 'local_gb': {'type': 'integer'},
- 'memory_mb': {'type': 'integer'},
- 'name': {'type': 'string'},
- 'started_at': {'type': 'string'},
- 'state': {'type': 'string'},
- 'tenant_id': {'type': 'string'},
- 'uptime': {'type': 'integer'},
- 'vcpus': {'type': 'integer'},
- },
- 'required': ['ended_at', 'flavor', 'hours', 'instance_id', 'local_gb',
- 'memory_mb', 'name', 'started_at', 'state', 'tenant_id',
- 'uptime', 'vcpus']
- }
-}
-
-_tenant_usage_list = {
- 'type': 'object',
- 'properties': {
- 'server_usages': _server_usages,
- 'start': {'type': 'string'},
- 'stop': {'type': 'string'},
- 'tenant_id': {'type': 'string'},
- 'total_hours': {'type': 'number'},
- 'total_local_gb_usage': {'type': 'number'},
- 'total_memory_mb_usage': {'type': 'number'},
- 'total_vcpus_usage': {'type': 'number'},
- },
- 'required': ['start', 'stop', 'tenant_id',
- 'total_hours', 'total_local_gb_usage',
- 'total_memory_mb_usage', 'total_vcpus_usage']
-}
-
-# 'required' of get_tenant is different from list_tenant's.
-_tenant_usage_get = copy.deepcopy(_tenant_usage_list)
-_tenant_usage_get['required'] = ['server_usages', 'start', 'stop', 'tenant_id',
- 'total_hours', 'total_local_gb_usage',
- 'total_memory_mb_usage', 'total_vcpus_usage']
-
-list_tenant_usage = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'tenant_usages': {
- 'type': 'array',
- 'items': _tenant_usage_list
- }
- },
- 'required': ['tenant_usages']
- }
-}
-
-get_tenant_usage = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'tenant_usage': _tenant_usage_get
- },
- 'required': ['tenant_usage']
- }
-}
diff --git a/tempest/api_schema/response/compute/v2_1/versions.py b/tempest/api_schema/response/compute/v2_1/versions.py
deleted file mode 100644
index 08a9fab..0000000
--- a/tempest/api_schema/response/compute/v2_1/versions.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# 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
-
-
-_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': {
- 'type': 'object',
- 'properties': {
- 'versions': {
- 'type': 'array',
- '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/api_schema/response/compute/v2_1/volumes.py b/tempest/api_schema/response/compute/v2_1/volumes.py
deleted file mode 100644
index bb34acb..0000000
--- a/tempest/api_schema/response/compute/v2_1/volumes.py
+++ /dev/null
@@ -1,120 +0,0 @@
-# Copyright 2014 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.
-
-create_get_volume = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'volume': {
- 'type': 'object',
- 'properties': {
- 'id': {'type': 'string'},
- 'status': {'type': 'string'},
- 'displayName': {'type': ['string', 'null']},
- 'availabilityZone': {'type': 'string'},
- 'createdAt': {'type': 'string'},
- 'displayDescription': {'type': ['string', 'null']},
- 'volumeType': {'type': ['string', 'null']},
- 'snapshotId': {'type': ['string', 'null']},
- 'metadata': {'type': 'object'},
- 'size': {'type': 'integer'},
- 'attachments': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'id': {'type': 'string'},
- 'device': {'type': 'string'},
- 'volumeId': {'type': 'string'},
- 'serverId': {'type': 'string'}
- },
- 'additionalProperties': False,
- # NOTE- If volume is not attached to any server
- # then, 'attachments' attributes comes as array
- # with empty objects "[{}]" due to that elements
- # of 'attachments' cannot defined as 'required'.
- # If it would come as empty array "[]" then,
- # those elements can be defined as 'required'.
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['id', 'status', 'displayName', 'availabilityZone',
- 'createdAt', 'displayDescription', 'volumeType',
- 'snapshotId', 'metadata', 'size', 'attachments']
- }
- },
- 'additionalProperties': False,
- 'required': ['volume']
- }
-}
-
-list_volumes = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'volumes': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'id': {'type': 'string'},
- 'status': {'type': 'string'},
- 'displayName': {'type': ['string', 'null']},
- 'availabilityZone': {'type': 'string'},
- 'createdAt': {'type': 'string'},
- 'displayDescription': {'type': ['string', 'null']},
- 'volumeType': {'type': ['string', 'null']},
- 'snapshotId': {'type': ['string', 'null']},
- 'metadata': {'type': 'object'},
- 'size': {'type': 'integer'},
- 'attachments': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'id': {'type': 'string'},
- 'device': {'type': 'string'},
- 'volumeId': {'type': 'string'},
- 'serverId': {'type': 'string'}
- },
- 'additionalProperties': False,
- # NOTE- If volume is not attached to any server
- # then, 'attachments' attributes comes as array
- # with empty object "[{}]" due to that elements
- # of 'attachments' cannot defined as 'required'
- # If it would come as empty array "[]" then,
- # those elements can be defined as 'required'.
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['id', 'status', 'displayName',
- 'availabilityZone', 'createdAt',
- 'displayDescription', 'volumeType',
- 'snapshotId', 'metadata', 'size',
- 'attachments']
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['volumes']
- }
-}
-
-delete_volume = {
- 'status_code': [202]
-}
diff --git a/tempest/clients.py b/tempest/clients.py
index 3fb4c22..74f8684 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -35,6 +35,32 @@
from tempest_lib.services.compute.hosts_client import HostsClient
from tempest_lib.services.compute.hypervisor_client import \
HypervisorClient
+from tempest_lib.services.compute.images_client import ImagesClient \
+ as ComputeImagesClient
+from tempest_lib.services.compute.instance_usage_audit_log_client import \
+ InstanceUsagesAuditLogClient
+from tempest_lib.services.compute.interfaces_client import InterfacesClient
+from tempest_lib.services.compute.limits_client import LimitsClient
+from tempest_lib.services.compute.migrations_client import MigrationsClient
+from tempest_lib.services.compute.networks_client import NetworksClient \
+ as ComputeNetworksClient
+from tempest_lib.services.compute.quota_classes_client import \
+ QuotaClassesClient
+from tempest_lib.services.compute.quotas_client import QuotasClient
+from tempest_lib.services.compute.security_group_default_rules_client import \
+ SecurityGroupDefaultRulesClient
+from tempest_lib.services.compute.security_groups_client import \
+ SecurityGroupsClient as ComputeSecurityGroupsClient
+from tempest_lib.services.compute.services_client import ServicesClient
+from tempest_lib.services.compute.snapshots_client import \
+ SnapshotsClient as ComputeSnapshotsClient
+from tempest_lib.services.compute.tenant_networks_client import \
+ TenantNetworksClient
+from tempest_lib.services.compute.tenant_usages_client import \
+ TenantUsagesClient
+from tempest_lib.services.compute.versions_client import VersionsClient
+from tempest_lib.services.compute.volumes_client import \
+ VolumesClient as ComputeVolumesClient
from tempest_lib.services.identity.v2.token_client import TokenClient
from tempest_lib.services.identity.v3.token_client import V3TokenClient
@@ -47,39 +73,12 @@
from tempest.services import botoclients
from tempest.services.compute.json.floating_ips_client import \
FloatingIPsClient as ComputeFloatingIPsClient
-from tempest.services.compute.json.images_client import ImagesClient
-from tempest.services.compute.json.instance_usage_audit_log_client import \
- InstanceUsagesAuditLogClient
-from tempest.services.compute.json.interfaces_client import \
- InterfacesClient
from tempest.services.compute.json.keypairs_client import KeyPairsClient
-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 \
- as ComputeNetworksClient
-from tempest.services.compute.json.quota_classes_client import \
- QuotaClassesClient
-from tempest.services.compute.json.quotas_client import QuotasClient
-from tempest.services.compute.json.security_group_default_rules_client import \
- SecurityGroupDefaultRulesClient
from tempest.services.compute.json.security_group_rules_client import \
SecurityGroupRulesClient
-from tempest.services.compute.json.security_groups_client import \
- SecurityGroupsClient
from tempest.services.compute.json.server_groups_client import \
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_client import \
- SnapshotsClient as ComputeSnapshotsClient
-from tempest.services.compute.json.tenant_networks_client import \
- TenantNetworksClient
-from tempest.services.compute.json.tenant_usages_client import \
- TenantUsagesClient
-from tempest.services.compute.json.versions_client import VersionsClient
-from tempest.services.compute.json.volumes_client import \
- VolumesClient as ComputeVolumesClient
from tempest.services.data_processing.v1_1.data_processing_client import \
DataProcessingClient
from tempest.services.database.json.flavors_client import \
@@ -90,64 +89,80 @@
DatabaseVersionsClient
from tempest.services.identity.v2.json.identity_client import \
IdentityClient
+from tempest.services.identity.v2.json.tenants_client import \
+ TenantsClient
from tempest.services.identity.v3.json.credentials_client import \
- CredentialsClient
+ CredentialsClient as CredentialsV3Client
from tempest.services.identity.v3.json.endpoints_client import \
- EndPointClient
-from tempest.services.identity.v3.json.identity_client import \
- IdentityV3Client
-from tempest.services.identity.v3.json.policy_client import PolicyClient
-from tempest.services.identity.v3.json.region_client import RegionClient
+ EndPointClient as EndPointV3Client
+from tempest.services.identity.v3.json.groups_client import \
+ GroupsClient as GroupsV3Client
+from tempest.services.identity.v3.json.identity_client import IdentityV3Client
+from tempest.services.identity.v3.json.policy_client import \
+ PolicyClient as PolicyV3Client
+from tempest.services.identity.v3.json.region_client import \
+ RegionClient as RegionV3Client
from tempest.services.identity.v3.json.service_client import \
- ServiceClient
-from tempest.services.image.v1.json.image_client import ImageClient
-from tempest.services.image.v2.json.image_client import ImageClientV2
+ ServiceClient as ServiceV3Client
+from tempest.services.image.v1.json.images_client import ImagesClient
+from tempest.services.image.v2.json.images_client import ImagesClientV2
from tempest.services.messaging.json.messaging_client import \
MessagingClient
+from tempest.services.network.json.floating_ips_client import FloatingIPsClient
+from tempest.services.network.json.metering_label_rules_client import \
+ MeteringLabelRulesClient
+from tempest.services.network.json.metering_labels_client import \
+ MeteringLabelsClient
from tempest.services.network.json.network_client import NetworkClient
from tempest.services.network.json.networks_client import NetworksClient
from tempest.services.network.json.ports_client import PortsClient
+from tempest.services.network.json.quotas_client import QuotasClient \
+ as NetworkQuotasClient
from tempest.services.network.json.subnets_client import SubnetsClient
from tempest.services.object_storage.account_client import AccountClient
from tempest.services.object_storage.container_client import ContainerClient
from tempest.services.object_storage.object_client import ObjectClient
from tempest.services.orchestration.json.orchestration_client import \
OrchestrationClient
+from tempest.services.telemetry.json.alarming_client import AlarmingClient
from tempest.services.telemetry.json.telemetry_client import \
TelemetryClient
-from tempest.services.volume.json.admin.volume_hosts_client import \
- VolumeHostsClient
-from tempest.services.volume.json.admin.volume_quotas_client import \
- VolumeQuotasClient
-from tempest.services.volume.json.admin.volume_services_client import \
- VolumesServicesClient
-from tempest.services.volume.json.admin.volume_types_client import \
- VolumeTypesClient
-from tempest.services.volume.json.availability_zone_client import \
- VolumeAvailabilityZoneClient
-from tempest.services.volume.json.backups_client import BackupsClient
-from tempest.services.volume.json.extensions_client import \
- ExtensionsClient as VolumeExtensionClient
-from tempest.services.volume.json.qos_client import QosSpecsClient
-from tempest.services.volume.json.snapshots_client import SnapshotsClient
-from tempest.services.volume.json.volumes_client import VolumesClient
-from tempest.services.volume.v2.json.admin.volume_hosts_client import \
- VolumeHostsV2Client
-from tempest.services.volume.v2.json.admin.volume_quotas_client import \
- VolumeQuotasV2Client
-from tempest.services.volume.v2.json.admin.volume_services_client import \
- VolumesServicesV2Client
-from tempest.services.volume.v2.json.admin.volume_types_client import \
- VolumeTypesV2Client
+from tempest.services.volume.v1.json.admin.hosts_client import \
+ HostsClient as VolumeHostsClient
+from tempest.services.volume.v1.json.admin.quotas_client import \
+ QuotasClient as VolumeQuotasClient
+from tempest.services.volume.v1.json.admin.services_client import \
+ ServicesClient as VolumeServicesClient
+from tempest.services.volume.v1.json.admin.types_client import \
+ TypesClient as VolumeTypesClient
+from tempest.services.volume.v1.json.availability_zone_client import \
+ AvailabilityZoneClient as VolumeAvailabilityZoneClient
+from tempest.services.volume.v1.json.backups_client import BackupsClient
+from tempest.services.volume.v1.json.extensions_client import \
+ ExtensionsClient as VolumeExtensionsClient
+from tempest.services.volume.v1.json.qos_client import QosSpecsClient
+from tempest.services.volume.v1.json.snapshots_client import SnapshotsClient
+from tempest.services.volume.v1.json.volumes_client import VolumesClient
+from tempest.services.volume.v2.json.admin.hosts_client import \
+ HostsClient as VolumeHostsV2Client
+from tempest.services.volume.v2.json.admin.quotas_client import \
+ QuotasClient as VolumeQuotasV2Client
+from tempest.services.volume.v2.json.admin.services_client import \
+ ServicesClient as VolumeServicesV2Client
+from tempest.services.volume.v2.json.admin.types_client import \
+ TypesClient as VolumeTypesV2Client
from tempest.services.volume.v2.json.availability_zone_client import \
- VolumeV2AvailabilityZoneClient
-from tempest.services.volume.v2.json.backups_client import BackupsClientV2
+ AvailabilityZoneClient as VolumeAvailabilityZoneV2Client
+from tempest.services.volume.v2.json.backups_client import \
+ BackupsClient as BackupsV2Client
from tempest.services.volume.v2.json.extensions_client import \
- ExtensionsV2Client as VolumeV2ExtensionClient
-from tempest.services.volume.v2.json.qos_client import QosSpecsV2Client
+ ExtensionsClient as VolumeExtensionsV2Client
+from tempest.services.volume.v2.json.qos_client import \
+ QosSpecsClient as QosSpecsV2Client
from tempest.services.volume.v2.json.snapshots_client import \
- SnapshotsV2Client
-from tempest.services.volume.v2.json.volumes_client import VolumesV2Client
+ SnapshotsClient as SnapshotsV2Client
+from tempest.services.volume.v2.json.volumes_client import \
+ VolumesClient as VolumesV2Client
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -218,6 +233,38 @@
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**self.default_params)
+ self.network_quotas_client = NetworkQuotasClient(
+ self.auth_provider,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type=CONF.network.endpoint_type,
+ build_interval=CONF.network.build_interval,
+ build_timeout=CONF.network.build_timeout,
+ **self.default_params)
+ self.floating_ips_client = FloatingIPsClient(
+ self.auth_provider,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type=CONF.network.endpoint_type,
+ build_interval=CONF.network.build_interval,
+ build_timeout=CONF.network.build_timeout,
+ **self.default_params)
+ self.metering_labels_client = MeteringLabelsClient(
+ self.auth_provider,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type=CONF.network.endpoint_type,
+ build_interval=CONF.network.build_interval,
+ build_timeout=CONF.network.build_timeout,
+ **self.default_params)
+ self.metering_label_rules_client = MeteringLabelRulesClient(
+ self.auth_provider,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type=CONF.network.endpoint_type,
+ build_interval=CONF.network.build_interval,
+ build_timeout=CONF.network.build_timeout,
+ **self.default_params)
self.messaging_client = MessagingClient(
self.auth_provider,
CONF.messaging.catalog_type,
@@ -230,8 +277,15 @@
CONF.identity.region,
endpoint_type=CONF.telemetry.endpoint_type,
**self.default_params_with_timeout_values)
+ if CONF.service_available.aodh:
+ self.alarming_client = AlarmingClient(
+ self.auth_provider,
+ CONF.alarming.catalog_type,
+ CONF.identity.region,
+ endpoint_type=CONF.alarming.endpoint_type,
+ **self.default_params_with_timeout_values)
if CONF.service_available.glance:
- self.image_client = ImageClient(
+ self.image_client = ImagesClient(
self.auth_provider,
CONF.image.catalog_type,
CONF.image.region or CONF.identity.region,
@@ -239,7 +293,7 @@
build_interval=CONF.image.build_interval,
build_timeout=CONF.image.build_timeout,
**self.default_params)
- self.image_client_v2 = ImageClientV2(
+ self.image_client_v2 = ImagesClientV2(
self.auth_provider,
CONF.image.catalog_type,
CONF.image.region or CONF.identity.region,
@@ -300,7 +354,7 @@
self.server_groups_client = ServerGroupsClient(
self.auth_provider, **params)
self.limits_client = LimitsClient(self.auth_provider, **params)
- self.images_client = ImagesClient(self.auth_provider, **params)
+ self.images_client = ComputeImagesClient(self.auth_provider, **params)
self.keypairs_client = KeyPairsClient(self.auth_provider, **params)
self.quotas_client = QuotasClient(self.auth_provider, **params)
self.quota_classes_client = QuotaClassesClient(self.auth_provider,
@@ -316,7 +370,7 @@
self.auth_provider, **params)
self.security_group_rules_client = SecurityGroupRulesClient(
self.auth_provider, **params)
- self.security_groups_client = SecurityGroupsClient(
+ self.compute_security_groups_client = ComputeSecurityGroupsClient(
self.auth_provider, **params)
self.interfaces_client = InterfacesClient(self.auth_provider,
**params)
@@ -381,24 +435,29 @@
# Client uses admin endpoint type of Keystone API v2
self.identity_client = IdentityClient(self.auth_provider,
**params_v2_admin)
+ self.tenants_client = TenantsClient(self.auth_provider,
+ **params_v2_admin)
params_v2_public = params.copy()
params_v2_public['endpoint_type'] = (
CONF.identity.v2_public_endpoint_type)
# Client uses public endpoint type of Keystone API v2
self.identity_public_client = IdentityClient(self.auth_provider,
**params_v2_public)
+ self.tenants_public_client = TenantsClient(self.auth_provider,
+ **params_v2_public)
params_v3 = params.copy()
params_v3['endpoint_type'] = CONF.identity.v3_endpoint_type
- # Client uses the endpoint type of Keystone API v3
+ # Clients below use the endpoint type of Keystone API v3
self.identity_v3_client = IdentityV3Client(self.auth_provider,
**params_v3)
- self.endpoints_client = EndPointClient(self.auth_provider,
- **params)
- self.service_client = ServiceClient(self.auth_provider, **params)
- self.policy_client = PolicyClient(self.auth_provider, **params)
- self.region_client = RegionClient(self.auth_provider, **params)
- self.credentials_client = CredentialsClient(self.auth_provider,
- **params)
+ self.endpoints_client = EndPointV3Client(self.auth_provider,
+ **params_v3)
+ self.service_client = ServiceV3Client(self.auth_provider, **params_v3)
+ self.policy_client = PolicyV3Client(self.auth_provider, **params_v3)
+ self.region_client = RegionV3Client(self.auth_provider, **params_v3)
+ self.credentials_client = CredentialsV3Client(self.auth_provider,
+ **params_v3)
+ self.groups_client = GroupsV3Client(self.auth_provider, **params_v3)
# Token clients do not use the catalog. They only need default_params.
# They read auth_url, so they should only be set if the corresponding
# API version is marked as enabled
@@ -431,10 +490,12 @@
**params)
self.volume_qos_v2_client = QosSpecsV2Client(
self.auth_provider, **params)
- self.volume_services_v2_client = VolumesServicesV2Client(
+ self.volume_services_client = VolumeServicesClient(
+ self.auth_provider, **params)
+ self.volume_services_v2_client = VolumeServicesV2Client(
self.auth_provider, **params)
self.backups_client = BackupsClient(self.auth_provider, **params)
- self.backups_v2_client = BackupsClientV2(self.auth_provider,
+ self.backups_v2_client = BackupsV2Client(self.auth_provider,
**params)
self.snapshots_client = SnapshotsClient(self.auth_provider,
**params)
@@ -448,7 +509,7 @@
**params)
self.volume_types_client = VolumeTypesClient(self.auth_provider,
**params)
- self.volume_services_client = VolumesServicesClient(
+ self.volume_types_v2_client = VolumeTypesV2Client(
self.auth_provider, **params)
self.volume_hosts_client = VolumeHostsClient(self.auth_provider,
**params)
@@ -458,16 +519,14 @@
**params)
self.volume_quotas_v2_client = VolumeQuotasV2Client(self.auth_provider,
**params)
- self.volumes_extension_client = VolumeExtensionClient(
+ self.volumes_extension_client = VolumeExtensionsClient(
self.auth_provider, **params)
- self.volumes_v2_extension_client = VolumeV2ExtensionClient(
+ self.volumes_v2_extension_client = VolumeExtensionsV2Client(
self.auth_provider, **params)
self.volume_availability_zone_client = \
VolumeAvailabilityZoneClient(self.auth_provider, **params)
self.volume_v2_availability_zone_client = \
- VolumeV2AvailabilityZoneClient(self.auth_provider, **params)
- self.volume_types_v2_client = VolumeTypesV2Client(
- self.auth_provider, **params)
+ VolumeAvailabilityZoneV2Client(self.auth_provider, **params)
def _set_object_storage_clients(self):
params = {
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index a90b0ce..64c9b00 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -89,9 +89,11 @@
from oslo_log import log as logging
import yaml
+from tempest.common import identity
from tempest import config
from tempest import exceptions as exc
from tempest.services.identity.v2.json import identity_client
+from tempest.services.identity.v2.json import tenants_client
from tempest.services.network.json import network_client
from tempest.services.network.json import networks_client
from tempest.services.network.json import subnets_client
@@ -137,6 +139,13 @@
endpoint_type='adminURL',
**params
)
+ tenants_admin = tenants_client.TenantsClient(
+ _auth,
+ CONF.identity.catalog_type,
+ CONF.identity.region,
+ endpoint_type='adminURL',
+ **params
+ )
network_admin = None
networks_admin = None
subnets_admin = None
@@ -162,12 +171,12 @@
CONF.network.region or CONF.identity.region,
endpoint_type='adminURL',
**params)
- return (identity_admin, neutron_iso_networks, network_admin,
+ return (identity_admin, tenants_admin, neutron_iso_networks, network_admin,
networks_admin, subnets_admin)
def create_resources(opts, resources):
- (identity_admin, neutron_iso_networks,
+ (identity_admin, tenants_admin, neutron_iso_networks,
network_admin, networks_admin, subnets_admin) = get_admin_clients(opts)
roles = identity_admin.list_roles()['roles']
for u in resources['users']:
@@ -179,22 +188,23 @@
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']]
+ existing = [x['name'] for x in tenants_admin.list_tenants()['tenants']]
for tenant in resources['tenants']:
if tenant not in existing:
- identity_admin.create_tenant(tenant)
+ tenants_admin.create_tenant(tenant)
else:
LOG.warn("Tenant '%s' already exists in this environment" % tenant)
LOG.info('Tenants created')
for u in resources['users']:
try:
- tenant = identity_admin.get_tenant_by_name(u['tenant'])
+ tenant = identity.get_tenant_by_name(tenants_admin, u['tenant'])
except tempest_lib.exceptions.NotFound:
LOG.error("Tenant: %s - not found" % u['tenant'])
continue
while True:
try:
- identity_admin.get_user_by_username(tenant['id'], u['name'])
+ identity.get_user_by_username(tenants_admin,
+ tenant['id'], u['name'])
except tempest_lib.exceptions.NotFound:
identity_admin.create_user(
u['name'], u['pass'], tenant['id'],
@@ -209,7 +219,7 @@
LOG.info('Users created')
if neutron_iso_networks:
for u in resources['users']:
- tenant = identity_admin.get_tenant_by_name(u['tenant'])
+ tenant = identity.get_tenant_by_name(tenants_admin, u['tenant'])
network_name, router_name = create_network_resources(
network_admin, networks_admin, subnets_admin, tenant['id'],
u['name'])
@@ -218,13 +228,13 @@
LOG.info('Networks created')
for u in resources['users']:
try:
- tenant = identity_admin.get_tenant_by_name(u['tenant'])
+ tenant = identity.get_tenant_by_name(tenants_admin, u['tenant'])
except tempest_lib.exceptions.NotFound:
LOG.error("Tenant: %s - not found" % u['tenant'])
continue
try:
- user = identity_admin.get_user_by_username(tenant['id'],
- u['name'])
+ user = identity.get_user_by_username(tenants_admin,
+ tenant['id'], u['name'])
except tempest_lib.exceptions.NotFound:
LOG.error("User: %s - not found" % u['user'])
continue
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index 239b4e9..1c8ddcb 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -59,6 +59,7 @@
from tempest import clients
from tempest.cmd import cleanup_service
from tempest.common import credentials_factory as credentials
+from tempest.common import identity
from tempest import config
SAVED_STATE_JSON = "saved_state.json"
@@ -177,11 +178,12 @@
def _init_admin_ids(self):
id_cl = self.admin_mgr.identity_client
- tenant = id_cl.get_tenant_by_name(CONF.auth.admin_tenant_name)
+ tenant = identity.get_tenant_by_name(id_cl,
+ CONF.auth.admin_tenant_name)
self.admin_tenant_id = tenant['id']
- user = id_cl.get_user_by_username(self.admin_tenant_id,
- CONF.auth.admin_username)
+ user = identity.get_user_by_username(id_cl, self.admin_tenant_id,
+ CONF.auth.admin_username)
self.admin_id = user['id']
roles = id_cl.list_roles()['roles']
@@ -238,7 +240,7 @@
id_cl = credentials.AdminManager().identity_client
if (self._tenant_exists(tenant_id)):
try:
- id_cl.remove_user_role(tenant_id, self.admin_id,
+ id_cl.delete_user_role(tenant_id, self.admin_id,
self.admin_role_id)
except Exception as ex:
LOG.exception("Failed removing role from tenant which still"
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index d2f6c03..b5b78c6 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -17,6 +17,7 @@
from oslo_log import log as logging
from tempest.common import credentials_factory as credentials
+from tempest.common import identity
from tempest import config
from tempest import test
@@ -84,10 +85,10 @@
def _get_network_id(net_name, tenant_name):
am = credentials.AdminManager()
net_cl = am.networks_client
- id_cl = am.identity_client
+ tn_cl = am.tenants_client
networks = net_cl.list_networks()
- tenant = id_cl.get_tenant_by_name(tenant_name)
+ tenant = identity.get_tenant_by_name(tn_cl, tenant_name)
t_id = tenant['id']
n_id = None
for net in networks['networks']:
@@ -268,7 +269,7 @@
class SecurityGroupService(BaseService):
def __init__(self, manager, **kwargs):
super(SecurityGroupService, self).__init__(kwargs)
- self.client = manager.security_groups_client
+ self.client = manager.compute_security_groups_client
def list(self):
client = self.client
@@ -385,6 +386,9 @@
self.networks_client = manager.networks_client
self.subnets_client = manager.subnets_client
self.ports_client = manager.ports_client
+ self.floating_ips_client = manager.floating_ips_client
+ self.metering_labels_client = manager.metering_labels_client
+ self.metering_label_rules_client = manager.metering_label_rules_client
def _filter_by_conf_networks(self, item_list):
if not item_list or not all(('network_id' in i for i in item_list)):
@@ -421,7 +425,7 @@
class NetworkFloatingIpService(NetworkService):
def list(self):
- client = self.client
+ client = self.floating_ips_client
flips = client.list_floatingips(**self.tenant_filter)
flips = flips['floatingips']
LOG.debug("List count, %s Network Floating IPs" % len(flips))
@@ -574,7 +578,7 @@
class NetworkMeteringLabelRuleService(NetworkService):
def list(self):
- client = self.client
+ client = self.metering_label_rules_client
rules = client.list_metering_label_rules()
rules = rules['metering_label_rules']
rules = self._filter_by_tenant_id(rules)
@@ -582,7 +586,7 @@
return rules
def delete(self):
- client = self.client
+ client = self.metering_label_rules_client
rules = self.list()
for rule in rules:
try:
@@ -598,7 +602,7 @@
class NetworkMeteringLabelService(NetworkService):
def list(self):
- client = self.client
+ client = self.metering_labels_client
labels = client.list_metering_labels()
labels = labels['metering_labels']
labels = self._filter_by_tenant_id(labels)
@@ -606,7 +610,7 @@
return labels
def delete(self):
- client = self.client
+ client = self.metering_labels_client
labels = self.list()
for label in labels:
try:
@@ -891,9 +895,12 @@
class TenantService(IdentityService):
+ def __init__(self, manager, **kwargs):
+ super(TenantService, self).__init__(kwargs)
+ self.client = manager.tenants_client
+
def list(self):
- client = self.client
- tenants = client.list_tenants()['tenants']
+ tenants = self.client.list_tenants()['tenants']
if not self.is_save_state:
tenants = [tenant for tenant in tenants if (tenant['id']
not in self.saved_state_json['tenants'].keys()
@@ -907,11 +914,10 @@
return tenants
def delete(self):
- client = self.client
tenants = self.list()
for tenant in tenants:
try:
- client.delete_tenant(tenant['id'])
+ self.client.delete_tenant(tenant['id'])
except Exception:
LOG.exception("Delete Tenant exception.")
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 97d431a..826d8e8 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -118,22 +118,25 @@
from tempest_lib import auth
from tempest_lib import exceptions as lib_exc
from tempest_lib.services.compute import flavors_client
+from tempest_lib.services.compute import security_groups_client
import yaml
+from tempest.common import identity
from tempest.common import waiters
from tempest import config
from tempest.services.compute.json import floating_ips_client
from tempest.services.compute.json import security_group_rules_client
-from tempest.services.compute.json import security_groups_client
from tempest.services.compute.json import servers_client
from tempest.services.identity.v2.json import identity_client
-from tempest.services.image.v2.json import image_client
+from tempest.services.identity.v2.json import tenants_client
+from tempest.services.image.v2.json import images_client
from tempest.services.network.json import network_client
from tempest.services.network.json import subnets_client
from tempest.services.object_storage import container_client
from tempest.services.object_storage import object_client
+from tempest.services.telemetry.json import alarming_client
from tempest.services.telemetry.json import telemetry_client
-from tempest.services.volume.json import volumes_client
+from tempest.services.volume.v1.json import volumes_client
CONF = config.CONF
OPTS = {}
@@ -197,6 +200,12 @@
CONF.identity.region,
endpoint_type='adminURL',
**default_params_with_timeout_values)
+ self.tenants = tenants_client.TenantsClient(
+ _auth,
+ CONF.identity.catalog_type,
+ CONF.identity.region,
+ endpoint_type='adminURL',
+ **default_params_with_timeout_values)
self.servers = servers_client.ServersClient(_auth,
**compute_params)
self.flavors = flavors_client.FlavorsClient(_auth,
@@ -211,7 +220,7 @@
**object_storage_params)
self.containers = container_client.ContainerClient(
_auth, **object_storage_params)
- self.images = image_client.ImageClientV2(
+ self.images = images_client.ImagesClientV2(
_auth,
CONF.image.catalog_type,
CONF.image.region or CONF.identity.region,
@@ -225,6 +234,12 @@
CONF.identity.region,
endpoint_type=CONF.telemetry.endpoint_type,
**default_params_with_timeout_values)
+ self.alarming = alarming_client.AlarmingClient(
+ _auth,
+ CONF.alarm.catalog_type,
+ CONF.identity.region,
+ endpoint_type=CONF.alarm.endpoint_type,
+ **default_params_with_timeout_values)
self.volumes = volumes_client.VolumesClient(
_auth,
CONF.volume.catalog_type,
@@ -283,11 +298,11 @@
Don't create the tenants if they already exist.
"""
admin = keystone_admin()
- body = admin.identity.list_tenants()['tenants']
+ body = admin.tenants.list_tenants()['tenants']
existing = [x['name'] for x in body]
for tenant in tenants:
if tenant not in existing:
- admin.identity.create_tenant(tenant)['tenant']
+ admin.tenants.create_tenant(tenant)['tenant']
else:
LOG.warn("Tenant '%s' already exists in this environment" % tenant)
@@ -295,8 +310,8 @@
def destroy_tenants(tenants):
admin = keystone_admin()
for tenant in tenants:
- tenant_id = admin.identity.get_tenant_by_name(tenant)['id']
- admin.identity.delete_tenant(tenant_id)
+ tenant_id = identity.get_tenant_by_name(admin.tenant, tenant)['id']
+ admin.tenants.delete_tenant(tenant_id)
##############
#
@@ -347,12 +362,13 @@
admin = keystone_admin()
for u in users:
try:
- tenant = admin.identity.get_tenant_by_name(u['tenant'])
+ tenant = identity.get_tenant_by_name(admin.tenants, u['tenant'])
except lib_exc.NotFound:
LOG.error("Tenant: %s - not found" % u['tenant'])
continue
try:
- admin.identity.get_user_by_username(tenant['id'], u['name'])
+ identity.get_user_by_username(admin.identity,
+ tenant['id'], u['name'])
LOG.warn("User '%s' already exists in this environment"
% u['name'])
except lib_exc.NotFound:
@@ -365,9 +381,10 @@
def destroy_users(users):
admin = keystone_admin()
for user in users:
- tenant_id = admin.identity.get_tenant_by_name(user['tenant'])['id']
- user_id = admin.identity.get_user_by_username(tenant_id,
- user['name'])['id']
+ tenant_id = identity.get_tenant_by_name(admin.tenants,
+ user['tenant'])['id']
+ user_id = identity.get_user_by_username(admin.identity,
+ tenant_id, user['name'])['id']
admin.identity.delete_user(user_id)
@@ -376,10 +393,11 @@
LOG.info("Collecting users")
admin = keystone_admin()
for u in users:
- tenant = admin.identity.get_tenant_by_name(u['tenant'])
+ tenant = identity.get_tenant_by_name(admin.tenants, u['tenant'])
u['tenant_id'] = tenant['id']
USERS[u['name']] = u
- body = admin.identity.get_user_by_username(tenant['id'], u['name'])
+ body = identity.get_user_by_username(admin.identity,
+ tenant['id'], u['name'])
USERS[u['name']]['id'] = body['id']
@@ -884,7 +902,7 @@
client.servers.wait_for_server_status(server_id, 'ACTIVE')
# create security group(s) after server spawning
for secgroup in server['secgroups']:
- client.servers.add_security_group(server_id, secgroup)
+ client.servers.add_security_group(server_id, name=secgroup)
if CONF.compute.use_floatingip_for_ssh:
floating_ip_pool = server.get('floating_ip_pool')
floating_ip = client.floating_ips.create_floating_ip(
diff --git a/tempest/cmd/run_stress.py b/tempest/cmd/run_stress.py
old mode 100755
new mode 100644
index 80f1b85..f99e5d9
--- a/tempest/cmd/run_stress.py
+++ b/tempest/cmd/run_stress.py
@@ -23,6 +23,7 @@
# unittest in python 2.6 does not contain loader, so uses unittest2
from unittest2 import loader
+from cliff import command
from oslo_log import log as logging
from oslo_serialization import jsonutils as json
from testtools import testsuite
@@ -70,29 +71,42 @@
return tests
-parser = argparse.ArgumentParser(description='Run stress tests')
-parser.add_argument('-d', '--duration', default=300, type=int,
- help="Duration of test in secs")
-parser.add_argument('-s', '--serial', action='store_true',
- help="Trigger running tests serially")
-parser.add_argument('-S', '--stop', action='store_true',
- default=False, help="Stop on first error")
-parser.add_argument('-n', '--number', type=int,
- help="How often an action is executed for each process")
-group = parser.add_mutually_exclusive_group(required=True)
-group.add_argument('-a', '--all', action='store_true',
- help="Execute all stress tests")
-parser.add_argument('-T', '--type',
- help="Filters tests of a certain type (e.g. gate)")
-parser.add_argument('-i', '--call-inherited', action='store_true',
- default=False,
- help="Call also inherited function with stress attribute")
-group.add_argument('-t', "--tests", nargs='?',
- help="Name of the file with test description")
+class TempestRunStress(command.Command):
+
+ def get_parser(self, prog_name):
+ pa = super(TempestRunStress, self).get_parser(prog_name)
+ pa = add_arguments(pa)
+ return pa
+
+ def take_action(self, pa):
+ return action(pa)
-def main():
- ns = parser.parse_args()
+def add_arguments(parser):
+ parser.add_argument('-d', '--duration', default=300, type=int,
+ help="Duration of test in secs")
+ parser.add_argument('-s', '--serial', action='store_true',
+ help="Trigger running tests serially")
+ parser.add_argument('-S', '--stop', action='store_true',
+ default=False, help="Stop on first error")
+ parser.add_argument('-n', '--number', type=int,
+ help="How often an action is executed for each "
+ "process")
+ group = parser.add_mutually_exclusive_group(required=True)
+ group.add_argument('-a', '--all', action='store_true',
+ help="Execute all stress tests")
+ parser.add_argument('-T', '--type',
+ help="Filters tests of a certain type (e.g. gate)")
+ parser.add_argument('-i', '--call-inherited', action='store_true',
+ default=False,
+ help="Call also inherited function with stress "
+ "attribute")
+ group.add_argument('-t', "--tests", nargs='?',
+ help="Name of the file with test description")
+ return parser
+
+
+def action(ns):
result = 0
if not ns.all:
tests = json.load(open(ns.tests, 'r'))
@@ -121,6 +135,15 @@
return result
+def main():
+ LOG.warning("Deprecated: Use 'tempest run-stress' instead. "
+ "The old entrypoint will be removed in a future release.")
+ parser = argparse.ArgumentParser(description='Run stress tests')
+ pa = add_arguments(parser)
+ ns = pa.parse_args()
+ return action(ns)
+
+
if __name__ == "__main__":
try:
sys.exit(main())
diff --git a/tempest/common/api_version_request.py b/tempest/common/api_version_request.py
new file mode 100644
index 0000000..d8a5b56
--- /dev/null
+++ b/tempest/common/api_version_request.py
@@ -0,0 +1,154 @@
+# Copyright 2014 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 re
+
+from tempest import exceptions
+
+
+# Define the minimum and maximum version of the API across all of the
+# REST API. The format of the version is:
+# X.Y where:
+#
+# - X will only be changed if a significant backwards incompatible API
+# change is made which affects the API as whole. That is, something
+# that is only very very rarely incremented.
+#
+# - Y when you make any change to the API. Note that this includes
+# semantic changes which may not affect the input or output formats or
+# even originate in the API code layer. We are not distinguishing
+# between backwards compatible and backwards incompatible changes in
+# the versioning system. It must be made clear in the documentation as
+# to what is a backwards compatible change and what is a backwards
+# incompatible one.
+
+class APIVersionRequest(object):
+ """This class represents an API Version Request.
+
+ This class provides convenience methods for manipulation
+ and comparison of version numbers that we need to do to
+ implement microversions.
+ """
+
+ # NOTE: This 'latest' version is a magic number, we assume any
+ # projects(Nova, etc.) never achieve this number.
+ latest_ver_major = 99999
+ latest_ver_minor = 99999
+
+ def __init__(self, version_string=None):
+ """Create an API version request object.
+
+ :param version_string: String representation of APIVersionRequest.
+ Correct format is 'X.Y', where 'X' and 'Y' are int values.
+ None value should be used to create Null APIVersionRequest,
+ which is equal to 0.0
+ """
+ # NOTE(gmann): 'version_string' as String "None" will be considered as
+ # invalid version string.
+ self.ver_major = 0
+ self.ver_minor = 0
+
+ if version_string is not None:
+ match = re.match(r"^([1-9]\d*)\.([1-9]\d*|0)$",
+ version_string)
+ if match:
+ self.ver_major = int(match.group(1))
+ self.ver_minor = int(match.group(2))
+ elif version_string == 'latest':
+ self.ver_major = self.latest_ver_major
+ self.ver_minor = self.latest_ver_minor
+ else:
+ raise exceptions.InvalidAPIVersionString(
+ version=version_string)
+
+ def __str__(self):
+ """Debug/Logging representation of object."""
+ return ("API Version Request: %s" % self.get_string())
+
+ def is_null(self):
+ return self.ver_major == 0 and self.ver_minor == 0
+
+ def _format_type_error(self, other):
+ return TypeError("'%(other)s' should be an instance of '%(cls)s'" %
+ {"other": other, "cls": self.__class__})
+
+ def __lt__(self, other):
+ if not isinstance(other, APIVersionRequest):
+ raise self._format_type_error(other)
+
+ return ((self.ver_major, self.ver_minor) <
+ (other.ver_major, other.ver_minor))
+
+ def __eq__(self, other):
+ if not isinstance(other, APIVersionRequest):
+ raise self._format_type_error(other)
+
+ return ((self.ver_major, self.ver_minor) ==
+ (other.ver_major, other.ver_minor))
+
+ def __gt__(self, other):
+ if not isinstance(other, APIVersionRequest):
+ raise self._format_type_error(other)
+
+ return ((self.ver_major, self.ver_minor) >
+ (other.ver_major, other.ver_minor))
+
+ def __le__(self, other):
+ return self < other or self == other
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __ge__(self, other):
+ return self > other or self == other
+
+ def matches(self, min_version, max_version):
+ """Matches the version object.
+
+ Returns whether the version object represents a version
+ greater than or equal to the minimum version and less than
+ or equal to the maximum version.
+
+ @param min_version: Minimum acceptable version.
+ @param max_version: Maximum acceptable version.
+ @returns: boolean
+
+ If min_version is null then there is no minimum limit.
+ If max_version is null then there is no maximum limit.
+ If self is null then raise ValueError
+ """
+
+ if self.is_null():
+ raise ValueError
+ if max_version.is_null() and min_version.is_null():
+ return True
+ elif max_version.is_null():
+ return min_version <= self
+ elif min_version.is_null():
+ return self <= max_version
+ else:
+ return min_version <= self <= max_version
+
+ def get_string(self):
+ """Version string representation.
+
+ Converts object to string representation which if used to create
+ an APIVersionRequest object results in the same version request.
+ """
+ if self.is_null():
+ return None
+ if (self.ver_major == self.latest_ver_major and
+ self.ver_minor == self.latest_ver_minor):
+ return 'latest'
+ return "%s.%s" % (self.ver_major, self.ver_minor)
diff --git a/tempest/common/api_version_utils.py b/tempest/common/api_version_utils.py
new file mode 100644
index 0000000..c499f23
--- /dev/null
+++ b/tempest/common/api_version_utils.py
@@ -0,0 +1,64 @@
+# 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 testtools
+
+from tempest.common import api_version_request
+from tempest import exceptions
+
+
+class BaseMicroversionTest(object):
+ """Mixin class for API microversion test class."""
+
+ # NOTE: Basically, each microversion is small API change and we
+ # can use the same tests for most microversions in most cases.
+ # So it is nice to define the test class as possible to run
+ # for all microversions. We need to define microversion range
+ # (min_microversion, max_microversion) on each test class if necessary.
+ min_microversion = None
+ max_microversion = 'latest'
+
+
+def check_skip_with_microversion(test_min_version, test_max_version,
+ cfg_min_version, cfg_max_version):
+ min_version = api_version_request.APIVersionRequest(test_min_version)
+ max_version = api_version_request.APIVersionRequest(test_max_version)
+ config_min_version = api_version_request.APIVersionRequest(cfg_min_version)
+ config_max_version = api_version_request.APIVersionRequest(cfg_max_version)
+ if ((min_version > max_version) or
+ (config_min_version > config_max_version)):
+ msg = ("Min version is greater than Max version. Test Class versions "
+ "[%s - %s]. configration versions [%s - %s]."
+ % (min_version.get_string(),
+ max_version.get_string(),
+ config_min_version.get_string(),
+ config_max_version.get_string()))
+ raise exceptions.InvalidConfiguration(msg)
+
+ # NOTE: Select tests which are in range of configuration like
+ # config min config max
+ # ----------------+--------------------------+----------------
+ # ...don't-select|
+ # ...select... ...select... ...select...
+ # |don't-select...
+ # ......................select............................
+ if (max_version < config_min_version or
+ config_max_version < min_version):
+ msg = ("The microversion range[%s - %s] of this test is out of the "
+ "configration range[%s - %s]."
+ % (min_version.get_string(),
+ max_version.get_string(),
+ config_min_version.get_string(),
+ config_max_version.get_string()))
+ raise testtools.TestCase.skipException(msg)
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index 6fc3843..5a14fbe 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -43,7 +43,7 @@
:param wait_until: Server status to wait for the server to reach after
its creation.
:param volume_backed: Whether the instance is volume backed or not.
- :returns a tuple
+ :returns: a tuple
"""
# TODO(jlanoux) add support of wait_until PINGABLE/SSHABLE
diff --git a/tempest/common/cred_client.py b/tempest/common/cred_client.py
index 13baafb..94515dc 100644
--- a/tempest/common/cred_client.py
+++ b/tempest/common/cred_client.py
@@ -31,9 +31,12 @@
admin credentials used for generating credentials.
"""
- def __init__(self, identity_client):
+ def __init__(self, identity_client, projects_client=None):
# The client implies version and credentials
self.identity_client = identity_client
+ # this is temporary until the v3 project client is
+ # separated, then projects_client will become mandatory
+ self.projects_client = projects_client or identity_client
def create_user(self, username, password, project, email):
user = self.identity_client.create_user(
@@ -91,8 +94,11 @@
class V2CredsClient(CredsClient):
+ def __init__(self, identity_client, projects_client):
+ super(V2CredsClient, self).__init__(identity_client, projects_client)
+
def create_project(self, name, description):
- tenant = self.identity_client.create_tenant(
+ tenant = self.projects_client.create_tenant(
name=name, description=description)['tenant']
return tenant
@@ -108,7 +114,7 @@
password=password)
def delete_project(self, project_id):
- self.identity_client.delete_tenant(project_id)
+ self.projects_client.delete_tenant(project_id)
class V3CredsClient(CredsClient):
@@ -152,8 +158,10 @@
return roles
-def get_creds_client(identity_client, project_domain_name=None):
+def get_creds_client(identity_client,
+ projects_client=None,
+ project_domain_name=None):
if isinstance(identity_client, v2_identity.IdentityClient):
- return V2CredsClient(identity_client)
+ return V2CredsClient(identity_client, projects_client)
else:
return V3CredsClient(identity_client, project_domain_name)
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
index 75639b2..5d290d4 100644
--- a/tempest/common/credentials_factory.py
+++ b/tempest/common/credentials_factory.py
@@ -11,8 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import os
-
+from oslo_concurrency import lockutils
from oslo_log import log as logging
from tempest_lib import auth
@@ -42,6 +41,29 @@
# === Credential Providers
+# Subset of the parameters of credential providers that depend on configuration
+def _get_common_provider_params():
+ return {
+ 'credentials_domain': CONF.auth.default_credentials_domain_name,
+ 'admin_role': CONF.identity.admin_role
+ }
+
+
+def _get_dynamic_provider_params():
+ return _get_common_provider_params()
+
+
+def _get_preprov_provider_params():
+ _common_params = _get_common_provider_params()
+ reseller_admin_role = CONF.object_storage.reseller_admin_role
+ return dict(_common_params, **dict([
+ ('accounts_lock_dir', lockutils.get_lock_path(CONF)),
+ ('test_accounts_file', CONF.auth.test_accounts_file),
+ ('object_storage_operator_role', CONF.object_storage.operator_role),
+ ('object_storage_reseller_admin_role', reseller_admin_role)
+ ]))
+
+
class LegacyCredentialProvider(cred_provider.CredentialProvider):
def __init__(self, identity_version):
@@ -118,11 +140,11 @@
raise exceptions.InvalidConfiguration(msg)
def is_role_available(self, role):
- msg = "Credentials being specified through the config file can not be"\
- " used with tests that specify using credentials by roles. "\
- "Either exclude/skip the tests doing this or use either an "\
- "test_accounts_file or dynamic credentials."
- raise exceptions.InvalidConfiguration(msg)
+ # NOTE(andreaf) LegacyCredentialProvider does not support credentials
+ # by role, so returning always False.
+ # Test that rely on credentials by role should use this to skip
+ # when this is credential provider is used
+ return False
# Return the right implementation of CredentialProvider based on config
@@ -143,17 +165,14 @@
name=name,
network_resources=network_resources,
identity_version=identity_version,
- credentials_domain=CONF.auth.default_credentials_domain_name,
- admin_role=CONF.identity.admin_role,
- admin_creds=admin_creds)
+ admin_creds=admin_creds,
+ **_get_dynamic_provider_params())
else:
- if (CONF.auth.test_accounts_file and
- os.path.isfile(CONF.auth.test_accounts_file)):
+ if CONF.auth.test_accounts_file:
# Most params are not relevant for pre-created accounts
return preprov_creds.PreProvisionedCredentialProvider(
name=name, identity_version=identity_version,
- credentials_domain=CONF.auth.default_credentials_domain_name,
- admin_role=CONF.identity.admin_role)
+ **_get_preprov_provider_params())
else:
# Dynamic credentials are disabled, and the account file is not
# defined - we fall back on credentials configured in tempest.conf
@@ -171,11 +190,10 @@
if CONF.auth.use_dynamic_credentials:
return is_admin
# Check whether test accounts file has the admin specified or not
- elif (CONF.auth.test_accounts_file and
- os.path.isfile(CONF.auth.test_accounts_file)):
+ elif CONF.auth.test_accounts_file:
check_accounts = preprov_creds.PreProvisionedCredentialProvider(
identity_version=identity_version, name='check_admin',
- admin_role=CONF.identity.admin_role)
+ **_get_preprov_provider_params())
if not check_accounts.admin_available():
is_admin = False
else:
@@ -197,11 +215,10 @@
if CONF.auth.use_dynamic_credentials:
return True
# Check whether test accounts file has the admin specified or not
- if (CONF.auth.test_accounts_file and
- os.path.isfile(CONF.auth.test_accounts_file)):
+ if CONF.auth.test_accounts_file:
check_accounts = preprov_creds.PreProvisionedCredentialProvider(
identity_version=identity_version, name='check_alt',
- admin_role=CONF.identity.admin_role)
+ **_get_preprov_provider_params())
else:
check_accounts = LegacyCredentialProvider(identity_version)
try:
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index e950c3e..813d94f 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -57,7 +57,8 @@
self._creds = {}
self.ports = []
self.default_admin_creds = admin_creds
- (self.identity_admin_client, self.network_admin_client,
+ (self.identity_admin_client, self.tenants_admin_client,
+ self.network_admin_client,
self.networks_admin_client,
self.subnets_admin_client,
self.ports_admin_client) = self._get_admin_clients()
@@ -69,7 +70,9 @@
self.default_admin_creds.project_domain_name or
self.credentials_domain)
self.creds_client = cred_client.get_creds_client(
- self.identity_admin_client, self.creds_domain_name)
+ self.identity_admin_client,
+ self.tenants_admin_client,
+ self.creds_domain_name)
def _get_admin_clients(self):
"""Returns a tuple with instances of the following admin clients
@@ -80,10 +83,10 @@
"""
os = clients.Manager(self.default_admin_creds)
if self.identity_version == 'v2':
- return (os.identity_client, os.network_client, os.networks_client,
- os.subnets_client, os.ports_client)
+ return (os.identity_client, os.tenants_client, os.network_client,
+ os.networks_client, os.subnets_client, os.ports_client)
else:
- return (os.identity_v3_client, os.network_client,
+ return (os.identity_v3_client, None, os.network_client,
os.networks_client, os.subnets_client, os.ports_client)
def _create_creds(self, suffix="", admin=False, roles=None):
diff --git a/tempest/common/fixed_network.py b/tempest/common/fixed_network.py
index b81830a..56cd331 100644
--- a/tempest/common/fixed_network.py
+++ b/tempest/common/fixed_network.py
@@ -15,11 +15,8 @@
from tempest_lib.common.utils import misc as misc_utils
-from tempest import config
from tempest import exceptions
-CONF = config.CONF
-
LOG = logging.getLogger(__name__)
@@ -31,14 +28,14 @@
object to use for making the network lists api request
:return: The full dictionary for the network in question
:rtype: dict
- :raises InvalidConfiguration: If the name provided is invalid, the networks
+ :raises InvalidTestResource: If the name provided is invalid, the networks
list returns a 404, there are no found networks, or the found network
is invalid
"""
caller = misc_utils.find_test_caller()
if not name:
- raise exceptions.InvalidConfiguration()
+ raise exceptions.InvalidTestResource(type='network', name=name)
networks = compute_networks_client.list_networks()['networks']
networks = [n for n in networks if n['label'] == name]
@@ -53,13 +50,13 @@
if caller:
msg = '(%s) %s' % (caller, msg)
LOG.warn(msg)
- raise exceptions.InvalidConfiguration()
+ raise exceptions.InvalidTestResource(type='network', name=name)
else:
msg = "Network with name: %s not found" % name
if caller:
msg = '(%s) %s' % (caller, msg)
LOG.warn(msg)
- raise exceptions.InvalidConfiguration()
+ raise exceptions.InvalidTestResource(type='network', name=name)
# To be consistent between neutron and nova network always use name even
# if label is used in the api response. If neither is present than then
# the returned network is invalid.
@@ -69,12 +66,13 @@
if caller:
msg = '(%s) %s' % (caller, msg)
LOG.warn(msg)
- raise exceptions.InvalidConfiguration()
+ raise exceptions.InvalidTestResource(type='network', name=name)
network['name'] = name
return network
-def get_tenant_network(creds_provider, compute_networks_client):
+def get_tenant_network(creds_provider, compute_networks_client,
+ shared_network_name):
"""Get a network usable by the primary tenant
:param creds_provider: instance of credential provider
@@ -83,23 +81,24 @@
neutron and nova-network cases. If this is not an admin network
client, set_network_kwargs might fail in case fixed_network_name
is the network to be used, and it's not visible to the tenant
- :return a dict with 'id' and 'name' of the network
+ :param shared_network_name: name of the shared network to be used if no
+ tenant network is available in the creds provider
+ :returns: a dict with 'id' and 'name' of the network
"""
caller = misc_utils.find_test_caller()
- fixed_network_name = CONF.compute.fixed_network_name
net_creds = creds_provider.get_primary_creds()
network = getattr(net_creds, 'network', None)
if not network or not network.get('name'):
- if fixed_network_name:
+ if shared_network_name:
msg = ('No valid network provided or created, defaulting to '
'fixed_network_name')
if caller:
msg = '(%s) %s' % (caller, msg)
LOG.debug(msg)
try:
- network = get_network_from_name(fixed_network_name,
+ network = get_network_from_name(shared_network_name,
compute_networks_client)
- except exceptions.InvalidConfiguration:
+ except exceptions.InvalidTestResource:
network = {}
msg = ('Found network %s available for tenant' % network)
if caller:
diff --git a/tempest/common/glance_http.py b/tempest/common/glance_http.py
index e5431a0..800e977 100644
--- a/tempest/common/glance_http.py
+++ b/tempest/common/glance_http.py
@@ -24,12 +24,10 @@
import OpenSSL
from oslo_log import log as logging
-from oslo_serialization import jsonutils as json
import six
from six import moves
from six.moves import http_client as httplib
from six.moves.urllib import parse as urlparse
-from tempest_lib import exceptions as lib_exc
from tempest import exceptions as exc
@@ -51,19 +49,20 @@
self.endpoint_port = endpoint_parts.port
self.endpoint_path = endpoint_parts.path
- self.connection_class = self.get_connection_class(self.endpoint_scheme)
- self.connection_kwargs = self.get_connection_kwargs(
+ self.connection_class = self._get_connection_class(
+ self.endpoint_scheme)
+ self.connection_kwargs = self._get_connection_kwargs(
self.endpoint_scheme, **kwargs)
@staticmethod
- def get_connection_class(scheme):
+ def _get_connection_class(scheme):
if scheme == 'https':
return VerifiedHTTPSConnection
else:
return httplib.HTTPConnection
@staticmethod
- def get_connection_kwargs(scheme, **kwargs):
+ def _get_connection_kwargs(scheme, **kwargs):
_kwargs = {'timeout': float(kwargs.get('timeout', 600))}
if scheme == 'https':
@@ -75,7 +74,7 @@
return _kwargs
- def get_connection(self):
+ def _get_connection(self):
_class = self.connection_class
try:
return _class(self.endpoint_hostname, self.endpoint_port,
@@ -95,7 +94,7 @@
self._log_request(method, url, kwargs['headers'])
- conn = self.get_connection()
+ conn = self._get_connection()
try:
url_parts = urlparse.urlparse(url)
@@ -159,30 +158,6 @@
self.LOG.debug("Large body (%d) md5 summary: %s", length,
hashlib.md5(str_body).hexdigest())
- def json_request(self, method, url, **kwargs):
- kwargs.setdefault('headers', {})
- kwargs['headers'].setdefault('Content-Type', 'application/json')
- if kwargs['headers']['Content-Type'] != 'application/json':
- msg = "Only application/json content-type is supported."
- raise lib_exc.InvalidContentType(msg)
-
- if 'body' in kwargs:
- kwargs['body'] = json.dumps(kwargs['body'])
-
- resp, body_iter = self._http_request(url, method, **kwargs)
-
- if 'application/json' in resp.getheader('content-type', ''):
- body = ''.join([chunk for chunk in body_iter])
- try:
- body = json.loads(body)
- except ValueError:
- LOG.error('Could not decode response body as JSON')
- else:
- msg = "Only json/application content-type is supported."
- raise lib_exc.InvalidContentType(msg)
-
- return resp, body
-
def raw_request(self, method, url, **kwargs):
kwargs.setdefault('headers', {})
kwargs['headers'].setdefault('Content-Type',
diff --git a/tempest/common/identity.py b/tempest/common/identity.py
new file mode 100644
index 0000000..2179363
--- /dev/null
+++ b/tempest/common/identity.py
@@ -0,0 +1,32 @@
+# 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 import exceptions as lib_exc
+
+
+def get_tenant_by_name(client, tenant_name):
+ tenants = client.list_tenants()['tenants']
+ for tenant in tenants:
+ if tenant['name'] == tenant_name:
+ return tenant
+ raise lib_exc.NotFound('No such tenant(%s) in %s' % (tenant_name, tenants))
+
+
+def get_user_by_username(client, tenant_id, username):
+ users = client.list_tenant_users(tenant_id)['users']
+ for user in users:
+ if user['name'] == username:
+ return user
+ raise lib_exc.NotFound('No such user(%s) in %s' % (username, users))
diff --git a/tempest/common/preprov_creds.py b/tempest/common/preprov_creds.py
index f711302..34af31e 100644
--- a/tempest/common/preprov_creds.py
+++ b/tempest/common/preprov_creds.py
@@ -19,41 +19,76 @@
from oslo_log import log as logging
import six
from tempest_lib import auth
+from tempest_lib import exceptions as lib_exc
import yaml
from tempest import clients
from tempest.common import cred_provider
from tempest.common import fixed_network
-from tempest import config
from tempest import exceptions
-CONF = config.CONF
LOG = logging.getLogger(__name__)
def read_accounts_yaml(path):
- with open(path, 'r') as yaml_file:
- accounts = yaml.load(yaml_file)
+ try:
+ with open(path, 'r') as yaml_file:
+ accounts = yaml.load(yaml_file)
+ except IOError:
+ raise exceptions.InvalidConfiguration(
+ 'The path for the test accounts file: %s '
+ 'could not be found' % path)
return accounts
class PreProvisionedCredentialProvider(cred_provider.CredentialProvider):
- def __init__(self, identity_version, name=None, credentials_domain=None,
- admin_role=None):
+ def __init__(self, identity_version, test_accounts_file,
+ accounts_lock_dir, name=None, credentials_domain=None,
+ admin_role=None, object_storage_operator_role=None,
+ object_storage_reseller_admin_role=None):
+ """Credentials provider using pre-provisioned accounts
+
+ This credentials provider loads the details of pre-provisioned
+ accounts from a YAML file, in the format specified by
+ `etc/accounts.yaml.sample`. It locks accounts while in use, using the
+ external locking mechanism, allowing for multiple python processes
+ to share a single account file, and thus running tests in parallel.
+
+ The accounts_lock_dir must be generated using `lockutils.get_lock_path`
+ from the oslo.concurrency library. For instance:
+
+ accounts_lock_dir = os.path.join(lockutils.get_lock_path(CONF),
+ 'test_accounts')
+
+ Role names for object storage are optional as long as the
+ `operator` and `reseller_admin` credential types are not used in the
+ accounts file.
+
+ :param identity_version: identity version of the credentials
+ :param admin_role: name of the admin role
+ :param test_accounts_file: path to the accounts YAML file
+ :param accounts_lock_dir: the directory for external locking
+ :param name: name of the hash file (optional)
+ :param credentials_domain: name of the domain credentials belong to
+ (if no domain is configured)
+ :param object_storage_operator_role: name of the role
+ :param object_storage_reseller_admin_role: name of the role
+ """
super(PreProvisionedCredentialProvider, self).__init__(
identity_version=identity_version, name=name,
- credentials_domain=credentials_domain, admin_role=admin_role)
- if (CONF.auth.test_accounts_file and
- os.path.isfile(CONF.auth.test_accounts_file)):
- accounts = read_accounts_yaml(CONF.auth.test_accounts_file)
+ admin_role=admin_role, credentials_domain=credentials_domain)
+ self.test_accounts_file = test_accounts_file
+ if test_accounts_file:
+ accounts = read_accounts_yaml(self.test_accounts_file)
self.use_default_creds = False
else:
accounts = {}
self.use_default_creds = True
- self.hash_dict = self.get_hash_dict(accounts, admin_role)
- self.accounts_dir = os.path.join(lockutils.get_lock_path(CONF),
- 'test_accounts')
+ self.hash_dict = self.get_hash_dict(
+ accounts, admin_role, object_storage_operator_role,
+ object_storage_reseller_admin_role)
+ self.accounts_dir = accounts_lock_dir
self._creds = {}
@classmethod
@@ -65,7 +100,9 @@
return hash_dict
@classmethod
- def get_hash_dict(cls, accounts, admin_role):
+ def get_hash_dict(cls, accounts, admin_role,
+ object_storage_operator_role=None,
+ object_storage_reseller_admin_role=None):
hash_dict = {'roles': {}, 'creds': {}, 'networks': {}}
# Loop over the accounts read from the yaml file
for account in accounts:
@@ -92,14 +129,24 @@
hash_dict = cls._append_role(admin_role, temp_hash_key,
hash_dict)
elif type == 'operator':
- hash_dict = cls._append_role(
- CONF.object_storage.operator_role, temp_hash_key,
- hash_dict)
+ if object_storage_operator_role:
+ hash_dict = cls._append_role(
+ object_storage_operator_role, temp_hash_key,
+ hash_dict)
+ else:
+ msg = ("Type 'operator' configured, but no "
+ "object_storage_operator_role specified")
+ raise lib_exc.InvalidCredentials(msg)
elif type == 'reseller_admin':
- hash_dict = cls._append_role(
- CONF.object_storage.reseller_admin_role,
- temp_hash_key,
- hash_dict)
+ if object_storage_reseller_admin_role:
+ hash_dict = cls._append_role(
+ object_storage_reseller_admin_role,
+ temp_hash_key,
+ hash_dict)
+ else:
+ msg = ("Type 'reseller_admin' configured, but no "
+ "object_storage_reseller_admin_role specified")
+ raise lib_exc.InvalidCredentials(msg)
# Populate the network subdict
for resource in resources:
if resource == 'network':
@@ -112,8 +159,8 @@
def is_multi_user(self):
# Default credentials is not a valid option with locking Account
if self.use_default_creds:
- raise exceptions.InvalidConfiguration(
- "Account file %s doesn't exist" % CONF.auth.test_accounts_file)
+ raise lib_exc.InvalidCredentials(
+ "Account file %s doesn't exist" % self.test_accounts_file)
else:
return len(self.hash_dict['creds']) > 1
@@ -149,7 +196,7 @@
names.append(fd.read())
msg = ('Insufficient number of users provided. %s have allocated all '
'the credentials for this allocation request' % ','.join(names))
- raise exceptions.InvalidConfiguration(msg)
+ raise lib_exc.InvalidCredentials(msg)
def _get_match_hash_list(self, roles=None):
hashes = []
@@ -159,7 +206,7 @@
for role in roles:
temp_hashes = self.hash_dict['roles'].get(role, None)
if not temp_hashes:
- raise exceptions.InvalidConfiguration(
+ raise lib_exc.InvalidCredentials(
"No credentials with role: %s specified in the "
"accounts ""file" % role)
hashes.append(temp_hashes)
@@ -191,8 +238,8 @@
def _get_creds(self, roles=None):
if self.use_default_creds:
- raise exceptions.InvalidConfiguration(
- "Account file %s doesn't exist" % CONF.auth.test_accounts_file)
+ raise lib_exc.InvalidCredentials(
+ "Account file %s doesn't exist" % self.test_accounts_file)
useable_hashes = self._get_match_hash_list(roles)
free_hash = self._get_free_hash(useable_hashes)
clean_creds = self._sanitize_creds(
@@ -297,7 +344,7 @@
try:
network = fixed_network.get_network_from_name(
net_name, compute_network_client)
- except exceptions.InvalidConfiguration:
+ except exceptions.InvalidTestResource:
network = {}
net_creds.set_resources(network=network)
return net_creds
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 10654ff..025b79f 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -95,15 +95,24 @@
return self.exec_command(cmd)
def ping_host(self, host, count=CONF.compute.ping_count,
- size=CONF.compute.ping_size):
+ size=CONF.compute.ping_size, nic=None):
addr = netaddr.IPAddress(host)
cmd = 'ping6' if addr.version == 6 else 'ping'
+ if nic:
+ cmd = 'sudo {cmd} -I {nic}'.format(cmd=cmd, nic=nic)
cmd += ' -c{0} -w{0} -s{1} {2}'.format(count, size, host)
return self.exec_command(cmd)
- def get_mac_address(self):
- cmd = "ip addr | awk '/ether/ {print $2}'"
- return self.exec_command(cmd)
+ def set_mac_address(self, nic, address):
+ self.set_nic_state(nic=nic, state="down")
+ cmd = "sudo ip link set dev {0} address {1}".format(nic, address)
+ self.exec_command(cmd)
+ self.set_nic_state(nic=nic, state="up")
+
+ def get_mac_address(self, nic=""):
+ show_nic = "show {nic} ".format(nic=nic) if nic else ""
+ cmd = "ip addr %s| awk '/ether/ {print $2}'" % show_nic
+ return self.exec_command(cmd).strip().lower()
def get_nic_name(self, address):
cmd = "ip -o addr | awk '/%s/ {print $2}'" % address
@@ -121,8 +130,8 @@
)
return self.exec_command(cmd)
- def turn_nic_on(self, nic):
- cmd = "sudo ip link set {nic} up".format(nic=nic)
+ def set_nic_state(self, nic, state="up"):
+ cmd = "sudo ip link set {nic} {state}".format(nic=nic, state=state)
return self.exec_command(cmd)
def get_pids(self, pr_name):
diff --git a/tempest/common/validation_resources.py b/tempest/common/validation_resources.py
index 1908b68..f526299 100644
--- a/tempest/common/validation_resources.py
+++ b/tempest/common/validation_resources.py
@@ -23,7 +23,7 @@
def create_ssh_security_group(os, add_rule=False):
- security_groups_client = os.security_groups_client
+ security_groups_client = os.compute_security_groups_client
security_group_rules_client = os.security_group_rules_client
sg_name = data_utils.rand_name('securitygroup-')
sg_description = data_utils.rand_name('description-')
@@ -81,7 +81,7 @@
if not has_exception:
has_exception = exc
if 'security_group' in validation_data:
- security_group_client = os.security_groups_client
+ security_group_client = os.compute_security_groups_client
sec_id = validation_data['security_group']['id']
try:
security_group_client.delete_security_group(sec_id)
diff --git a/tempest/config.py b/tempest/config.py
index dbef88c..1f9a1f3 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -237,10 +237,6 @@
cfg.StrOpt('image_ssh_password',
default="password",
help="Password used to authenticate to an instance."),
- cfg.StrOpt('image_alt_ssh_user',
- default="root",
- help="User name used to authenticate to an instance using "
- "the alternate image."),
cfg.IntOpt('build_interval',
default=1,
help="Time in seconds between build status checks."),
@@ -345,6 +341,24 @@
title="Enabled Compute Service Features")
ComputeFeaturesGroup = [
+ cfg.StrOpt('min_microversion',
+ default=None,
+ help="Lower version of the test target microversion range. "
+ "The format is 'X.Y', where 'X' and 'Y' are int values. "
+ "Tempest selects tests based on the range between "
+ "min_microversion and max_microversion. "
+ "If both values are not specified, Tempest avoids tests "
+ "which require a microversion. Valid values are string "
+ "with format 'X.Y' or string 'latest'"),
+ cfg.StrOpt('max_microversion',
+ default=None,
+ help="Upper version of the test target microversion range. "
+ "The format is 'X.Y', where 'X' and 'Y' are int values. "
+ "Tempest selects tests based on the range between "
+ "min_microversion and max_microversion. "
+ "If both values are not specified, Tempest avoids tests "
+ "which require a microversion. Valid values are string "
+ "with format 'X.Y' or string 'latest'"),
cfg.BoolOpt('disk_config',
default=True,
help="If false, skip disk config tests"),
@@ -726,11 +740,21 @@
'publicURL', 'adminURL', 'internalURL'],
help="The endpoint type to use for the volume service."),
cfg.StrOpt('backend1_name',
- default='BACKEND_1',
- help="Name of the backend1 (must be declared in cinder.conf)"),
+ default='',
+ help='Name of the backend1 (must be declared in cinder.conf)',
+ deprecated_for_removal=True),
cfg.StrOpt('backend2_name',
- default='BACKEND_2',
- help="Name of the backend2 (must be declared in cinder.conf)"),
+ default='',
+ help='Name of the backend2 (must be declared in cinder.conf)',
+ deprecated_for_removal=True),
+ cfg.ListOpt('backend_names',
+ default=['BACKEND_1', 'BACKEND_2'],
+ help='A list of backend names seperated by comma .'
+ 'The backend name must be declared in cinder.conf',
+ deprecated_opts=[cfg.DeprecatedOpt('BACKEND_1',
+ group='volume'),
+ cfg.DeprecatedOpt('BACKEND_2',
+ group='volume')]),
cfg.StrOpt('storage_protocol',
default='iSCSI',
help='Backend protocol to target when creating volume types'),
@@ -921,6 +945,20 @@
"notification tests")
]
+alarming_group = cfg.OptGroup(name='alarming',
+ title='Alarming Service Options')
+
+AlarmingGroup = [
+ cfg.StrOpt('catalog_type',
+ default='alarming',
+ help="Catalog type of the Alarming service."),
+ cfg.StrOpt('endpoint_type',
+ default='publicURL',
+ choices=['public', 'admin', 'internal',
+ 'publicURL', 'adminURL', 'internalURL'],
+ help="The endpoint type to use for the alarming service."),
+]
+
telemetry_feature_group = cfg.OptGroup(name='telemetry-feature-enabled',
title='Enabled Ceilometer Features')
@@ -1131,6 +1169,9 @@
cfg.BoolOpt('ceilometer',
default=True,
help="Whether or not Ceilometer is expected to be available"),
+ cfg.BoolOpt('aodh',
+ default=False,
+ help="Whether or not Aodh is expected to be available"),
cfg.BoolOpt('horizon',
default=True,
help="Whether or not Horizon is expected to be available"),
@@ -1277,6 +1318,7 @@
(orchestration_group, OrchestrationGroup),
(telemetry_group, TelemetryGroup),
(telemetry_feature_group, TelemetryFeaturesGroup),
+ (alarming_group, AlarmingGroup),
(dashboard_group, DashboardGroup),
(data_processing_group, DataProcessingGroup),
(data_processing_feature_group, DataProcessingFeaturesGroup),
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index c23e70c..1d725af 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -139,6 +139,13 @@
message = "%(num)d cleanUp operation failed"
+# NOTE(andreaf) This exception is added here to facilitate the migration
+# of get_network_from_name and preprov_creds to tempest-lib, and it should
+# be migrated along with them
+class InvalidTestResource(TempestException):
+ message = "%(name) is not a valid %(type), or the name is ambiguous"
+
+
class RFCViolation(RestClientException):
message = "RFC Violation"
@@ -169,6 +176,11 @@
message = "Invalid structure of table with details"
+class InvalidAPIVersionString(TempestException):
+ message = ("API Version String %(version)s is of invalid format. Must "
+ "be of format MajorNum.MinorNum or string 'latest'.")
+
+
class CommandFailed(Exception):
def __init__(self, returncode, cmd, output, stderr):
super(CommandFailed, self).__init__()
diff --git a/tempest/hacking/checks.py b/tempest/hacking/checks.py
index 936fbe8..1dad3ba 100644
--- a/tempest/hacking/checks.py
+++ b/tempest/hacking/checks.py
@@ -32,6 +32,7 @@
TESTTOOLS_SKIP_DECORATOR = re.compile(r'\s*@testtools\.skip\((.*)\)')
METHOD = re.compile(r"^ def .+")
METHOD_GET_RESOURCE = re.compile(r"^\s*def (list|show)\_.+")
+METHOD_DELETE_RESOURCE = re.compile(r"^\s*def delete_.+")
CLASS = re.compile(r"^class .+")
@@ -146,27 +147,37 @@
"decorators.skip_because from tempest-lib")
+def _common_service_clients_check(logical_line, physical_line, filename,
+ ignored_list_file=None):
+ if 'tempest/services/' not in filename:
+ return False
+
+ if ignored_list_file is not None:
+ ignored_list = []
+ with open('tempest/hacking/' + ignored_list_file) as f:
+ for line in f:
+ ignored_list.append(line.strip())
+
+ if filename in ignored_list:
+ return False
+
+ if not METHOD.match(physical_line):
+ return False
+
+ if pep8.noqa(physical_line):
+ return False
+
+ return True
+
+
def get_resources_on_service_clients(logical_line, physical_line, filename,
line_number, lines):
"""Check that service client names of GET should be consistent
T110
"""
- if 'tempest/services/' not in filename:
- return
-
- ignored_list = []
- with open('tempest/hacking/ignored_list_T110.txt') as f:
- for line in f:
- ignored_list.append(line.strip())
-
- if filename in ignored_list:
- return
-
- if not METHOD.match(physical_line):
- return
-
- if pep8.noqa(physical_line):
+ if not _common_service_clients_check(logical_line, physical_line,
+ filename, 'ignored_list_T110.txt'):
return
for line in lines[line_number:]:
@@ -185,6 +196,32 @@
yield (0, msg)
+def delete_resources_on_service_clients(logical_line, physical_line, filename,
+ line_number, lines):
+ """Check that service client names of DELETE should be consistent
+
+ T111
+ """
+ if not _common_service_clients_check(logical_line, physical_line,
+ filename, 'ignored_list_T111.txt'):
+ return
+
+ for line in lines[line_number:]:
+ if METHOD.match(line) or CLASS.match(line):
+ # the end of a method
+ return
+
+ if 'self.delete(' not in line:
+ continue
+
+ if METHOD_DELETE_RESOURCE.match(logical_line):
+ return
+
+ msg = ("T111: [DELETE /resources/<id>] methods should be "
+ "delete_<resource name>")
+ yield (0, msg)
+
+
def factory(register):
register(import_no_clients_in_api_and_scenario_tests)
register(scenario_tests_need_service_tags)
@@ -195,3 +232,4 @@
register(no_mutable_default_args)
register(no_testtools_skip_decorator)
register(get_resources_on_service_clients)
+ register(delete_resources_on_service_clients)
diff --git a/tempest/hacking/ignored_list_T110.txt b/tempest/hacking/ignored_list_T110.txt
index 7c3e830..8de3151 100644
--- a/tempest/hacking/ignored_list_T110.txt
+++ b/tempest/hacking/ignored_list_T110.txt
@@ -1,13 +1,8 @@
-./tempest/services/compute/json/servers_client.py
-./tempest/services/database/json/flavors_client.py
-./tempest/services/identity/v3/json/credentials_client.py
./tempest/services/identity/v3/json/identity_client.py
-./tempest/services/identity/v3/json/policy_client.py
-./tempest/services/identity/v3/json/region_client.py
./tempest/services/messaging/json/messaging_client.py
./tempest/services/object_storage/object_client.py
+./tempest/services/telemetry/json/alarming_client.py
./tempest/services/telemetry/json/telemetry_client.py
-./tempest/services/volume/json/qos_client.py
-./tempest/services/volume/json/backups_client.py
-./tempest/services/image/v2/json/image_client.py
+./tempest/services/volume/base/base_qos_client.py
+./tempest/services/volume/base/base_backups_client.py
./tempest/services/baremetal/base.py
diff --git a/tempest/hacking/ignored_list_T111.txt b/tempest/hacking/ignored_list_T111.txt
new file mode 100644
index 0000000..8017e76
--- /dev/null
+++ b/tempest/hacking/ignored_list_T111.txt
@@ -0,0 +1 @@
+./tempest/services/baremetal/base.py
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 9f283c5..fc56ad5 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -23,7 +23,7 @@
from tempest_lib.common.utils import misc as misc_utils
from tempest_lib import exceptions as lib_exc
-from tempest.common import fixed_network
+from tempest.common import compute
from tempest.common.utils import data_utils
from tempest.common.utils.linux import remote_client
from tempest.common import waiters
@@ -55,7 +55,8 @@
cls.images_client = cls.manager.images_client
cls.keypairs_client = cls.manager.keypairs_client
# Nova security groups client
- cls.security_groups_client = cls.manager.security_groups_client
+ cls.compute_security_groups_client = (
+ cls.manager.compute_security_groups_client)
cls.security_group_rules_client = (
cls.manager.security_group_rules_client)
cls.servers_client = cls.manager.servers_client
@@ -65,6 +66,7 @@
cls.networks_client = cls.manager.networks_client
cls.ports_client = cls.manager.ports_client
cls.subnets_client = cls.manager.subnets_client
+ cls.floating_ips_client = cls.manager.floating_ips_client
# Heat client
cls.orchestration_client = cls.manager.orchestration_client
@@ -157,52 +159,100 @@
return body['keypair']
def create_server(self, name=None, image=None, flavor=None,
- wait_on_boot=True, wait_on_delete=True,
- create_kwargs=None):
- """Creates VM instance.
+ validatable=False, wait_until=None,
+ wait_on_delete=True, clients=None, **kwargs):
+ """Wrapper utility that returns a test server.
- @param image: image from which to create the instance
- @param wait_on_boot: wait for status ACTIVE before continue
- @param wait_on_delete: force synchronous delete on cleanup
- @param create_kwargs: additional details for instance creation
- @return: server dict
+ This wrapper utility calls the common create test server and
+ returns a test server. The purpose of this wrapper is to minimize
+ the impact on the code of the tests already using this
+ function.
"""
- if name is None:
- name = data_utils.rand_name(self.__class__.__name__)
- if image is None:
- image = CONF.compute.image_ref
- if flavor is None:
- flavor = CONF.compute.flavor_ref
- if create_kwargs is None:
- create_kwargs = {}
- network = self.get_tenant_network()
- create_kwargs = fixed_network.set_networks_kwarg(network,
- create_kwargs)
- LOG.debug("Creating a server (name: %s, image: %s, flavor: %s)",
- name, image, flavor)
- server = self.servers_client.create_server(name=name, imageRef=image,
- flavorRef=flavor,
- **create_kwargs)['server']
+ # NOTE(jlanoux): As a first step, ssh checks in the scenario
+ # tests need to be run regardless of the run_validation and
+ # validatable parameters and thus until the ssh validation job
+ # becomes voting in CI. The test resources management and IP
+ # association are taken care of in the scenario tests.
+ # Therefore, the validatable parameter is set to false in all
+ # those tests. In this way create_server just return a standard
+ # server and the scenario tests always perform ssh checks.
+
+ # Needed for the cross_tenant_traffic test:
+ if clients is None:
+ clients = self.manager
+
+ vnic_type = CONF.network.port_vnic_type
+
+ # If vnic_type is configured create port for
+ # every network
+ if vnic_type:
+ ports = []
+ networks = []
+ create_port_body = {'binding:vnic_type': vnic_type,
+ 'namestart': 'port-smoke'}
+ if kwargs:
+ # Convert security group names to security group ids
+ # to pass to create_port
+ if 'security_groups' in kwargs:
+ security_groups =\
+ clients.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 kwargs.pop(
+ 'security_groups')]
+ security_groups_ids = [sec_dict[s]
+ for s in sec_groups_names]
+
+ if security_groups_ids:
+ create_port_body[
+ 'security_groups'] = security_groups_ids
+ networks = kwargs.pop('networks')
+
+ # 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 = clients.networks_client.list_networks(
+ filters={'router:external': False})
+ self.assertEqual(1, len(networks),
+ "There is more than one"
+ " network for the tenant")
+ for net in networks:
+ net_id = net['uuid']
+ port = self._create_port(network_id=net_id,
+ client=clients.ports_client,
+ **create_port_body)
+ ports.append({'port': port.id})
+ if ports:
+ kwargs['networks'] = ports
+ self.ports = ports
+
+ tenant_network = self.get_tenant_network()
+
+ body, servers = compute.create_test_server(
+ clients,
+ tenant_network=tenant_network,
+ wait_until=wait_until,
+ **kwargs)
+
+ # TODO(jlanoux) Move wait_on_delete in compute.py
if wait_on_delete:
self.addCleanup(waiters.wait_for_server_termination,
- self.servers_client,
- server['id'])
+ clients.servers_client,
+ body['id'])
+
self.addCleanup_with_wait(
waiter_callable=waiters.wait_for_server_termination,
- thing_id=server['id'], thing_id_param='server_id',
+ thing_id=body['id'], thing_id_param='server_id',
cleanup_callable=self.delete_wrapper,
- cleanup_args=[self.servers_client.delete_server, server['id']],
- waiter_client=self.servers_client)
- if wait_on_boot:
- waiters.wait_for_server_status(self.servers_client,
- server_id=server['id'],
- status='ACTIVE')
- # 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.assertEqual(server['name'], name)
+ cleanup_args=[clients.servers_client.delete_server, body['id']],
+ waiter_client=clients.servers_client)
+ server = clients.servers_client.show_server(body['id'])['server']
return server
def create_volume(self, size=None, name=None, snapshot_id=None,
@@ -237,7 +287,7 @@
return volume
def _create_loginable_secgroup_rule(self, secgroup_id=None):
- _client = self.security_groups_client
+ _client = self.compute_security_groups_client
_client_rules = self.security_group_rules_client
if secgroup_id is None:
sgs = _client.list_security_groups()['security_groups']
@@ -279,13 +329,14 @@
# Create security group
sg_name = data_utils.rand_name(self.__class__.__name__)
sg_desc = sg_name + " description"
- secgroup = self.security_groups_client.create_security_group(
+ secgroup = self.compute_security_groups_client.create_security_group(
name=sg_name, description=sg_desc)['security_group']
self.assertEqual(secgroup['name'], sg_name)
self.assertEqual(secgroup['description'], sg_desc)
- self.addCleanup(self.delete_wrapper,
- self.security_groups_client.delete_security_group,
- secgroup['id'])
+ self.addCleanup(
+ self.delete_wrapper,
+ self.compute_security_groups_client.delete_security_group,
+ secgroup['id'])
# Add rules to the security group
self._create_loginable_secgroup_rule(secgroup['id'])
@@ -320,7 +371,7 @@
username = CONF.scenario.ssh_user
# Set this with 'keypair' or others to log in with keypair or
# username/password.
- if CONF.compute.ssh_auth_method == 'keypair':
+ if CONF.validation.auth_method == 'keypair':
password = None
if private_key is None:
private_key = self.keypair['private_key']
@@ -380,20 +431,22 @@
(img_path, img_container_format, img_disk_format,
img_properties, ami_img_path, ari_img_path, aki_img_path))
try:
- self.image = self._image_create('scenario-img',
- img_container_format,
- img_path,
- disk_format=img_disk_format,
- properties=img_properties)
+ image = self._image_create('scenario-img',
+ img_container_format,
+ img_path,
+ disk_format=img_disk_format,
+ properties=img_properties)
except IOError:
LOG.debug("A qcow2 image was not found. Try to get a uec image.")
kernel = self._image_create('scenario-aki', 'aki', aki_img_path)
ramdisk = self._image_create('scenario-ari', 'ari', ari_img_path)
properties = {'kernel_id': kernel, 'ramdisk_id': ramdisk}
- self.image = self._image_create('scenario-ami', 'ami',
- path=ami_img_path,
- properties=properties)
- LOG.debug("image:%s" % self.image)
+ image = self._image_create('scenario-ami', 'ami',
+ path=ami_img_path,
+ properties=properties)
+ LOG.debug("image:%s" % image)
+
+ return image
def _log_console_output(self, servers=None):
if not CONF.compute_feature_enabled.console_output:
@@ -404,7 +457,7 @@
servers = servers['servers']
for server in servers:
console_output = self.servers_client.get_console_output(
- server['id'], length=None)['output']
+ server['id'])['output']
LOG.debug('Console output for %s\nbody=\n%s',
server['id'], console_output)
@@ -488,7 +541,7 @@
def ping_ip_address(self, ip_address, should_succeed=True,
ping_timeout=None):
- timeout = ping_timeout or CONF.compute.ping_timeout
+ timeout = ping_timeout or CONF.validation.ping_timeout
cmd = ['ping', '-c1', '-w1', ip_address]
def ping():
@@ -565,7 +618,7 @@
"""Create a floating IP and associates to a server on Nova"""
floating_ip = (self.compute_floating_ips_client.
- create_floating_ip(pool_name)['floating_ip'])
+ create_floating_ip(pool=pool_name)['floating_ip'])
self.addCleanup(self.delete_wrapper,
self.compute_floating_ips_client.delete_floating_ip,
floating_ip['id'])
@@ -693,8 +746,8 @@
def cidr_in_use(cidr, tenant_id):
"""Check cidr existence
- :return True if subnet with cidr already exist in tenant
- False else
+ :returns: True if subnet with cidr already exist in tenant
+ False else
"""
cidr_in_use = self._list_subnets(tenant_id=tenant_id, cidr=cidr)
return len(cidr_in_use) != 0
@@ -759,8 +812,9 @@
def _get_server_port_id_and_ip4(self, server, ip_addr=None):
ports = self._list_ports(device_id=server['id'], status='ACTIVE',
fixed_ip=ip_addr)
- # it might happen here that this port has more then one ip address
- # as in case of dual stack- when this port is created on 2 subnets
+ # A port can have more then one IP address in some cases.
+ # If the network is dual-stack (IPv4 + IPv6), this port is associated
+ # with 2 subnets
port_map = [(p["id"], fxip["ip_address"])
for p in ports
for fxip in p["fixed_ips"]
@@ -786,7 +840,7 @@
if not external_network_id:
external_network_id = CONF.network.public_network_id
if not client:
- client = self.network_client
+ client = self.floating_ips_client
if not port_id:
port_id, ip4 = self._get_server_port_id_and_ip4(thing)
else:
@@ -862,18 +916,20 @@
self._log_net_info(e)
raise
- def _check_remote_connectivity(self, source, dest, should_succeed=True):
+ def _check_remote_connectivity(self, source, dest, should_succeed=True,
+ nic=None):
"""check ping server via source ssh connection
:param source: RemoteClient: an ssh connection from which to ping
:param dest: and IP to ping against
:param should_succeed: boolean should ping succeed or not
+ :param nic: specific network interface to ping from
:returns: boolean -- should_succeed == ping
:returns: ping is false if ping failed
"""
def ping_remote():
try:
- source.ping_host(dest)
+ source.ping_host(dest, nic=nic)
except lib_exc.SSHExecCommandFailed:
LOG.warn('Failed to ping IP: %s via a ssh connection from: %s.'
% (dest, source.ssh_client.host))
@@ -881,7 +937,7 @@
return should_succeed
return tempest.test.call_until_true(ping_remote,
- CONF.compute.ping_timeout,
+ CONF.validation.ping_timeout,
1)
def _create_security_group(self, client=None, tenant_id=None,
@@ -1132,71 +1188,6 @@
subnet.add_to_router(router.id)
return network, subnet, router
- def create_server(self, name=None, image=None, flavor=None,
- wait_on_boot=True, wait_on_delete=True,
- network_client=None, networks_client=None,
- ports_client=None, create_kwargs=None):
- if network_client is None:
- network_client = self.network_client
- if networks_client is None:
- networks_client = self.networks_client
- if ports_client is None:
- ports_client = self.ports_client
-
- vnic_type = CONF.network.port_vnic_type
-
- # If vnic_type is configured create port for
- # every network
- if vnic_type:
- ports = []
- networks = []
- create_port_body = {'binding:vnic_type': vnic_type,
- 'namestart': 'port-smoke'}
- if create_kwargs:
- # Convert security group names to security group ids
- # to pass to create_port
- if create_kwargs.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.get(
- 'security_groups')]
- security_groups_ids = [sec_dict[s]
- for s in sec_groups_names]
-
- if security_groups_ids:
- create_port_body[
- 'security_groups'] = security_groups_ids
- networks = create_kwargs.get('networks')
-
- # 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 = networks_client.list_networks(filters={
- 'router:external': False})
- self.assertEqual(1, len(networks),
- "There is more than one"
- " network for the tenant")
- for net in networks:
- net_id = net['uuid']
- port = self._create_port(network_id=net_id,
- client=ports_client,
- **create_port_body)
- ports.append({'port': port.id})
- if ports:
- create_kwargs['networks'] = ports
- self.ports = ports
-
- return super(NetworkScenarioTest, self).create_server(
- name=name, image=image, flavor=flavor,
- wait_on_boot=wait_on_boot, wait_on_delete=wait_on_delete,
- create_kwargs=create_kwargs)
-
# power/provision states as of icehouse
class BaremetalPowerStates(object):
@@ -1319,11 +1310,8 @@
dest.validate_authentication()
def boot_instance(self):
- create_kwargs = {
- 'key_name': self.keypair['name']
- }
self.instance = self.create_server(
- wait_on_boot=False, create_kwargs=create_kwargs)
+ key_name=self.keypair['name'])
self.wait_node(self.instance['id'])
self.node = self.get_node(instance_id=self.instance['id'])
@@ -1369,16 +1357,6 @@
else:
cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
- def _wait_for_volume_status(self, status):
- self.status_timeout(
- self.volume_client.volumes, self.volume.id, status)
-
- def nova_boot(self):
- self.keypair = self.create_keypair()
- create_kwargs = {'key_name': self.keypair['name']}
- self.server = self.create_server(image=self.image,
- create_kwargs=create_kwargs)
-
def create_volume_type(self, client=None, name=None):
if not client:
client = self.admin_volume_types_client
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index fa05577..9415629 100644
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ b/tempest/scenario/test_baremetal_basic_ops.py
@@ -63,15 +63,6 @@
server_id=self.instance['id'],
status='ACTIVE')
- def create_remote_file(self, client, filename):
- """Create a file on the remote client connection.
-
- After creating the file, force a filesystem sync. Otherwise,
- if we issue a rebuild too quickly, the file may not exist.
- """
- client.exec_command('sudo touch ' + filename)
- client.exec_command('sync')
-
def verify_partition(self, client, label, mount, gib_size):
"""Verify a labeled partition's mount point and size."""
LOG.info("Looking for partition %s mounted on %s" % (label, mount))
@@ -118,12 +109,11 @@
@test.idempotent_id('549173a5-38ec-42bb-b0e2-c8b9f4a08943')
@test.services('baremetal', 'compute', 'image', 'network')
def test_baremetal_server_ops(self):
- test_filename = '/mnt/rebuild_test.txt'
self.add_keypair()
self.boot_instance()
self.validate_ports()
self.verify_connectivity()
- if CONF.compute.ssh_connect_method == 'floating':
+ if CONF.validation.connect_method == 'floating':
floating_ip = self.create_floating_ip(self.instance)['ip']
self.verify_connectivity(ip=floating_ip)
@@ -132,12 +122,13 @@
# We expect the ephemeral partition to be mounted on /mnt and to have
# the same size as our flavor definition.
eph_size = self.get_flavor_ephemeral_size()
- if eph_size > 0:
+ if eph_size:
preserve_ephemeral = True
self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
# Create the test file
- self.create_remote_file(vm_client, test_filename)
+ timestamp = self.create_timestamp(
+ floating_ip, private_key=self.keypair['private_key'])
else:
preserve_ephemeral = False
@@ -146,9 +137,9 @@
self.verify_connectivity()
# Check that we maintained our data
- if eph_size > 0:
- vm_client = self.get_remote_client(self.instance)
+ if eph_size:
self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
- vm_client.exec_command('ls ' + test_filename)
-
+ timestamp2 = self.get_timestamp(
+ floating_ip, private_key=self.keypair['private_key'])
+ self.assertEqual(timestamp, timestamp2)
self.terminate_instance()
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index 99837eb..dcd77ad 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -42,8 +42,12 @@
raise cls.skipException('Encrypted volume attach is not supported')
def launch_instance(self):
- self.glance_image_create()
- self.nova_boot()
+ image = self.glance_image_create()
+ keypair = self.create_keypair()
+
+ return self.create_server(image_id=image,
+ key_name=keypair['name'],
+ wait_until='ACTIVE')
def create_encrypted_volume(self, encryption_provider, volume_type):
volume_type = self.create_volume_type(name=volume_type)
@@ -52,26 +56,26 @@
key_size=512,
cipher='aes-xts-plain64',
control_location='front-end')
- self.volume = self.create_volume(volume_type=volume_type['name'])
+ return self.create_volume(volume_type=volume_type['name'])
- def attach_detach_volume(self):
- self.volume = self.nova_volume_attach(self.server, self.volume)
- self.nova_volume_detach(self.server, self.volume)
+ def attach_detach_volume(self, server, volume):
+ attached_volume = self.nova_volume_attach(server, volume)
+ self.nova_volume_detach(server, attached_volume)
@test.idempotent_id('79165fb4-5534-4b9d-8429-97ccffb8f86e')
@test.services('compute', 'volume', 'image')
def test_encrypted_cinder_volumes_luks(self):
- self.launch_instance()
- self.create_encrypted_volume('nova.volume.encryptors.'
- 'luks.LuksEncryptor',
- volume_type='luks')
- self.attach_detach_volume()
+ server = self.launch_instance()
+ volume = self.create_encrypted_volume('nova.volume.encryptors.'
+ 'luks.LuksEncryptor',
+ volume_type='luks')
+ self.attach_detach_volume(server, volume)
@test.idempotent_id('cbc752ed-b716-4717-910f-956cce965722')
@test.services('compute', 'volume', 'image')
def test_encrypted_cinder_volumes_cryptsetup(self):
- self.launch_instance()
- self.create_encrypted_volume('nova.volume.encryptors.'
- 'cryptsetup.CryptsetupEncryptor',
- volume_type='cryptsetup')
- self.attach_detach_volume()
+ server = self.launch_instance()
+ volume = self.create_encrypted_volume('nova.volume.encryptors.'
+ 'cryptsetup.CryptsetupEncryptor',
+ volume_type='cryptsetup')
+ self.attach_detach_volume(server, volume)
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index 6497f7a..b549ecb 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -79,17 +79,18 @@
waiters.wait_for_server_status(self.servers_client,
server['id'], status)
- def nova_boot(self):
+ def nova_boot(self, image):
name = data_utils.rand_name('scenario-server')
flavor_id = CONF.compute.flavor_ref
# Explicitly create secgroup to avoid cleanup at the end of testcases.
# Since no traffic is tested, we don't need to actually add rules to
# secgroup
- secgroup = self.security_groups_client.create_security_group(
+ secgroup = self.compute_security_groups_client.create_security_group(
name='secgroup-%s' % name,
description='secgroup-desc-%s' % name)['security_group']
- self.addCleanupClass(self.security_groups_client.delete_security_group,
- secgroup['id'])
+ self.addCleanupClass(
+ self.compute_security_groups_client.delete_security_group,
+ secgroup['id'])
create_kwargs = {
'min_count': CONF.scenario.large_ops_number,
'security_groups': [{'name': secgroup['name']}]
@@ -99,7 +100,7 @@
create_kwargs)
self.servers_client.create_server(
name=name,
- imageRef=self.image,
+ imageRef=image,
flavorRef=flavor_id,
**create_kwargs)
# needed because of bug 1199788
@@ -118,8 +119,8 @@
self._wait_for_server_status('ACTIVE')
def _large_ops_scenario(self):
- self.glance_image_create()
- self.nova_boot()
+ image = self.glance_image_create()
+ self.nova_boot(image)
@test.idempotent_id('14ba0e78-2ed9-4d17-9659-a48f4756ecb3')
@test.services('compute', 'image')
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index c3f3c78..2ef3cee 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -37,6 +37,18 @@
* with and without optional parameters
* check command outputs
+ Steps:
+ 1. Create image
+ 2. Create keypair
+ 3. Boot instance with keypair and get list of instances
+ 4. Create volume and show list of volumes
+ 5. Attach volume to instance and getlist of volumes
+ 6. Add IP to instance
+ 7. Create and add security group to instance
+ 8. Check SSH connection to instance
+ 9. Reboot instance
+ 10. Check SSH connection to instance after reboot
+
"""
def _wait_for_server_status(self, server, status):
@@ -46,11 +58,6 @@
waiters.wait_for_server_status(self.servers_client,
server_id, status)
- def nova_boot(self, keypair):
- create_kwargs = {'key_name': keypair['name']}
- return self.create_server(image=self.image,
- create_kwargs=create_kwargs)
-
def nova_list(self):
servers = self.servers_client.list_servers()
# The list servers in the compute client is inconsistent...
@@ -77,7 +84,7 @@
self.assertEqual(volume, got_volume)
def nova_reboot(self, server):
- self.servers_client.reboot_server(server['id'], 'SOFT')
+ self.servers_client.reboot_server(server['id'], type='SOFT')
self._wait_for_server_status(server, 'ACTIVE')
def check_partitions(self):
@@ -88,9 +95,9 @@
def create_and_add_security_group_to_server(self, server):
secgroup = self._create_security_group()
self.servers_client.add_security_group(server['id'],
- secgroup['name'])
+ name=secgroup['name'])
self.addCleanup(self.servers_client.remove_security_group,
- server['id'], secgroup['name'])
+ server['id'], name=secgroup['name'])
def wait_for_secgroup_add():
body = (self.servers_client.show_server(server['id'])
@@ -107,11 +114,12 @@
@test.idempotent_id('bdbb5441-9204-419d-a225-b4fdbfb1a1a8')
@test.services('compute', 'volume', 'image', 'network')
def test_minimum_basic_scenario(self):
- self.glance_image_create()
-
+ image = self.glance_image_create()
keypair = self.create_keypair()
- server = self.nova_boot(keypair)
+ server = self.create_server(image_id=image,
+ key_name=keypair['name'],
+ wait_until='ACTIVE')
servers = self.nova_list()
self.assertIn(server['id'], [x['id'] for x in servers])
@@ -130,10 +138,15 @@
floating_ip = self.create_floating_ip(server)
self.create_and_add_security_group_to_server(server)
+ # check that we can SSH to the server before reboot
self.linux_client = self.get_remote_client(
floating_ip['ip'], private_key=keypair['private_key'])
+
self.nova_reboot(server)
+ # check that we can SSH to the server after reboot
+ # (both connections are part of the scenario)
self.linux_client = self.get_remote_client(
floating_ip['ip'], private_key=keypair['private_key'])
+
self.check_partitions()
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 3689508..8aac98e 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -57,16 +57,13 @@
security_group = self._create_security_group()
network, subnet, router = self.create_networks()
public_network_id = CONF.network.public_network_id
- create_kwargs = {
- 'networks': [
- {'uuid': network.id},
- ],
- 'key_name': keypair['name'],
- 'security_groups': [{'name': security_group['name']}],
- }
server_name = data_utils.rand_name('server-smoke')
- server = self.create_server(name=server_name,
- create_kwargs=create_kwargs)
+ server = self.create_server(
+ name=server_name,
+ networks=[{'uuid': network.id}],
+ key_name=keypair['name'],
+ security_groups=[{'name': security_group['name']}],
+ wait_until='ACTIVE')
floating_ip = self.create_floating_ip(server, public_network_id)
# Verify that we can indeed connect to the server before we mess with
# it's state
@@ -115,7 +112,7 @@
@test.services('compute', 'network')
def test_server_connectivity_reboot(self):
server, keypair, floating_ip = self._setup_network_and_servers()
- self.servers_client.reboot_server(server['id'], reboot_type='SOFT')
+ self.servers_client.reboot_server(server['id'], type='SOFT')
self._wait_server_status_and_check_network_connectivity(
server, keypair, floating_ip)
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 8fefd9e..5bbff1c 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -155,16 +155,16 @@
keypair = self.create_keypair()
self.keypairs[keypair['name']] = keypair
security_groups = [{'name': self.security_group['name']}]
- create_kwargs = {
- 'networks': [
- {'uuid': network.id},
- ],
- 'key_name': keypair['name'],
- 'security_groups': security_groups,
- }
+ network = {'uuid': network.id}
if port_id is not None:
- create_kwargs['networks'][0]['port'] = port_id
- server = self.create_server(name=name, create_kwargs=create_kwargs)
+ network['port'] = port_id
+
+ server = self.create_server(
+ name=name,
+ networks=[network],
+ key_name=keypair['name'],
+ security_groups=security_groups,
+ wait_until='ACTIVE')
self.servers.append(server)
return server
@@ -287,7 +287,7 @@
num, new_nic = self.diff_list[0]
ssh_client.assign_static_ip(nic=new_nic,
addr=new_port.fixed_ips[0]['ip_address'])
- ssh_client.turn_nic_on(nic=new_nic)
+ ssh_client.set_nic_state(nic=new_nic)
def _get_server_nics(self, ssh_client):
reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
@@ -726,7 +726,7 @@
target_agent = list(hosting_agents if no_migration else
agent_list - hosting_agents)[0]
schedule_router(target_agent,
- self.router['id'])
+ router_id=self.router['id'])
self.assertEqual(
target_agent,
list_hosts(self.router.id)['agents'][0]['id'],
@@ -737,3 +737,49 @@
self.check_public_network_connectivity(
should_connect=True,
msg='After router rescheduling')
+
+ @test.requires_ext(service='network', extension='port-security')
+ @test.idempotent_id('7c0bb1a2-d053-49a4-98f9-ca1a1d849f63')
+ @test.services('compute', 'network')
+ def test_port_security_macspoofing_port(self):
+ """Tests port_security extension enforces mac spoofing
+
+ 1. create a new network
+ 2. connect VM to new network
+ 4. check VM can ping new network DHCP port
+ 5. spoof mac on new new network interface
+ 6. check Neutron enforces mac spoofing and blocks pings via spoofed
+ interface
+ 7. disable port-security on the spoofed port
+ 8. check Neutron allows pings via spoofed interface
+ """
+ spoof_mac = "00:00:00:00:00:01"
+
+ # Create server
+ self._setup_network_and_servers()
+ self.check_public_network_connectivity(should_connect=True)
+ self._create_new_network()
+ self._hotplug_server()
+ fip, server = self.floating_ip_tuple
+ new_ports = self._list_ports(device_id=server["id"],
+ network_id=self.new_net["id"])
+ spoof_port = new_ports[0]
+ private_key = self._get_server_key(server)
+ ssh_client = self.get_remote_client(fip.floating_ip_address,
+ private_key=private_key)
+ spoof_nic = ssh_client.get_nic_name(spoof_port["mac_address"])
+ dhcp_ports = self._list_ports(device_owner="network:dhcp",
+ network_id=self.new_net["id"])
+ new_net_dhcp = dhcp_ports[0]["fixed_ips"][0]["ip_address"]
+ self._check_remote_connectivity(ssh_client, dest=new_net_dhcp,
+ nic=spoof_nic, should_succeed=True)
+ ssh_client.set_mac_address(spoof_nic, spoof_mac)
+ new_mac = ssh_client.get_mac_address(nic=spoof_nic)
+ self.assertEqual(spoof_mac, new_mac)
+ self._check_remote_connectivity(ssh_client, dest=new_net_dhcp,
+ nic=spoof_nic, should_succeed=False)
+ self.ports_client.update_port(spoof_port["id"],
+ port_security_enabled=False,
+ security_groups=[])
+ self._check_remote_connectivity(ssh_client, dest=new_net_dhcp,
+ nic=spoof_nic, should_succeed=True)
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 151eef8..d6ad46a 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -65,9 +65,6 @@
super(TestGettingAddress, self).setUp()
self.keypair = self.create_keypair()
self.sec_grp = self._create_security_group(tenant_id=self.tenant_id)
- self.srv_kwargs = {
- 'key_name': self.keypair['name'],
- 'security_groups': [{'name': self.sec_grp['name']}]}
def prepare_network(self, address6_mode, n_subnets6=1, dualnet=False):
"""Prepare network
@@ -119,11 +116,13 @@
def prepare_server(self, networks=None):
username = CONF.compute.image_ssh_user
- create_kwargs = self.srv_kwargs
networks = networks or [self.network]
- create_kwargs['networks'] = [{'uuid': n.id} for n in networks]
- srv = self.create_server(create_kwargs=create_kwargs)
+ srv = self.create_server(
+ key_name=self.keypair['name'],
+ security_groups=[{'name': self.sec_grp['name']}],
+ networks=[{'uuid': n.id} for n in networks],
+ wait_until='ACTIVE')
fip = self.create_floating_ip(thing=srv)
ips = self.define_server_ips(srv=srv)
ssh = self.get_remote_client(
@@ -148,7 +147,7 @@
"ports: %s")
% (self.network_v6, ports))
mac6 = ports[0]
- ssh.turn_nic_on(ssh.get_nic_name(mac6))
+ ssh.set_nic_state(ssh.get_nic_name(mac6))
def _prepare_and_test(self, address6_mode, n_subnets6=1, dualnet=False):
net_list = self.prepare_network(address6_mode=address6_mode,
@@ -181,10 +180,10 @@
guest_has_address, sshv4_2, ips_from_api_2['6'][i])
self.assertTrue(test.call_until_true(srv1_v6_addr_assigned,
- CONF.compute.ping_timeout, 1))
+ CONF.validation.ping_timeout, 1))
self.assertTrue(test.call_until_true(srv2_v6_addr_assigned,
- CONF.compute.ping_timeout, 1))
+ CONF.validation.ping_timeout, 1))
self._check_connectivity(sshv4_1, ips_from_api_2['4'])
self._check_connectivity(sshv4_2, ips_from_api_1['4'])
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 51188d5..e266dc2 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -234,23 +234,16 @@
def _create_server(self, name, tenant, security_groups=None):
"""creates a server and assigns to security group"""
- self._set_compute_context(tenant)
if security_groups is None:
security_groups = [tenant.security_groups['default']]
security_groups_names = [{'name': s['name']} for s in security_groups]
- create_kwargs = {
- 'networks': [
- {'uuid': tenant.network.id},
- ],
- 'key_name': tenant.keypair['name'],
- 'security_groups': security_groups_names
- }
server = self.create_server(
name=name,
- network_client=tenant.manager.network_client,
- networks_client=tenant.manager.networks_client,
- ports_client=tenant.manager.ports_client,
- create_kwargs=create_kwargs)
+ networks=[{'uuid': tenant.network.id}],
+ key_name=tenant.keypair['name'],
+ security_groups=security_groups_names,
+ wait_until='ACTIVE',
+ clients=tenant.manager)
self.assertEqual(
sorted([s['name'] for s in security_groups]),
sorted([s['name'] for s in server['security_groups']]))
@@ -283,7 +276,7 @@
public_network_id = CONF.network.public_network_id
floating_ip = self.create_floating_ip(
server, public_network_id,
- client=tenant.manager.network_client)
+ client=tenant.manager.floating_ips_client)
self.floating_ips.setdefault(server['id'], floating_ip)
def _create_tenant_network(self, tenant):
@@ -293,10 +286,6 @@
subnets_client=tenant.manager.subnets_client)
tenant.set_network(network, subnet, router)
- def _set_compute_context(self, tenant):
- self.servers_client = tenant.manager.servers_client
- return self.servers_client
-
def _deploy_tenant(self, tenant_or_id):
"""creates:
@@ -310,7 +299,6 @@
tenant = self.tenants[tenant_or_id]
else:
tenant = tenant_or_id
- self._set_compute_context(tenant)
self._create_tenant_keypairs(tenant)
self._create_tenant_network(tenant)
self._create_tenant_security_groups(tenant)
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index 9387dc7..4b932ce 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -53,7 +53,7 @@
@test.services('compute')
def test_resize_server_confirm(self):
# We create an instance for use in this test
- instance = self.create_server()
+ instance = self.create_server(wait_until='ACTIVE')
instance_id = instance['id']
resize_flavor = CONF.compute.flavor_ref_alt
LOG.debug("Resizing instance %s from flavor %s to flavor %s",
@@ -74,7 +74,7 @@
@test.services('compute')
def test_server_sequence_suspend_resume(self):
# We create an instance for use in this test
- instance = self.create_server()
+ instance = self.create_server(wait_until='ACTIVE')
instance_id = instance['id']
LOG.debug("Suspending instance %s. Current status: %s",
instance_id, instance['status'])
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 8a19254..239e120 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -72,20 +72,6 @@
def add_keypair(self):
self.keypair = self.create_keypair()
- def boot_instance(self):
- # Create server with image and flavor from input scenario
- security_groups = [{'name': self.security_group['name']}]
- self.md = {'meta1': 'data1', 'meta2': 'data2', 'metaN': 'dataN'}
- create_kwargs = {
- 'key_name': self.keypair['name'],
- 'security_groups': security_groups,
- 'config_drive': CONF.compute_feature_enabled.config_drive,
- 'metadata': self.md
- }
- self.instance = self.create_server(image=self.image_ref,
- flavor=self.flavor_ref,
- create_kwargs=create_kwargs)
-
def verify_ssh(self):
if self.run_ssh:
# Obtain a floating IP
@@ -139,7 +125,16 @@
def test_server_basicops(self):
self.add_keypair()
self.security_group = self._create_security_group()
- self.boot_instance()
+ security_groups = [{'name': self.security_group['name']}]
+ self.md = {'meta1': 'data1', 'meta2': 'data2', 'metaN': 'dataN'}
+ self.instance = self.create_server(
+ image_id=self.image_ref,
+ flavor=self.flavor_ref,
+ key_name=self.keypair['name'],
+ security_groups=security_groups,
+ config_drive=CONF.compute_feature_enabled.config_drive,
+ metadata=self.md,
+ wait_until='ACTIVE')
self.verify_ssh()
self.verify_metadata()
self.verify_metadata_on_config_drive()
diff --git a/tempest/scenario/test_server_multinode.py b/tempest/scenario/test_server_multinode.py
index 403804d..7e0e41c 100644
--- a/tempest/scenario/test_server_multinode.py
+++ b/tempest/scenario/test_server_multinode.py
@@ -60,15 +60,11 @@
servers = []
for host in hosts[:CONF.compute.min_compute_nodes]:
- create_kwargs = {
- 'availability_zone': '%(zone)s:%(host_name)s' % host
- }
-
# by getting to active state here, this means this has
# landed on the host in question.
- inst = self.create_server(image=CONF.compute.image_ref,
- flavor=CONF.compute.flavor_ref,
- create_kwargs=create_kwargs)
+ inst = self.create_server(
+ availability_zone='%(zone)s:%(host_name)s' % host,
+ wait_until='ACTIVE')
server = self.servers_client.show_server(inst['id'])['server']
servers.append(server)
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 5778107..378ae9d 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -59,10 +59,6 @@
security_group = self._create_security_group()
security_groups = [{'name': security_group['name']}]
- create_kwargs = {
- 'key_name': keypair['name'],
- 'security_groups': security_groups
- }
if boot_from_volume:
volume = self.create_volume(size=CONF.volume.volume_size,
@@ -72,11 +68,17 @@
'volume_id': volume['id'],
'delete_on_termination': '0'}]
- create_kwargs['block_device_mapping'] = bd_map
- server = self.create_server(create_kwargs=create_kwargs)
+ server = self.create_server(
+ key_name=keypair['name'],
+ security_groups=security_groups,
+ block_device_mapping=bd_map,
+ wait_until='ACTIVE')
else:
- server = self.create_server(image=CONF.compute.image_ref,
- create_kwargs=create_kwargs)
+ server = self.create_server(
+ image_id=CONF.compute.image_ref,
+ key_name=keypair['name'],
+ security_groups=security_groups,
+ wait_until='ACTIVE')
instance_ip = self.get_server_or_ip(server)
timestamp = self.create_timestamp(instance_ip,
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index cd59334..f3b6558 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -36,14 +36,6 @@
"""
- def _boot_image(self, image_id, keypair, security_group):
- security_groups = [{'name': security_group['name']}]
- create_kwargs = {
- 'key_name': keypair['name'],
- 'security_groups': security_groups
- }
- return self.create_server(image=image_id, create_kwargs=create_kwargs)
-
@test.idempotent_id('608e604b-1d63-4a82-8e3e-91bc665c90b4')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting is not available.')
@@ -54,8 +46,12 @@
security_group = self._create_security_group()
# boot an instance and create a timestamp file in it
- server = self._boot_image(CONF.compute.image_ref, keypair,
- security_group)
+ server = self.create_server(
+ image_id=CONF.compute.image_ref,
+ key_name=keypair['name'],
+ security_groups=[{'name': security_group['name']}],
+ wait_until='ACTIVE')
+
instance_ip = self.get_server_or_ip(server)
timestamp = self.create_timestamp(instance_ip,
private_key=keypair['private_key'])
@@ -64,8 +60,11 @@
snapshot_image = self.create_server_snapshot(server=server)
# boot a second instance from the snapshot
- server_from_snapshot = self._boot_image(snapshot_image['id'],
- keypair, security_group)
+ server_from_snapshot = self.create_server(
+ image_id=snapshot_image['id'],
+ key_name=keypair['name'],
+ security_groups=[{'name': security_group['name']}],
+ wait_until='ACTIVE')
# check the existence of the timestamp file in the second instance
server_from_snapshot_ip = self.get_server_or_ip(server_from_snapshot)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 05ae33e..faae800 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -64,14 +64,6 @@
self.snapshots_client.wait_for_snapshot_status(volume_snapshot['id'],
status)
- def _boot_image(self, image_id, keypair, security_group):
- security_groups = [{'name': security_group['name']}]
- create_kwargs = {
- 'key_name': keypair['name'],
- 'security_groups': security_groups
- }
- return self.create_server(image=image_id, create_kwargs=create_kwargs)
-
def _create_volume_snapshot(self, volume):
snapshot_name = data_utils.rand_name('scenario-snapshot')
snapshot = self.snapshots_client.create_snapshot(
@@ -135,8 +127,11 @@
# boot an instance and create a timestamp file in it
volume = self._create_volume()
- server = self._boot_image(CONF.compute.image_ref, keypair,
- security_group)
+ server = self.create_server(
+ image_id=CONF.compute.image_ref,
+ key_name=keypair['name'],
+ security_groups=security_group,
+ wait_until='ACTIVE')
# create and add floating IP to server1
ip_for_server = self.get_server_or_ip(server)
@@ -160,8 +155,10 @@
snapshot_id=volume_snapshot['id'])
# boot second instance from the snapshot(instance2)
- server_from_snapshot = self._boot_image(snapshot_image['id'],
- keypair, security_group)
+ server_from_snapshot = self.create_server(
+ image_id=snapshot_image['id'],
+ key_name=keypair['name'],
+ security_groups=security_group)
# create and add floating IP to server_from_snapshot
ip_for_snapshot = self.get_server_or_ip(server_from_snapshot)
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 96e79e6..81ecda0 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -69,7 +69,10 @@
{'name': security_group['name']}]
create_kwargs.update(self._get_bdm(
vol_id, delete_on_termination=delete_on_termination))
- return self.create_server(image='', create_kwargs=create_kwargs)
+ return self.create_server(
+ image='',
+ wait_until='ACTIVE',
+ **create_kwargs)
def _create_snapshot_from_volume(self, vol_id):
snap_name = data_utils.rand_name('snapshot')
@@ -158,7 +161,8 @@
self._delete_server(instance)
# boot instance from EBS image
- instance = self.create_server(image=image['id'])
+ instance = self.create_server(
+ image_id=image['id'])
# just ensure that instance booted
# delete instance
diff --git a/tempest/services/baremetal/base.py b/tempest/services/baremetal/base.py
index 004c0de..d8cb99d 100644
--- a/tempest/services/baremetal/base.py
+++ b/tempest/services/baremetal/base.py
@@ -59,7 +59,7 @@
:param resource_name: The name of the REST resource, e.g., 'nodes'.
:param uuid: The unique identifier of an object in UUID format.
- :return: Relative URI for the resource or object.
+ :returns: Relative URI for the resource or object.
"""
prefix = self.uri_prefix if not permanent else ''
@@ -68,18 +68,18 @@
res=resource_name,
uuid='/%s' % uuid if uuid else '')
- def _make_patch(self, allowed_attributes, **kw):
+ def _make_patch(self, allowed_attributes, **kwargs):
"""Create a JSON patch according to RFC 6902.
:param allowed_attributes: An iterable object that contains a set of
allowed attributes for an object.
- :param **kw: Attributes and new values for them.
- :return: A JSON path that sets values of the specified attributes to
+ :param **kwargs: Attributes and new values for them.
+ :returns: A JSON path that sets values of the specified attributes to
the new ones.
"""
- def get_change(kw, path='/'):
- for name, value in six.iteritems(kw):
+ def get_change(kwargs, path='/'):
+ for name, value in six.iteritems(kwargs):
if isinstance(value, dict):
for ch in get_change(value, path + '%s/' % name):
yield ch
@@ -92,7 +92,7 @@
'value': value,
'op': 'replace'}
- patch = [ch for ch in get_change(kw)
+ patch = [ch for ch in get_change(kwargs)
if ch['path'].lstrip('/') in allowed_attributes]
return patch
@@ -101,8 +101,8 @@
"""Get the list of objects of the specified type.
:param resource: The name of the REST resource, e.g., 'nodes'.
- "param **kw: Parameters for the request.
- :return: A tuple with the server response and deserialized JSON list
+ :param **kwargs: Parameters for the request.
+ :returns: A tuple with the server response and deserialized JSON list
of objects
"""
@@ -119,7 +119,7 @@
"""Gets a specific object of the specified type.
:param uuid: Unique identifier of the object in UUID format.
- :return: Serialized object as a dictionary.
+ :returns: Serialized object as a dictionary.
"""
if 'uri' in kwargs:
@@ -137,7 +137,7 @@
:param resource: The name of the REST resource, e.g., 'nodes'.
:param object_dict: A Python dict that represents an object of the
specified type.
- :return: A tuple with the server response and the deserialized created
+ :returns: A tuple with the server response and the deserialized created
object.
"""
@@ -154,7 +154,7 @@
:param resource: The name of the REST resource, e.g., 'nodes'.
:param uuid: The unique identifier of an object in UUID format.
- :return: A tuple with the server response and the response body.
+ :returns: A tuple with the server response and the response body.
"""
uri = self._get_uri(resource, uuid)
@@ -168,7 +168,7 @@
:param resource: The name of the REST resource, e.g., 'nodes'.
:param uuid: The unique identifier of an object in UUID format.
- :return: A tuple with the server response and the serialized patched
+ :returns: A tuple with the server response and the serialized patched
object.
"""
@@ -190,7 +190,7 @@
"""Retrieves the desctription of the API.
:param version: The version of the API. Default: 'v1'.
- :return: Serialized description of API resources.
+ :returns: Serialized description of API resources.
"""
return self._list_request(version, permanent=True)
diff --git a/tempest/services/botoclients.py b/tempest/services/botoclients.py
index e117719..9d452ff 100644
--- a/tempest/services/botoclients.py
+++ b/tempest/services/botoclients.py
@@ -101,8 +101,8 @@
break
else:
ec2_cred = (identity_client.create_user_ec2_credentials(
- identity_client.user_id, identity_client.tenant_id)
- ['credential'])
+ identity_client.user_id,
+ tenant_id=identity_client.tenant_id)['credential'])
if not all((ec2_cred, ec2_cred['access'], ec2_cred['secret'])):
raise lib_exc.NotFound("Unable to get access and secret keys")
else:
diff --git a/tempest/services/compute/json/base.py b/tempest/services/compute/json/base.py
new file mode 100644
index 0000000..02e9f8b
--- /dev/null
+++ b/tempest/services/compute/json/base.py
@@ -0,0 +1,25 @@
+# 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.common import service_client
+
+
+class BaseComputeClient(service_client.ServiceClient):
+ api_microversion = None
+
+ def get_headers(self):
+ headers = super(BaseComputeClient, self).get_headers()
+ if self.api_microversion:
+ headers['X-OpenStack-Nova-API-Version'] = self.api_microversion
+ return headers
diff --git a/tempest/services/compute/json/floating_ips_client.py b/tempest/services/compute/json/floating_ips_client.py
index 69d06a3..b3e2f2f 100644
--- a/tempest/services/compute/json/floating_ips_client.py
+++ b/tempest/services/compute/json/floating_ips_client.py
@@ -42,11 +42,14 @@
self.validate_response(schema.create_get_floating_ip, resp, body)
return service_client.ResponseBody(resp, body)
- def create_floating_ip(self, pool_name=None):
- """Allocate a floating IP to the project."""
+ def create_floating_ip(self, **kwargs):
+ """Allocate a floating IP to the project.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-compute-v2.1.html#createFloatingIP
+ """
url = 'os-floating-ips'
- post_body = {'pool': pool_name}
- post_body = json.dumps(post_body)
+ post_body = json.dumps(kwargs)
resp, body = self.post(url, post_body)
body = json.loads(body)
self.validate_response(schema.create_get_floating_ip, resp, body)
diff --git a/tempest/services/compute/json/images_client.py b/tempest/services/compute/json/images_client.py
deleted file mode 100644
index 99fdfe6..0000000
--- a/tempest/services/compute/json/images_client.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright 2012 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 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 images as schema
-from tempest.common import service_client
-
-
-class ImagesClient(service_client.ServiceClient):
-
- def create_image(self, server_id, **kwargs):
- """Creates an image of the original server."""
-
- post_body = {'createImage': kwargs}
- post_body = json.dumps(post_body)
- resp, body = self.post('servers/%s/action' % server_id,
- post_body)
- self.validate_response(schema.create_image, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def list_images(self, detail=False, **params):
- """Returns a list of all images filtered by any parameters."""
- url = 'images'
- _schema = schema.list_images
- if detail:
- url += '/detail'
- _schema = schema.list_images_details
-
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(_schema, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_image(self, image_id):
- """Returns the details of a single image."""
- resp, body = self.get("images/%s" % image_id)
- self.expected_success(200, resp.status)
- body = json.loads(body)
- self.validate_response(schema.get_image, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def delete_image(self, image_id):
- """Deletes the provided image."""
- resp, body = self.delete("images/%s" % image_id)
- self.validate_response(schema.delete, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def list_image_metadata(self, image_id):
- """Lists all metadata items for an image."""
- resp, body = self.get("images/%s/metadata" % image_id)
- body = json.loads(body)
- self.validate_response(schema.image_metadata, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def set_image_metadata(self, image_id, meta):
- """Sets the metadata for an image."""
- post_body = json.dumps({'metadata': meta})
- resp, body = self.put('images/%s/metadata' % image_id, post_body)
- body = json.loads(body)
- self.validate_response(schema.image_metadata, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def update_image_metadata(self, image_id, meta):
- """Updates the metadata for an image."""
- post_body = json.dumps({'metadata': meta})
- resp, body = self.post('images/%s/metadata' % image_id, post_body)
- body = json.loads(body)
- self.validate_response(schema.image_metadata, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_image_metadata_item(self, image_id, key):
- """Returns the value for a specific image metadata key."""
- resp, body = self.get("images/%s/metadata/%s" % (image_id, key))
- body = json.loads(body)
- self.validate_response(schema.image_meta_item, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def set_image_metadata_item(self, image_id, key, meta):
- """Sets the value for a specific image metadata key."""
- post_body = json.dumps({'meta': meta})
- resp, body = self.put('images/%s/metadata/%s' % (image_id, key),
- post_body)
- body = json.loads(body)
- self.validate_response(schema.image_meta_item, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def delete_image_metadata_item(self, image_id, key):
- """Deletes a single image metadata key/value pair."""
- resp, body = self.delete("images/%s/metadata/%s" %
- (image_id, key))
- self.validate_response(schema.delete, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def is_resource_deleted(self, id):
- try:
- self.show_image(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 'image'
diff --git a/tempest/services/compute/json/instance_usage_audit_log_client.py b/tempest/services/compute/json/instance_usage_audit_log_client.py
deleted file mode 100644
index 4d9625e..0000000
--- a/tempest/services/compute/json/instance_usage_audit_log_client.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2013 IBM 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 tempest.api_schema.response.compute.v2_1 import \
- instance_usage_audit_logs as schema
-from tempest.common import service_client
-
-
-class InstanceUsagesAuditLogClient(service_client.ServiceClient):
-
- def list_instance_usage_audit_logs(self):
- url = 'os-instance_usage_audit_log'
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_instance_usage_audit_log,
- resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_instance_usage_audit_log(self, time_before):
- url = 'os-instance_usage_audit_log/%s' % time_before
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.get_instance_usage_audit_log, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/interfaces_client.py b/tempest/services/compute/json/interfaces_client.py
deleted file mode 100644
index fe076d8..0000000
--- a/tempest/services/compute/json/interfaces_client.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright 2013 IBM Corp.
-# 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 tempest.api_schema.response.compute.v2_1 import interfaces as schema
-from tempest.common import service_client
-
-
-class InterfacesClient(service_client.ServiceClient):
-
- def list_interfaces(self, server_id):
- resp, body = self.get('servers/%s/os-interface' % server_id)
- body = json.loads(body)
- self.validate_response(schema.list_interfaces, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def create_interface(self, server_id, **kwargs):
- post_body = {'interfaceAttachment': kwargs}
- post_body = json.dumps(post_body)
- resp, body = self.post('servers/%s/os-interface' % server_id,
- body=post_body)
- body = json.loads(body)
- self.validate_response(schema.get_create_interfaces, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_interface(self, server_id, port_id):
- resp, body = self.get('servers/%s/os-interface/%s' % (server_id,
- port_id))
- body = json.loads(body)
- self.validate_response(schema.get_create_interfaces, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def delete_interface(self, server_id, port_id):
- resp, body = self.delete('servers/%s/os-interface/%s' % (server_id,
- port_id))
- self.validate_response(schema.delete_interface, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/limits_client.py b/tempest/services/compute/json/limits_client.py
deleted file mode 100644
index b64b4a5..0000000
--- a/tempest/services/compute/json/limits_client.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 2012 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 oslo_serialization import jsonutils as json
-
-from tempest.api_schema.response.compute.v2_1 import limits as schema
-from tempest.common import service_client
-
-
-class LimitsClient(service_client.ServiceClient):
-
- def show_limits(self):
- resp, body = self.get("limits")
- body = json.loads(body)
- self.validate_response(schema.get_limit, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/migrations_client.py b/tempest/services/compute/json/migrations_client.py
deleted file mode 100644
index b302539..0000000
--- a/tempest/services/compute/json/migrations_client.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2014 NEC Corporation.
-#
-# 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.api_schema.response.compute.v2_1 import migrations as schema
-from tempest.common import service_client
-
-
-class MigrationsClient(service_client.ServiceClient):
-
- def list_migrations(self, **params):
- """Lists all migrations."""
-
- url = 'os-migrations'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_migrations, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/networks_client.py b/tempest/services/compute/json/networks_client.py
deleted file mode 100644
index dd20ee5..0000000
--- a/tempest/services/compute/json/networks_client.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2012 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 oslo_serialization import jsonutils as json
-
-from tempest.common import service_client
-
-
-class NetworksClient(service_client.ServiceClient):
-
- def list_networks(self):
- resp, body = self.get("os-networks")
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def show_network(self, network_id):
- resp, body = self.get("os-networks/%s" % network_id)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/quota_classes_client.py b/tempest/services/compute/json/quota_classes_client.py
deleted file mode 100644
index 7aac5e4..0000000
--- a/tempest/services/compute/json/quota_classes_client.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2012 NTT Data
-# 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 tempest.api_schema.response.compute.v2_1\
- import quota_classes as classes_schema
-from tempest.common import service_client
-
-
-class QuotaClassesClient(service_client.ServiceClient):
-
- def show_quota_class_set(self, quota_class_id):
- """List the quota class set for a quota class."""
-
- url = 'os-quota-class-sets/%s' % quota_class_id
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(classes_schema.get_quota_class_set, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def update_quota_class_set(self, quota_class_id, **kwargs):
- """Updates the quota class's limits for one or more resources."""
- post_body = json.dumps({'quota_class_set': kwargs})
-
- resp, body = self.put('os-quota-class-sets/%s' % quota_class_id,
- post_body)
-
- body = json.loads(body)
- self.validate_response(classes_schema.update_quota_class_set,
- resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/quotas_client.py b/tempest/services/compute/json/quotas_client.py
deleted file mode 100644
index e628b3a..0000000
--- a/tempest/services/compute/json/quotas_client.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright 2012 NTT Data
-# 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 tempest.api_schema.response.compute.v2_1 import quotas as schema
-from tempest.common import service_client
-
-
-class QuotasClient(service_client.ServiceClient):
-
- def show_quota_set(self, tenant_id, user_id=None):
- """List the quota set for a tenant."""
-
- url = 'os-quota-sets/%s' % tenant_id
- if user_id:
- url += '?user_id=%s' % user_id
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.get_quota_set, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_default_quota_set(self, tenant_id):
- """List the default quota set for a tenant."""
-
- url = 'os-quota-sets/%s/defaults' % tenant_id
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.get_quota_set, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def update_quota_set(self, tenant_id, user_id=None, **kwargs):
- """Updates the tenant's quota limits for one or more resources"""
- post_body = json.dumps({'quota_set': kwargs})
-
- if user_id:
- resp, body = self.put('os-quota-sets/%s?user_id=%s' %
- (tenant_id, user_id), post_body)
- else:
- resp, body = self.put('os-quota-sets/%s' % tenant_id,
- post_body)
-
- body = json.loads(body)
- self.validate_response(schema.update_quota_set, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def delete_quota_set(self, tenant_id):
- """Delete the tenant's quota set."""
- resp, body = self.delete('os-quota-sets/%s' % tenant_id)
- self.validate_response(schema.delete_quota, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/security_group_default_rules_client.py b/tempest/services/compute/json/security_group_default_rules_client.py
deleted file mode 100644
index b31baab..0000000
--- a/tempest/services/compute/json/security_group_default_rules_client.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright 2014 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 oslo_serialization import jsonutils as json
-
-from tempest.api_schema.response.compute.v2_1 import \
- security_group_default_rule as schema
-from tempest.common import service_client
-
-
-class SecurityGroupDefaultRulesClient(service_client.ServiceClient):
-
- def create_security_default_group_rule(self, **kwargs):
- """Creating security group default rules.
-
- ip_protocol : ip_protocol (icmp, tcp, udp).
- from_port: Port at start of range.
- to_port : Port at end of range.
- cidr : CIDR for address range.
- """
- post_body = json.dumps({'security_group_default_rule': kwargs})
- url = 'os-security-group-default-rules'
- resp, body = self.post(url, post_body)
- body = json.loads(body)
- self.validate_response(schema.create_get_security_group_default_rule,
- resp, body)
- return service_client.ResponseBody(resp, body)
-
- def delete_security_group_default_rule(self,
- security_group_default_rule_id):
- """Deletes the provided Security Group default rule."""
- resp, body = self.delete('os-security-group-default-rules/%s' % (
- security_group_default_rule_id))
- self.validate_response(schema.delete_security_group_default_rule,
- resp, body)
- return service_client.ResponseBody(resp, body)
-
- def list_security_group_default_rules(self):
- """List all Security Group default rules."""
- resp, body = self.get('os-security-group-default-rules')
- body = json.loads(body)
- self.validate_response(schema.list_security_group_default_rules,
- resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_security_group_default_rule(self, security_group_default_rule_id):
- """Return the details of provided Security Group default rule."""
- resp, body = self.get('os-security-group-default-rules/%s' %
- security_group_default_rule_id)
- body = json.loads(body)
- self.validate_response(schema.create_get_security_group_default_rule,
- resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/security_groups_client.py b/tempest/services/compute/json/security_groups_client.py
deleted file mode 100644
index c996079..0000000
--- a/tempest/services/compute/json/security_groups_client.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright 2012 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 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 security_groups as schema
-from tempest.common import service_client
-
-
-class SecurityGroupsClient(service_client.ServiceClient):
-
- def list_security_groups(self, **params):
- """List all security groups for a user."""
-
- url = 'os-security-groups'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_security_groups, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_security_group(self, security_group_id):
- """Get the details of a Security Group."""
- url = "os-security-groups/%s" % security_group_id
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.get_security_group, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def create_security_group(self, **kwargs):
- """Creates a new security group.
-
- name (Required): Name of security group.
- description (Required): Description of security group.
- """
- post_body = json.dumps({'security_group': kwargs})
- resp, body = self.post('os-security-groups', post_body)
- body = json.loads(body)
- self.validate_response(schema.get_security_group, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def update_security_group(self, security_group_id, **kwargs):
- """Update a security group.
-
- security_group_id: a security_group to update
- name: new name of security group
- description: new description of security group
- """
- post_body = json.dumps({'security_group': kwargs})
- resp, body = self.put('os-security-groups/%s' % security_group_id,
- post_body)
- body = json.loads(body)
- self.validate_response(schema.update_security_group, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def delete_security_group(self, security_group_id):
- """Deletes the provided Security Group."""
- resp, body = self.delete(
- 'os-security-groups/%s' % security_group_id)
- self.validate_response(schema.delete_security_group, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def is_resource_deleted(self, id):
- try:
- self.show_security_group(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 'security_group'
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 90b7a2d..c20295b 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -32,7 +32,10 @@
self.enable_instance_password = enable_instance_password
def create_server(self, **kwargs):
- """Create server
+ """Create server.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-compute-v2.1.html#createServer
Most parameters except the following are passed to the API without
any changes.
@@ -69,7 +72,10 @@
return service_client.ResponseBody(resp, body)
def update_server(self, server_id, **kwargs):
- """Update server
+ """Update server.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-compute-v2.1.html#updateServer
Most parameters except the following are passed to the API without
any changes.
@@ -85,20 +91,26 @@
return service_client.ResponseBody(resp, body)
def show_server(self, server_id):
- """Get server details"""
+ """Get server details."""
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)
def delete_server(self, server_id):
- """Delete server"""
+ """Delete server."""
resp, body = self.delete("servers/%s" % server_id)
self.validate_response(schema.delete_server, resp, body)
return service_client.ResponseBody(resp, body)
def list_servers(self, detail=False, **params):
- """List servers"""
+ """List servers.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-compute-v2.1.html#listServers
+ and http://developer.openstack.org/
+ api-ref-compute-v2.1.html#listDetailServers
+ """
url = 'servers'
_schema = schema.list_servers
@@ -140,23 +152,27 @@
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",
- backup_type=backup_type,
- rotation=rotation,
- name=name)
+ def create_backup(self, server_id, **kwargs):
+ """Backup a server instance.
- def change_password(self, server_id, adminPass):
- """Changes the root password for the server."""
- return self.action(server_id, 'changePassword',
- adminPass=adminPass)
+ Available params: see http://developer.openstack.org/
+ api-ref-compute-v2.1.html#createBackup
+ """
+ return self.action(server_id, "createBackup", **kwargs)
- def get_password(self, server_id):
+ def change_password(self, server_id, **kwargs):
+ """Change the root password for the server.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-compute-v2.1.html#changePassword
+ """
+ return self.action(server_id, 'changePassword', **kwargs)
+
+ def show_password(self, server_id):
resp, body = self.get("servers/%s/os-server-password" %
server_id)
body = json.loads(body)
- self.validate_response(schema.get_password, resp, body)
+ self.validate_response(schema.show_password, resp, body)
return service_client.ResponseBody(resp, body)
def delete_password(self, server_id):
@@ -171,12 +187,19 @@
resp, body)
return service_client.ResponseBody(resp, body)
- def reboot_server(self, server_id, reboot_type):
- """Reboots a server."""
- return self.action(server_id, 'reboot', type=reboot_type)
+ def reboot_server(self, server_id, **kwargs):
+ """Reboot a server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#reboot
+ """
+ return self.action(server_id, 'reboot', **kwargs)
def rebuild_server(self, server_id, image_ref, **kwargs):
- """Rebuilds a server with a new image.
+ """Rebuild a server with a new image.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#rebuild
Most parameters except the following are passed to the API without
any changes.
@@ -193,7 +216,10 @@
rebuild_schema, **kwargs)
def resize_server(self, server_id, flavor_ref, **kwargs):
- """Changes the flavor of a server.
+ """Change the flavor of a server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#resize
Most parameters except the following are passed to the API without
any changes.
@@ -205,13 +231,21 @@
return self.action(server_id, 'resize', **kwargs)
def confirm_resize_server(self, server_id, **kwargs):
- """Confirms the flavor change for a server."""
+ """Confirm the flavor change for a server.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-compute-v2.1.html#confirmResize
+ """
return self.action(server_id, 'confirmResize',
schema.server_actions_confirm_resize,
**kwargs)
def revert_resize_server(self, server_id, **kwargs):
- """Reverts a server back to its original flavor."""
+ """Revert a server back to its original flavor.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-compute-v2.1.html#revertResize
+ """
return self.action(server_id, 'revertResize', **kwargs)
def list_server_metadata(self, server_id):
@@ -240,10 +274,10 @@
resp, body)
return service_client.ResponseBody(resp, body)
- def get_server_metadata_item(self, server_id, key):
+ def show_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,
+ self.validate_response(schema.set_show_server_metadata_item,
resp, body)
return service_client.ResponseBody(resp, body)
@@ -252,7 +286,7 @@
resp, body = self.put('servers/%s/metadata/%s' % (server_id, key),
post_body)
body = json.loads(body)
- self.validate_response(schema.set_get_server_metadata_item,
+ self.validate_response(schema.set_show_server_metadata_item,
resp, body)
return service_client.ResponseBody(resp, body)
@@ -278,19 +312,19 @@
self.validate_response(schema.attach_volume, resp, body)
return service_client.ResponseBody(resp, body)
- def detach_volume(self, server_id, volume_id):
+ def detach_volume(self, server_id, volume_id): # noqa
"""Detaches a volume from a server instance."""
resp, body = self.delete('servers/%s/os-volume_attachments/%s' %
(server_id, volume_id))
self.validate_response(schema.detach_volume, resp, body)
return service_client.ResponseBody(resp, body)
- def get_volume_attachment(self, server_id, attach_id):
+ def show_volume_attachment(self, server_id, attach_id):
"""Return details about the given volume attachment."""
resp, body = self.get('servers/%s/os-volume_attachments/%s' % (
server_id, attach_id))
body = json.loads(body)
- self.validate_response(schema.get_volume_attachment, resp, body)
+ self.validate_response(schema.show_volume_attachment, resp, body)
return service_client.ResponseBody(resp, body)
def list_volume_attachments(self, server_id):
@@ -301,73 +335,132 @@
self.validate_response(schema.list_volume_attachments, resp, body)
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', name=name)
+ def add_security_group(self, server_id, **kwargs):
+ """Add a security group to the server.
- def remove_security_group(self, server_id, name):
- """Removes a security group from the server."""
- return self.action(server_id, 'removeSecurityGroup', name=name)
+ Available params: TODO
+ """
+ # TODO(oomichi): The api-site doesn't contain this API description.
+ # So the above should be changed to the api-site link after
+ # adding the description on the api-site.
+ # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1524199
+ return self.action(server_id, 'addSecurityGroup', **kwargs)
+
+ def remove_security_group(self, server_id, **kwargs):
+ """Remove a security group from the server.
+
+ Available params: TODO
+ """
+ # TODO(oomichi): The api-site doesn't contain this API description.
+ # So the above should be changed to the api-site link after
+ # adding the description on the api-site.
+ # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1524199
+ return self.action(server_id, 'removeSecurityGroup', **kwargs)
def live_migrate_server(self, server_id, **kwargs):
- """This should be called with administrator privileges ."""
+ """This should be called with administrator privileges.
- req_body = json.dumps({'os-migrateLive': kwargs})
-
- resp, body = self.post("servers/%s/action" % server_id, req_body)
- self.validate_response(schema.server_actions_common_schema,
- resp, body)
- return service_client.ResponseBody(resp, body)
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#migrateLive
+ """
+ return self.action(server_id, 'os-migrateLive', **kwargs)
def migrate_server(self, server_id, **kwargs):
- """Migrates a server to a new host."""
+ """Migrate a server to a new host.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#migrate
+ """
return self.action(server_id, 'migrate', **kwargs)
def lock_server(self, server_id, **kwargs):
- """Locks the given server."""
+ """Lock the given server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#lock
+ """
return self.action(server_id, 'lock', **kwargs)
def unlock_server(self, server_id, **kwargs):
- """UNlocks the given server."""
+ """UNlock the given server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#unlock
+ """
return self.action(server_id, 'unlock', **kwargs)
def suspend_server(self, server_id, **kwargs):
- """Suspends the provided server."""
+ """Suspend the provided server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#suspend
+ """
return self.action(server_id, 'suspend', **kwargs)
def resume_server(self, server_id, **kwargs):
- """Un-suspends the provided server."""
+ """Un-suspend the provided server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#resume
+ """
return self.action(server_id, 'resume', **kwargs)
def pause_server(self, server_id, **kwargs):
- """Pauses the provided server."""
+ """Pause the provided server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#pause
+ """
return self.action(server_id, 'pause', **kwargs)
def unpause_server(self, server_id, **kwargs):
- """Un-pauses the provided server."""
+ """Un-pause the provided server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#unpause
+ """
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', state=state)
+ def reset_state(self, server_id, **kwargs):
+ """Reset the state of a server to active/error.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#resetState
+ """
+ return self.action(server_id, 'os-resetState', **kwargs)
def shelve_server(self, server_id, **kwargs):
- """Shelves the provided server."""
+ """Shelve the provided server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#shelve
+ """
return self.action(server_id, 'shelve', **kwargs)
def unshelve_server(self, server_id, **kwargs):
- """Un-shelves the provided server."""
+ """Un-shelve the provided server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#unshelve
+ """
return self.action(server_id, 'unshelve', **kwargs)
def shelve_offload_server(self, server_id, **kwargs):
- """Shelve-offload the provided server."""
+ """Shelve-offload the provided server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#shelveOffload
+ """
return self.action(server_id, 'shelveOffload', **kwargs)
- def get_console_output(self, server_id, length):
- kwargs = {'length': length} if length else {}
+ def get_console_output(self, server_id, **kwargs):
+ """Get console output.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#getConsoleOutput
+ """
return self.action(server_id, 'os-getConsoleOutput',
- schema.get_console_output,
- **kwargs)
+ schema.get_console_output, **kwargs)
def list_virtual_interfaces(self, server_id):
"""List the virtual interfaces used in an instance."""
@@ -378,16 +471,18 @@
return service_client.ResponseBody(resp, body)
def rescue_server(self, server_id, **kwargs):
- """Rescue the provided server."""
- return self.action(server_id, 'rescue',
- schema.rescue_server,
- **kwargs)
+ """Rescue the provided server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#rescue
+ """
+ return self.action(server_id, 'rescue', schema.rescue_server, **kwargs)
def unrescue_server(self, server_id):
"""Unrescue the provided server."""
return self.action(server_id, 'unrescue')
- def get_server_diagnostics(self, server_id):
+ def show_server_diagnostics(self, server_id):
"""Get the usage data for a server."""
resp, body = self.get("servers/%s/diagnostics" % server_id)
return service_client.ResponseBody(resp, json.loads(body))
@@ -400,40 +495,67 @@
self.validate_response(schema.list_instance_actions, resp, body)
return service_client.ResponseBody(resp, body)
- def get_instance_action(self, server_id, request_id):
+ def show_instance_action(self, server_id, request_id):
"""Returns the action details of the provided server."""
resp, body = self.get("servers/%s/os-instance-actions/%s" %
(server_id, request_id))
body = json.loads(body)
- self.validate_response(schema.get_instance_action, resp, body)
+ self.validate_response(schema.show_instance_action, resp, body)
return service_client.ResponseBody(resp, body)
def force_delete_server(self, server_id, **kwargs):
- """Force delete a server."""
+ """Force delete a server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#forceDelete
+ """
return self.action(server_id, 'forceDelete', **kwargs)
def restore_soft_deleted_server(self, server_id, **kwargs):
- """Restore a soft-deleted server."""
+ """Restore a soft-deleted server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#restore
+ """
return self.action(server_id, 'restore', **kwargs)
def reset_network(self, server_id, **kwargs):
- """Resets the Network of a server"""
+ """Reset the Network of a server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#resetNetwork
+ """
return self.action(server_id, 'resetNetwork', **kwargs)
def inject_network_info(self, server_id, **kwargs):
- """Inject the Network Info into server"""
+ """Inject the Network Info into server.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#injectNetworkInfo
+ """
return self.action(server_id, 'injectNetworkInfo', **kwargs)
- def get_vnc_console(self, server_id, console_type):
- """Get URL of VNC console."""
+ def get_vnc_console(self, server_id, **kwargs):
+ """Get URL of VNC console.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#getVNCConsole
+ """
return self.action(server_id, "os-getVNCConsole",
- schema.get_vnc_console,
- type=console_type)
+ schema.get_vnc_console, **kwargs)
def add_fixed_ip(self, server_id, **kwargs):
- """Add a fixed IP to input server instance."""
+ """Add a fixed IP to server instance.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#addFixedIp
+ """
return self.action(server_id, 'addFixedIp', **kwargs)
def remove_fixed_ip(self, server_id, **kwargs):
- """Remove input fixed IP from input server instance."""
+ """Remove input fixed IP from input server instance.
+
+ Available params: http://developer.openstack.org/
+ api-ref-compute-v2.1.html#removeFixedIp
+ """
return self.action(server_id, 'removeFixedIp', **kwargs)
diff --git a/tempest/services/compute/json/services_client.py b/tempest/services/compute/json/services_client.py
deleted file mode 100644
index 57d0434..0000000
--- a/tempest/services/compute/json/services_client.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright 2013 NEC Corporation
-# Copyright 2013 IBM Corp.
-# 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.api_schema.response.compute.v2_1 import services as schema
-from tempest.common import service_client
-
-
-class ServicesClient(service_client.ServiceClient):
-
- def list_services(self, **params):
- url = 'os-services'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_services, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def enable_service(self, **kwargs):
- """Enable service on a host
-
- host_name: Name of host
- binary: Service binary
- """
- post_body = json.dumps(kwargs)
- resp, body = self.put('os-services/enable', post_body)
- body = json.loads(body)
- self.validate_response(schema.enable_disable_service, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def disable_service(self, **kwargs):
- """Disable service on a host
-
- host_name: Name of host
- binary: Service binary
- """
- post_body = json.dumps(kwargs)
- resp, body = self.put('os-services/disable', post_body)
- body = json.loads(body)
- self.validate_response(schema.enable_disable_service, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/snapshots_client.py b/tempest/services/compute/json/snapshots_client.py
deleted file mode 100644
index e3f92db..0000000
--- a/tempest/services/compute/json/snapshots_client.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# 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 SnapshotsClient(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/tenant_networks_client.py b/tempest/services/compute/json/tenant_networks_client.py
deleted file mode 100644
index 33166c0..0000000
--- a/tempest/services/compute/json/tenant_networks_client.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# 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 oslo_serialization import jsonutils as json
-
-from tempest.api_schema.response.compute.v2_1 import tenant_networks as schema
-from tempest.common import service_client
-
-
-class TenantNetworksClient(service_client.ServiceClient):
-
- def list_tenant_networks(self):
- resp, body = self.get("os-tenant-networks")
- body = json.loads(body)
- self.validate_response(schema.list_tenant_networks, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_tenant_network(self, network_id):
- resp, body = self.get("os-tenant-networks/%s" % network_id)
- body = json.loads(body)
- self.validate_response(schema.get_tenant_network, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/tenant_usages_client.py b/tempest/services/compute/json/tenant_usages_client.py
deleted file mode 100644
index 73b4706..0000000
--- a/tempest/services/compute/json/tenant_usages_client.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright 2013 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 oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
-
-from tempest.api_schema.response.compute.v2_1 import tenant_usages as schema
-from tempest.common import service_client
-
-
-class TenantUsagesClient(service_client.ServiceClient):
-
- def list_tenant_usages(self, **params):
- url = 'os-simple-tenant-usage'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_tenant_usage, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_tenant_usage(self, tenant_id, **params):
- url = 'os-simple-tenant-usage/%s' % tenant_id
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.get_tenant_usage, resp, body)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/versions_client.py b/tempest/services/compute/json/versions_client.py
deleted file mode 100644
index 48c0e8d..0000000
--- a/tempest/services/compute/json/versions_client.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
-#
-# 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 import urllib
-
-from tempest.api_schema.response.compute.v2_1 import versions as schema
-from tempest.common import service_client
-
-
-class VersionsClient(service_client.ServiceClient):
-
- 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
- # versions. For that, here should use raw_request() instead of
- # get().
- endpoint = self.base_url
- url = urllib.parse.urlparse(endpoint)
- 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_client.py b/tempest/services/compute/json/volumes_client.py
deleted file mode 100644
index 69d982e..0000000
--- a/tempest/services/compute/json/volumes_client.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 2012 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 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 volumes as schema
-from tempest.common import service_client
-
-
-class VolumesClient(service_client.ServiceClient):
-
- def list_volumes(self, detail=False, **params):
- """List all the volumes created."""
- url = 'os-volumes'
-
- 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_volumes, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def show_volume(self, volume_id):
- """Returns the details of a single volume."""
- url = "os-volumes/%s" % volume_id
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.create_get_volume, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def create_volume(self, **kwargs):
- """Creates a new Volume.
-
- size(Required): Size of volume in GB.
- Following optional keyword arguments are accepted:
- display_name: Optional Volume Name.
- metadata: A dictionary of values to be used as metadata.
- """
- post_body = json.dumps({'volume': kwargs})
- 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)
-
- def delete_volume(self, volume_id):
- """Deletes the Specified Volume."""
- resp, body = self.delete("os-volumes/%s" % volume_id)
- self.validate_response(schema.delete_volume, resp, body)
- return service_client.ResponseBody(resp, body)
-
- def is_resource_deleted(self, id):
- try:
- self.show_volume(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 'volume'
diff --git a/tempest/services/database/json/flavors_client.py b/tempest/services/database/json/flavors_client.py
index 88feb17..34a91ba 100644
--- a/tempest/services/database/json/flavors_client.py
+++ b/tempest/services/database/json/flavors_client.py
@@ -31,8 +31,8 @@
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))
+ def show_db_flavor(self, db_flavor_id):
+ resp, body = self.get("flavors/%s" % db_flavor_id)
self.expected_success(200, resp.status)
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 b27f036..f80e22d 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -11,7 +11,6 @@
# under the License.
from oslo_serialization import jsonutils as json
-from tempest_lib import exceptions as lib_exc
from tempest.common import service_client
@@ -45,24 +44,6 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def create_tenant(self, name, **kwargs):
- """Create a tenant
-
- name (required): New tenant name
- description: Description of new tenant (default is none)
- enabled <true|false>: Initial tenant status (default is true)
- """
- post_body = {
- 'name': name,
- 'description': kwargs.get('description', ''),
- 'enabled': kwargs.get('enabled', True),
- }
- post_body = json.dumps({'tenant': post_body})
- resp, body = self.post('tenants', post_body)
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
def delete_role(self, role_id):
"""Delete a role."""
resp, body = self.delete('OS-KSADM/roles/%s' % str(role_id))
@@ -85,26 +66,13 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def remove_user_role(self, tenant_id, user_id, role_id):
+ def delete_user_role(self, tenant_id, user_id, role_id):
"""Removes a role assignment for a user on a tenant."""
resp, body = self.delete('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
(tenant_id, user_id, role_id))
self.expected_success(204, resp.status)
return service_client.ResponseBody(resp, body)
- def delete_tenant(self, tenant_id):
- """Delete a tenant."""
- resp, body = self.delete('tenants/%s' % str(tenant_id))
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def show_tenant(self, tenant_id):
- """Get tenant details."""
- resp, body = self.get('tenants/%s' % str(tenant_id))
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
def list_roles(self):
"""Returns roles."""
resp, body = self.get('OS-KSADM/roles')
@@ -112,38 +80,6 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def list_tenants(self):
- """Returns tenants."""
- resp, body = self.get('tenants')
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def get_tenant_by_name(self, tenant_name):
- tenants = self.list_tenants()['tenants']
- for tenant in tenants:
- if tenant['name'] == tenant_name:
- return tenant
- raise lib_exc.NotFound('No such tenant')
-
- def update_tenant(self, tenant_id, **kwargs):
- """Updates a tenant."""
- body = self.show_tenant(tenant_id)['tenant']
- name = kwargs.get('name', body['name'])
- desc = kwargs.get('description', body['description'])
- en = kwargs.get('enabled', body['enabled'])
- post_body = {
- 'id': tenant_id,
- 'name': name,
- 'description': desc,
- 'enabled': en,
- }
- post_body = json.dumps({'tenant': post_body})
- resp, body = self.post('tenants/%s' % tenant_id, post_body)
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
def create_user(self, name, password, tenant_id, email, **kwargs):
"""Create a user."""
post_body = {
@@ -213,20 +149,6 @@
self.expected_success(204, resp.status)
return service_client.ResponseBody(resp, body)
- def list_tenant_users(self, tenant_id):
- """List users for a Tenant."""
- resp, body = self.get('/tenants/%s/users' % tenant_id)
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def get_user_by_username(self, tenant_id, username):
- users = self.list_tenant_users(tenant_id)['users']
- for user in users:
- if user['name'] == username:
- return user
- raise lib_exc.NotFound('No such user')
-
def create_service(self, name, type, **kwargs):
"""Create a service."""
post_body = {
@@ -322,8 +244,11 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def create_user_ec2_credentials(self, user_id, tenant_id):
- post_body = json.dumps({'tenant_id': tenant_id})
+ def create_user_ec2_credentials(self, user_id, **kwargs):
+ # TODO(piyush): Current api-site doesn't contain this API description.
+ # After fixing the api-site, we need to fix here also for putting the
+ # link to api-site.
+ post_body = json.dumps(kwargs)
resp, body = self.post('/users/%s/credentials/OS-EC2' % user_id,
post_body)
self.expected_success(200, resp.status)
diff --git a/tempest/services/identity/v2/json/tenants_client.py b/tempest/services/identity/v2/json/tenants_client.py
new file mode 100644
index 0000000..937ae6f
--- /dev/null
+++ b/tempest/services/identity/v2/json/tenants_client.py
@@ -0,0 +1,84 @@
+# Copyright 2015 Red Hat, Inc.
+#
+# 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 tempest.common import service_client
+
+
+class TenantsClient(service_client.ServiceClient):
+ api_version = "v2.0"
+
+ def create_tenant(self, name, **kwargs):
+ """Create a tenant
+
+ name (required): New tenant name
+ description: Description of new tenant (default is none)
+ enabled <true|false>: Initial tenant status (default is true)
+ """
+ post_body = {
+ 'name': name,
+ 'description': kwargs.get('description', ''),
+ 'enabled': kwargs.get('enabled', True),
+ }
+ post_body = json.dumps({'tenant': post_body})
+ resp, body = self.post('tenants', post_body)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def delete_tenant(self, tenant_id):
+ """Delete a tenant."""
+ resp, body = self.delete('tenants/%s' % str(tenant_id))
+ self.expected_success(204, resp.status)
+ return service_client.ResponseBody(resp, body)
+
+ def show_tenant(self, tenant_id):
+ """Get tenant details."""
+ resp, body = self.get('tenants/%s' % str(tenant_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def list_tenants(self):
+ """Returns tenants."""
+ resp, body = self.get('tenants')
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def update_tenant(self, tenant_id, **kwargs):
+ """Updates a tenant."""
+ body = self.show_tenant(tenant_id)['tenant']
+ name = kwargs.get('name', body['name'])
+ desc = kwargs.get('description', body['description'])
+ en = kwargs.get('enabled', body['enabled'])
+ post_body = {
+ 'id': tenant_id,
+ 'name': name,
+ 'description': desc,
+ 'enabled': en,
+ }
+ post_body = json.dumps({'tenant': post_body})
+ resp, body = self.post('tenants/%s' % tenant_id, post_body)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def list_tenant_users(self, tenant_id):
+ """List users for a Tenant."""
+ resp, body = self.get('/tenants/%s/users' % tenant_id)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/credentials_client.py b/tempest/services/identity/v3/json/credentials_client.py
index 7d4cf9a..753e960 100644
--- a/tempest/services/identity/v3/json/credentials_client.py
+++ b/tempest/services/identity/v3/json/credentials_client.py
@@ -51,7 +51,7 @@
body['credential']['blob'] = json.loads(body['credential']['blob'])
return service_client.ResponseBody(resp, body)
- def get_credential(self, credential_id):
+ def show_credential(self, credential_id):
"""To GET Details of a credential."""
resp, body = self.get('credentials/%s' % credential_id)
self.expected_success(200, resp.status)
diff --git a/tempest/services/identity/v3/json/groups_client.py b/tempest/services/identity/v3/json/groups_client.py
new file mode 100644
index 0000000..70edd23
--- /dev/null
+++ b/tempest/services/identity/v3/json/groups_client.py
@@ -0,0 +1,90 @@
+# Copyright 2013 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.
+
+"""
+http://developer.openstack.org/api-ref-identity-v3.html#groups-v3
+"""
+
+from oslo_serialization import jsonutils as json
+
+from tempest.common import service_client
+
+
+class GroupsClient(service_client.ServiceClient):
+ api_version = "v3"
+
+ def create_group(self, **kwargs):
+ """Creates a group.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-identity-v3.html#createGroup
+ """
+ post_body = json.dumps({'group': kwargs})
+ resp, body = self.post('groups', post_body)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def show_group(self, group_id):
+ """Get group details."""
+ resp, body = self.get('groups/%s' % group_id)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def list_groups(self):
+ """Lists the groups."""
+ resp, body = self.get('groups')
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def update_group(self, group_id, **kwargs):
+ """Updates a group.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-identity-v3.html#updateGroup
+ """
+ post_body = json.dumps({'group': kwargs})
+ resp, body = self.patch('groups/%s' % group_id, post_body)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def delete_group(self, group_id):
+ """Delete a group."""
+ resp, body = self.delete('groups/%s' % str(group_id))
+ self.expected_success(204, resp.status)
+ return service_client.ResponseBody(resp, body)
+
+ def add_group_user(self, group_id, user_id):
+ """Add user into group."""
+ resp, body = self.put('groups/%s/users/%s' % (group_id, user_id),
+ None)
+ self.expected_success(204, resp.status)
+ return service_client.ResponseBody(resp, body)
+
+ def list_group_users(self, group_id):
+ """List users in group."""
+ resp, body = self.get('groups/%s/users' % group_id)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBody(resp, body)
+
+ def delete_group_user(self, group_id, user_id):
+ """Delete user in group."""
+ resp, body = self.delete('groups/%s/users/%s' % (group_id, user_id))
+ self.expected_success(204, resp.status)
+ return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index f7913d0..972db99 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -81,13 +81,13 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def update_user_password(self, user_id, password, original_password):
- """Updates a user password."""
- update_user = {
- 'password': password,
- 'original_password': original_password
- }
- update_user = json.dumps({'user': update_user})
+ def update_user_password(self, user_id, **kwargs):
+ """Update a user password
+
+ Available params: see http://developer.openstack.org/
+ api-ref-identity-v3.html#changeUserPassword
+ """
+ update_user = json.dumps({'user': kwargs})
resp, _ = self.post('users/%s/password' % user_id, update_user)
self.expected_success(204, resp.status)
return service_client.ResponseBody(resp)
@@ -299,72 +299,6 @@
self.expected_success(204, resp.status)
return service_client.ResponseBody(resp, body)
- def create_group(self, name, **kwargs):
- """Creates a group."""
- description = kwargs.get('description', None)
- domain_id = kwargs.get('domain_id', 'default')
- project_id = kwargs.get('project_id', None)
- post_body = {
- 'description': description,
- 'domain_id': domain_id,
- 'project_id': project_id,
- 'name': name
- }
- post_body = json.dumps({'group': post_body})
- resp, body = self.post('groups', post_body)
- self.expected_success(201, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def get_group(self, group_id):
- """Get group details."""
- resp, body = self.get('groups/%s' % group_id)
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def list_groups(self):
- """Lists the groups."""
- resp, body = self.get('groups')
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def update_group(self, group_id, **kwargs):
- """Updates a group."""
- body = self.get_group(group_id)['group']
- name = kwargs.get('name', body['name'])
- description = kwargs.get('description', body['description'])
- post_body = {
- 'name': name,
- 'description': description
- }
- post_body = json.dumps({'group': post_body})
- resp, body = self.patch('groups/%s' % group_id, post_body)
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def delete_group(self, group_id):
- """Delete a group."""
- resp, body = self.delete('groups/%s' % str(group_id))
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def add_group_user(self, group_id, user_id):
- """Add user into group."""
- resp, body = self.put('groups/%s/users/%s' % (group_id, user_id),
- None)
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def list_group_users(self, group_id):
- """List users in group."""
- resp, body = self.get('groups/%s/users' % group_id)
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
def list_user_groups(self, user_id):
"""Lists groups which a user belongs to."""
resp, body = self.get('users/%s/groups' % user_id)
@@ -372,12 +306,6 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def delete_group_user(self, group_id, user_id):
- """Delete user in group."""
- resp, body = self.delete('groups/%s/users/%s' % (group_id, user_id))
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
def assign_user_role_on_project(self, project_id, user_id, role_id):
"""Add roles to a user on a project."""
resp, body = self.put('projects/%s/users/%s/roles/%s' %
@@ -408,14 +336,14 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def revoke_role_from_user_on_project(self, project_id, user_id, role_id):
+ def delete_role_from_user_on_project(self, project_id, user_id, role_id):
"""Delete role of a user on a project."""
resp, body = self.delete('projects/%s/users/%s/roles/%s' %
(project_id, user_id, role_id))
self.expected_success(204, resp.status)
return service_client.ResponseBody(resp, body)
- def revoke_role_from_user_on_domain(self, domain_id, user_id, role_id):
+ def delete_role_from_user_on_domain(self, domain_id, user_id, role_id):
"""Delete role of a user on a domain."""
resp, body = self.delete('domains/%s/users/%s/roles/%s' %
(domain_id, user_id, role_id))
@@ -452,33 +380,27 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def revoke_role_from_group_on_project(self, project_id, group_id, role_id):
+ def delete_role_from_group_on_project(self, project_id, group_id, role_id):
"""Delete role of a user on a project."""
resp, body = self.delete('projects/%s/groups/%s/roles/%s' %
(project_id, group_id, role_id))
self.expected_success(204, resp.status)
return service_client.ResponseBody(resp, body)
- def revoke_role_from_group_on_domain(self, domain_id, group_id, role_id):
+ def delete_role_from_group_on_domain(self, domain_id, group_id, role_id):
"""Delete role of a user on a domain."""
resp, body = self.delete('domains/%s/groups/%s/roles/%s' %
(domain_id, group_id, role_id))
self.expected_success(204, resp.status)
return service_client.ResponseBody(resp, body)
- def create_trust(self, trustor_user_id, trustee_user_id, project_id,
- role_names, impersonation, expires_at):
- """Creates a trust."""
- roles = [{'name': n} for n in role_names]
- post_body = {
- 'trustor_user_id': trustor_user_id,
- 'trustee_user_id': trustee_user_id,
- 'project_id': project_id,
- 'impersonation': impersonation,
- 'roles': roles,
- 'expires_at': expires_at
- }
- post_body = json.dumps({'trust': post_body})
+ def create_trust(self, **kwargs):
+ """Creates a trust.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-identity-v3-ext.html#createTrust
+ """
+ post_body = json.dumps({'trust': kwargs})
resp, body = self.post('OS-TRUST/trusts', post_body)
self.expected_success(201, resp.status)
body = json.loads(body)
diff --git a/tempest/services/identity/v3/json/policy_client.py b/tempest/services/identity/v3/json/policy_client.py
index ecc9df7..7927ed5 100644
--- a/tempest/services/identity/v3/json/policy_client.py
+++ b/tempest/services/identity/v3/json/policy_client.py
@@ -44,7 +44,7 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def get_policy(self, policy_id):
+ def show_policy(self, policy_id):
"""Lists out the given policy."""
url = 'policies/%s' % policy_id
resp, body = self.get(url)
diff --git a/tempest/services/identity/v3/json/region_client.py b/tempest/services/identity/v3/json/region_client.py
index 6ccdc31..3595391 100644
--- a/tempest/services/identity/v3/json/region_client.py
+++ b/tempest/services/identity/v3/json/region_client.py
@@ -59,7 +59,7 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def get_region(self, region_id):
+ def show_region(self, region_id):
"""Get region."""
url = 'regions/%s' % region_id
resp, body = self.get(url)
diff --git a/tempest/services/image/v1/json/image_client.py b/tempest/services/image/v1/json/images_client.py
similarity index 96%
rename from tempest/services/image/v1/json/image_client.py
rename to tempest/services/image/v1/json/images_client.py
index d97da36..3406db8 100644
--- a/tempest/services/image/v1/json/image_client.py
+++ b/tempest/services/image/v1/json/images_client.py
@@ -32,13 +32,13 @@
LOG = logging.getLogger(__name__)
-class ImageClient(service_client.ServiceClient):
+class ImagesClient(service_client.ServiceClient):
def __init__(self, auth_provider, catalog_type, region, endpoint_type=None,
build_interval=None, build_timeout=None,
disable_ssl_certificate_validation=None,
ca_certs=None, trace_requests=None):
- super(ImageClient, self).__init__(
+ super(ImagesClient, self).__init__(
auth_provider,
catalog_type,
region,
@@ -265,11 +265,14 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def add_member(self, member_id, image_id, can_share=False):
+ def add_member(self, member_id, image_id, **kwargs):
+ """Add a member to an image.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-image-v1.html#addMember-v1
+ """
url = 'v1/images/%s/members/%s' % (image_id, member_id)
- body = None
- if can_share:
- body = json.dumps({'member': {'can_share': True}})
+ body = json.dumps({'member': kwargs})
resp, __ = self.put(url, body)
self.expected_success(204, resp.status)
return service_client.ResponseBody(resp)
diff --git a/tempest/services/image/v2/json/image_client.py b/tempest/services/image/v2/json/images_client.py
similarity index 82%
rename from tempest/services/image/v2/json/image_client.py
rename to tempest/services/image/v2/json/images_client.py
index eea179d..44062ea 100644
--- a/tempest/services/image/v2/json/image_client.py
+++ b/tempest/services/image/v2/json/images_client.py
@@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import jsonschema
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
from tempest_lib import exceptions as lib_exc
@@ -22,13 +21,13 @@
from tempest.common import service_client
-class ImageClientV2(service_client.ServiceClient):
+class ImagesClientV2(service_client.ServiceClient):
def __init__(self, auth_provider, catalog_type, region, endpoint_type=None,
build_interval=None, build_timeout=None,
disable_ssl_certificate_validation=None, ca_certs=None,
trace_requests=None):
- super(ImageClientV2, self).__init__(
+ super(ImagesClientV2, self).__init__(
auth_provider,
catalog_type,
region,
@@ -49,14 +48,6 @@
insecure=self.dscv,
ca_certs=self.ca_certs)
- def _validate_schema(self, body, type='image'):
- if type in ['image', 'images']:
- schema = self.show_schema(type)
- else:
- raise ValueError("%s is not a valid schema type" % type)
-
- jsonschema.validate(body, schema)
-
@property
def http(self):
if self._http is None:
@@ -65,8 +56,6 @@
def update_image(self, image_id, patch):
data = json.dumps(patch)
- self._validate_schema(data)
-
headers = {"Content-Type": "application/openstack-images-v2.0"
"-json-patch"}
resp, body = self.patch('v2/images/%s' % image_id, data, headers)
@@ -89,8 +78,6 @@
params[option] = value
data = json.dumps(params)
- self._validate_schema(data)
-
resp, body = self.post('v2/images', data)
self.expected_success(201, resp.status)
body = json.loads(body)
@@ -123,7 +110,6 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- self._validate_schema(body, type='images')
return service_client.ResponseBody(resp, body)
def show_image(self, image_id):
@@ -153,7 +139,7 @@
self.expected_success(204, resp.status)
return service_client.ResponseBody(resp, body)
- def load_image_file(self, image_id):
+ def show_image_file(self, image_id):
url = 'v2/images/%s/file' % image_id
resp, body = self.get(url)
self.expected_success(200, resp.status)
@@ -178,17 +164,27 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def add_image_member(self, image_id, member_id):
+ def create_image_member(self, image_id, **kwargs):
+ """Create an image member.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-image-v2.html#createImageMember-v2
+ """
url = 'v2/images/%s/members' % image_id
- data = json.dumps({'member': member_id})
+ data = json.dumps(kwargs)
resp, body = self.post(url, data)
self.expected_success(200, resp.status)
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def update_image_member(self, image_id, member_id, body):
+ def update_image_member(self, image_id, member_id, **kwargs):
+ """Update an image member.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-image-v2.html#updateImageMember-v2
+ """
url = 'v2/images/%s/members/%s' % (image_id, member_id)
- data = json.dumps(body)
+ data = json.dumps(kwargs)
resp, body = self.put(url, data)
self.expected_success(200, resp.status)
body = json.loads(body)
@@ -200,7 +196,7 @@
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, json.loads(body))
- def remove_image_member(self, image_id, member_id):
+ def delete_image_member(self, image_id, member_id):
url = 'v2/images/%s/members/%s' % (image_id, member_id)
resp, _ = self.delete(url)
self.expected_success(204, resp.status)
@@ -220,54 +216,43 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def create_namespaces(self, namespace, **kwargs):
- params = {
- "namespace": namespace,
- }
+ def create_namespace(self, **kwargs):
+ """Create a namespace.
- for option in kwargs:
- value = kwargs.get(option)
- if isinstance(value, dict) or isinstance(value, tuple):
- params.update(value)
- else:
- params[option] = value
-
- data = json.dumps(params)
- self._validate_schema(data)
-
+ Available params: see http://developer.openstack.org/
+ api-ref-image-v2.html#createNamespace-v2
+ """
+ data = json.dumps(kwargs)
resp, body = self.post('/v2/metadefs/namespaces', data)
self.expected_success(201, resp.status)
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def show_namespaces(self, namespace):
+ def show_namespace(self, namespace):
url = '/v2/metadefs/namespaces/%s' % namespace
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def update_namespaces(self, namespace, visibility, **kwargs):
- params = {
- "namespace": namespace,
- "visibility": visibility
- }
- for option in kwargs:
- value = kwargs.get(option)
- if isinstance(value, dict) or isinstance(value, tuple):
- params.update(value)
- else:
- params[option] = value
+ def update_namespace(self, namespace, **kwargs):
+ """Update a namespace.
+ Available params: see http://developer.openstack.org/
+ api-ref-image-v2.html#updateNamespace-v2
+ """
+ # NOTE: On Glance API, we need to pass namespace on both URI
+ # and a request body.
+ params = {'namespace': namespace}
+ params.update(kwargs)
data = json.dumps(params)
- self._validate_schema(data)
url = '/v2/metadefs/namespaces/%s' % namespace
resp, body = self.put(url, body=data)
self.expected_success(200, resp.status)
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def delete_namespaces(self, namespace):
+ def delete_namespace(self, namespace):
url = '/v2/metadefs/namespaces/%s' % namespace
resp, _ = self.delete(url)
self.expected_success(204, resp.status)
diff --git a/tempest/services/messaging/json/messaging_client.py b/tempest/services/messaging/json/messaging_client.py
index 2f233a9..5a43841 100644
--- a/tempest/services/messaging/json/messaging_client.py
+++ b/tempest/services/messaging/json/messaging_client.py
@@ -170,7 +170,7 @@
self.expected_success(204, resp.status)
return resp, body
- def release_claim(self, claim_uri):
+ def delete_claim(self, claim_uri):
resp, body = self.delete(claim_uri)
self.expected_success(204, resp.status)
return resp, body
diff --git a/tempest/services/network/json/floating_ips_client.py b/tempest/services/network/json/floating_ips_client.py
new file mode 100644
index 0000000..5c490ed
--- /dev/null
+++ b/tempest/services/network/json/floating_ips_client.py
@@ -0,0 +1,38 @@
+# 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.network.json import base
+
+
+class FloatingIPsClient(base.BaseNetworkClient):
+
+ def create_floatingip(self, **kwargs):
+ uri = '/floatingips'
+ post_data = {'floatingip': kwargs}
+ 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)
+
+ def show_floatingip(self, floatingip_id, **fields):
+ uri = '/floatingips/%s' % floatingip_id
+ return self.show_resource(uri, **fields)
+
+ def delete_floatingip(self, floatingip_id):
+ uri = '/floatingips/%s' % floatingip_id
+ return self.delete_resource(uri)
+
+ def list_floatingips(self, **filters):
+ uri = '/floatingips'
+ return self.list_resources(uri, **filters)
diff --git a/tempest/services/network/json/metering_label_rules_client.py b/tempest/services/network/json/metering_label_rules_client.py
new file mode 100644
index 0000000..374a89c
--- /dev/null
+++ b/tempest/services/network/json/metering_label_rules_client.py
@@ -0,0 +1,33 @@
+# 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.network.json import base
+
+
+class MeteringLabelRulesClient(base.BaseNetworkClient):
+
+ 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)
+
+ 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)
+
+ 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)
+
+ def list_metering_label_rules(self, **filters):
+ uri = '/metering/metering-label-rules'
+ return self.list_resources(uri, **filters)
diff --git a/tempest/services/network/json/metering_labels_client.py b/tempest/services/network/json/metering_labels_client.py
new file mode 100644
index 0000000..2e5cdae
--- /dev/null
+++ b/tempest/services/network/json/metering_labels_client.py
@@ -0,0 +1,33 @@
+# 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.network.json import base
+
+
+class MeteringLabelsClient(base.BaseNetworkClient):
+
+ def create_metering_label(self, **kwargs):
+ uri = '/metering/metering-labels'
+ post_data = {'metering_label': kwargs}
+ 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)
+
+ def delete_metering_label(self, metering_label_id):
+ uri = '/metering/metering-labels/%s' % metering_label_id
+ return self.delete_resource(uri)
+
+ def list_metering_labels(self, **filters):
+ uri = '/metering/metering-labels'
+ return self.list_resources(uri, **filters)
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 50a5d5e..459891f 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -35,62 +35,6 @@
quotas
"""
- def create_floatingip(self, **kwargs):
- uri = '/floatingips'
- post_data = {'floatingip': kwargs}
- 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)
-
- def show_floatingip(self, floatingip_id, **fields):
- uri = '/floatingips/%s' % floatingip_id
- return self.show_resource(uri, **fields)
-
- def delete_floatingip(self, floatingip_id):
- uri = '/floatingips/%s' % floatingip_id
- return self.delete_resource(uri)
-
- def list_floatingips(self, **filters):
- uri = '/floatingips'
- 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)
-
- def show_metering_label(self, metering_label_id, **fields):
- uri = '/metering/metering-labels/%s' % metering_label_id
- 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)
-
- def list_metering_labels(self, **filters):
- uri = '/metering/metering-labels'
- 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)
-
- 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)
-
- 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)
-
- def list_metering_label_rules(self, **filters):
- uri = '/metering/metering-label-rules'
- return self.list_resources(uri, **filters)
-
def create_security_group(self, **kwargs):
uri = '/security-groups'
post_data = {'security_group': kwargs}
@@ -213,23 +157,6 @@
message = '(%s) %s' % (caller, message)
raise exceptions.TimeoutException(message)
- def update_quotas(self, tenant_id, **kwargs):
- put_body = {'quota': kwargs}
- uri = '/quotas/%s' % tenant_id
- return self.update_resource(uri, put_body)
-
- def reset_quotas(self, tenant_id):
- uri = '/quotas/%s' % tenant_id
- return self.delete_resource(uri)
-
- def show_quotas(self, tenant_id, **fields):
- uri = '/quotas/%s' % tenant_id
- return self.show_resource(uri, **fields)
-
- def list_quotas(self, **filters):
- uri = '/quotas'
- 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
@@ -339,10 +266,12 @@
uri = '/routers/%s/l3-agents' % router_id
return self.list_resources(uri)
- def add_router_to_l3_agent(self, agent_id, router_id):
+ def add_router_to_l3_agent(self, agent_id, **kwargs):
+ # TODO(piyush): Current api-site doesn't contain this API description.
+ # After fixing the api-site, we need to fix here also for putting the
+ # link to api-site.
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, kwargs)
def remove_router_from_l3_agent(self, agent_id, router_id):
uri = '/agents/%s/l3-routers/%s' % (agent_id, router_id)
diff --git a/tempest/services/network/json/quotas_client.py b/tempest/services/network/json/quotas_client.py
new file mode 100644
index 0000000..9b65a54
--- /dev/null
+++ b/tempest/services/network/json/quotas_client.py
@@ -0,0 +1,35 @@
+# 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.network.json import base
+
+
+class QuotasClient(base.BaseNetworkClient):
+
+ def update_quotas(self, tenant_id, **kwargs):
+ put_body = {'quota': kwargs}
+ uri = '/quotas/%s' % tenant_id
+ return self.update_resource(uri, put_body)
+
+ def reset_quotas(self, tenant_id):
+ uri = '/quotas/%s' % tenant_id
+ return self.delete_resource(uri)
+
+ def show_quotas(self, tenant_id, **fields):
+ uri = '/quotas/%s' % tenant_id
+ return self.show_resource(uri, **fields)
+
+ def list_quotas(self, **filters):
+ uri = '/quotas'
+ return self.list_resources(uri, **filters)
diff --git a/tempest/services/telemetry/json/alarming_client.py b/tempest/services/telemetry/json/alarming_client.py
new file mode 100644
index 0000000..ce14211
--- /dev/null
+++ b/tempest/services/telemetry/json/alarming_client.py
@@ -0,0 +1,98 @@
+# Copyright 2014 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 oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+
+from tempest.common import service_client
+
+
+class AlarmingClient(service_client.ServiceClient):
+
+ version = '2'
+ uri_prefix = "v2"
+
+ def deserialize(self, body):
+ return json.loads(body.replace("\n", ""))
+
+ def serialize(self, body):
+ return json.dumps(body)
+
+ def list_alarms(self, query=None):
+ uri = '%s/alarms' % self.uri_prefix
+ uri_dict = {}
+ if query:
+ uri_dict = {'q.field': query[0],
+ 'q.op': query[1],
+ 'q.value': query[2]}
+ if uri_dict:
+ uri += "?%s" % urllib.urlencode(uri_dict)
+ resp, body = self.get(uri)
+ self.expected_success(200, resp.status)
+ body = self.deserialize(body)
+ return service_client.ResponseBodyList(resp, body)
+
+ def show_alarm(self, alarm_id):
+ uri = '%s/alarms/%s' % (self.uri_prefix, alarm_id)
+ resp, body = self.get(uri)
+ self.expected_success(200, resp.status)
+ body = self.deserialize(body)
+ return service_client.ResponseBody(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)
+
+ def delete_alarm(self, alarm_id):
+ uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
+ resp, body = self.delete(uri)
+ self.expected_success(204, resp.status)
+ if body:
+ body = self.deserialize(body)
+ return service_client.ResponseBody(resp, body)
+
+ def create_alarm(self, **kwargs):
+ uri = "%s/alarms" % self.uri_prefix
+ body = self.serialize(kwargs)
+ resp, body = self.post(uri, body)
+ self.expected_success(201, resp.status)
+ body = self.deserialize(body)
+ return service_client.ResponseBody(resp, body)
+
+ def update_alarm(self, alarm_id, **kwargs):
+ uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
+ body = self.serialize(kwargs)
+ resp, body = self.put(uri, body)
+ self.expected_success(200, resp.status)
+ body = self.deserialize(body)
+ return service_client.ResponseBody(resp, body)
+
+ def show_alarm_state(self, alarm_id):
+ uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
+ resp, body = self.get(uri)
+ self.expected_success(200, resp.status)
+ body = self.deserialize(body)
+ return service_client.ResponseBodyData(resp, body)
+
+ def alarm_set_state(self, alarm_id, state):
+ uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
+ body = self.serialize(state)
+ resp, body = self.put(uri, body)
+ self.expected_success(200, resp.status)
+ body = self.deserialize(body)
+ return service_client.ResponseBodyData(resp, body)
diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py
index fc8951e..abdeba2 100644
--- a/tempest/services/telemetry/json/telemetry_client.py
+++ b/tempest/services/telemetry/json/telemetry_client.py
@@ -30,17 +30,6 @@
def serialize(self, body):
return json.dumps(body)
- def add_sample(self, sample_list, meter_name, meter_unit, volume,
- sample_type, resource_id, **kwargs):
- sample = {"counter_name": meter_name, "counter_unit": meter_unit,
- "counter_volume": volume, "counter_type": sample_type,
- "resource_id": resource_id}
- for key in kwargs:
- sample[key] = kwargs[key]
-
- sample_list.append(self.serialize(sample))
- return sample_list
-
def create_sample(self, meter_name, sample_list):
uri = "%s/meters/%s" % (self.uri_prefix, meter_name)
body = self.serialize(sample_list)
@@ -72,10 +61,6 @@
uri = '%s/meters' % self.uri_prefix
return self._helper_list(uri, query)
- def list_alarms(self, query=None):
- uri = '%s/alarms' % self.uri_prefix
- return self._helper_list(uri, query)
-
def list_statistics(self, meter, period=None, query=None):
uri = "%s/meters/%s/statistics" % (self.uri_prefix, meter)
return self._helper_list(uri, query, period)
@@ -94,56 +79,3 @@
self.expected_success(200, resp.status)
body = self.deserialize(body)
return service_client.ResponseBody(resp, body)
-
- def show_alarm(self, alarm_id):
- uri = '%s/alarms/%s' % (self.uri_prefix, alarm_id)
- resp, body = self.get(uri)
- self.expected_success(200, resp.status)
- body = self.deserialize(body)
- return service_client.ResponseBody(resp, body)
-
- def delete_alarm(self, alarm_id):
- uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
- resp, body = self.delete(uri)
- self.expected_success(204, resp.status)
- if body:
- body = self.deserialize(body)
- return service_client.ResponseBody(resp, body)
-
- def create_alarm(self, **kwargs):
- uri = "%s/alarms" % self.uri_prefix
- body = self.serialize(kwargs)
- resp, body = self.post(uri, body)
- self.expected_success(201, resp.status)
- body = self.deserialize(body)
- return service_client.ResponseBody(resp, body)
-
- def update_alarm(self, alarm_id, **kwargs):
- uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
- body = self.serialize(kwargs)
- resp, body = self.put(uri, body)
- self.expected_success(200, resp.status)
- body = self.deserialize(body)
- return service_client.ResponseBody(resp, body)
-
- def show_alarm_state(self, alarm_id):
- uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
- resp, body = self.get(uri)
- self.expected_success(200, resp.status)
- body = self.deserialize(body)
- return service_client.ResponseBodyData(resp, body)
-
- def alarm_set_state(self, alarm_id, state):
- uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
- body = self.serialize(state)
- resp, body = self.put(uri, body)
- 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/services/volume/json/__init__.py b/tempest/services/volume/base/__init__.py
similarity index 100%
copy from tempest/services/volume/json/__init__.py
copy to tempest/services/volume/base/__init__.py
diff --git a/tempest/services/volume/json/admin/__init__.py b/tempest/services/volume/base/admin/__init__.py
similarity index 100%
copy from tempest/services/volume/json/admin/__init__.py
copy to tempest/services/volume/base/admin/__init__.py
diff --git a/tempest/services/volume/json/admin/volume_hosts_client.py b/tempest/services/volume/base/admin/base_hosts_client.py
similarity index 84%
rename from tempest/services/volume/json/admin/volume_hosts_client.py
rename to tempest/services/volume/base/admin/base_hosts_client.py
index 939db59..074f87f 100644
--- a/tempest/services/volume/json/admin/volume_hosts_client.py
+++ b/tempest/services/volume/base/admin/base_hosts_client.py
@@ -19,10 +19,10 @@
from tempest.common import service_client
-class BaseVolumeHostsClient(service_client.ServiceClient):
+class BaseHostsClient(service_client.ServiceClient):
"""Client class to send CRUD Volume Hosts API requests"""
- def list_hosts(self, params=None):
+ def list_hosts(self, **params):
"""Lists all hosts."""
url = 'os-hosts'
@@ -33,7 +33,3 @@
body = json.loads(body)
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
-
-
-class VolumeHostsClient(BaseVolumeHostsClient):
- """Client class to send CRUD Volume Host API V1 requests"""
diff --git a/tempest/services/volume/json/admin/volume_quotas_client.py b/tempest/services/volume/base/admin/base_quotas_client.py
similarity index 75%
rename from tempest/services/volume/json/admin/volume_quotas_client.py
rename to tempest/services/volume/base/admin/base_quotas_client.py
index f6d4a14..e063a31 100644
--- a/tempest/services/volume/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/base/admin/base_quotas_client.py
@@ -18,7 +18,7 @@
from tempest.common import service_client
-class BaseVolumeQuotasClient(service_client.ServiceClient):
+class BaseQuotasClient(service_client.ServiceClient):
"""Client class to send CRUD Volume Quotas API requests"""
TYPE = "json"
@@ -50,21 +50,14 @@
body = self.show_quota_set(tenant_id, params={'usage': True})
return body
- def update_quota_set(self, tenant_id, gigabytes=None, volumes=None,
- snapshots=None):
- post_body = {}
+ def update_quota_set(self, tenant_id, **kwargs):
+ """Updates quota set
- if gigabytes is not None:
- post_body['gigabytes'] = gigabytes
-
- if volumes is not None:
- post_body['volumes'] = volumes
-
- if snapshots is not None:
- post_body['snapshots'] = snapshots
-
- post_body = jsonutils.dumps({'quota_set': post_body})
- resp, body = self.put('os-quota-sets/%s' % tenant_id, post_body)
+ Available params: see http://developer.openstack.org/
+ api-ref-blockstorage-v2.html#updateQuotas-v2
+ """
+ put_body = jsonutils.dumps({'quota_set': kwargs})
+ resp, body = self.put('os-quota-sets/%s' % tenant_id, put_body)
self.expected_success(200, resp.status)
body = jsonutils.loads(body)
return service_client.ResponseBody(resp, body)
@@ -74,7 +67,3 @@
resp, body = self.delete('os-quota-sets/%s' % tenant_id)
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
-
-
-class VolumeQuotasClient(BaseVolumeQuotasClient):
- """Client class to send CRUD Volume Type API V1 requests"""
diff --git a/tempest/services/volume/json/admin/volume_services_client.py b/tempest/services/volume/base/admin/base_services_client.py
similarity index 83%
rename from tempest/services/volume/json/admin/volume_services_client.py
rename to tempest/services/volume/base/admin/base_services_client.py
index 798a642..3626469 100644
--- a/tempest/services/volume/json/admin/volume_services_client.py
+++ b/tempest/services/volume/base/admin/base_services_client.py
@@ -19,9 +19,9 @@
from tempest.common import service_client
-class BaseVolumesServicesClient(service_client.ServiceClient):
+class BaseServicesClient(service_client.ServiceClient):
- def list_services(self, params=None):
+ def list_services(self, **params):
url = 'os-services'
if params:
url += '?%s' % urllib.urlencode(params)
@@ -30,7 +30,3 @@
body = json.loads(body)
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
-
-
-class VolumesServicesClient(BaseVolumesServicesClient):
- """Volume V1 volume services client"""
diff --git a/tempest/services/volume/json/admin/volume_types_client.py b/tempest/services/volume/base/admin/base_types_client.py
similarity index 97%
rename from tempest/services/volume/json/admin/volume_types_client.py
rename to tempest/services/volume/base/admin/base_types_client.py
index f2da8a5..de6ea8a 100644
--- a/tempest/services/volume/json/admin/volume_types_client.py
+++ b/tempest/services/volume/base/admin/base_types_client.py
@@ -20,7 +20,7 @@
from tempest.common import service_client
-class BaseVolumeTypesClient(service_client.ServiceClient):
+class BaseTypesClient(service_client.ServiceClient):
"""Client class to send CRUD Volume Types API requests"""
def is_resource_deleted(self, resource):
@@ -182,7 +182,3 @@
"/types/%s/encryption/provider" % str(vol_type_id))
self.expected_success(202, resp.status)
return service_client.ResponseBody(resp, body)
-
-
-class VolumeTypesClient(BaseVolumeTypesClient):
- """Volume V1 Volume Types client"""
diff --git a/tempest/services/volume/json/availability_zone_client.py b/tempest/services/volume/base/base_availability_zone_client.py
similarity index 83%
rename from tempest/services/volume/json/availability_zone_client.py
rename to tempest/services/volume/base/base_availability_zone_client.py
index 36f95d6..b63fdc2 100644
--- a/tempest/services/volume/json/availability_zone_client.py
+++ b/tempest/services/volume/base/base_availability_zone_client.py
@@ -18,14 +18,10 @@
from tempest.common import service_client
-class BaseVolumeAvailabilityZoneClient(service_client.ServiceClient):
+class BaseAvailabilityZoneClient(service_client.ServiceClient):
def list_availability_zones(self):
resp, body = self.get('os-availability-zone')
body = json.loads(body)
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
-
-
-class VolumeAvailabilityZoneClient(BaseVolumeAvailabilityZoneClient):
- """Volume V1 availability zone client."""
diff --git a/tempest/services/volume/json/backups_client.py b/tempest/services/volume/base/base_backups_client.py
similarity index 82%
rename from tempest/services/volume/json/backups_client.py
rename to tempest/services/volume/base/base_backups_client.py
index 3045992..fc9a40a 100644
--- a/tempest/services/volume/json/backups_client.py
+++ b/tempest/services/volume/base/base_backups_client.py
@@ -16,7 +16,6 @@
import time
from oslo_serialization import jsonutils as json
-
from tempest_lib import exceptions as lib_exc
from tempest.common import service_client
@@ -26,26 +25,17 @@
class BaseBackupsClient(service_client.ServiceClient):
"""Client class to send CRUD Volume backup API requests"""
- def create_backup(self, volume_id, container=None, name=None,
- description=None):
+ def create_backup(self, **kwargs):
"""Creates a backup of volume."""
- post_body = {'volume_id': volume_id}
- if container:
- post_body['container'] = container
- if name:
- post_body['name'] = name
- if description:
- post_body['description'] = description
- post_body = json.dumps({'backup': post_body})
+ post_body = json.dumps({'backup': kwargs})
resp, body = self.post('backups', post_body)
body = json.loads(body)
self.expected_success(202, resp.status)
return service_client.ResponseBody(resp, body)
- def restore_backup(self, backup_id, volume_id=None):
+ def restore_backup(self, backup_id, **kwargs):
"""Restore volume from backup."""
- post_body = {'volume_id': volume_id}
- post_body = json.dumps({'restore': post_body})
+ post_body = json.dumps({'restore': kwargs})
resp, body = self.post('backups/%s/restore' % (backup_id), post_body)
body = json.loads(body)
self.expected_success(202, resp.status)
@@ -83,11 +73,9 @@
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
- def import_backup(self, backup_service, backup_url):
+ def import_backup(self, **kwargs):
"""Import backup metadata record."""
- post_body = {'backup_service': backup_service,
- 'backup_url': backup_url}
- post_body = json.dumps({'backup-record': post_body})
+ post_body = json.dumps({'backup-record': kwargs})
resp, body = self.post("backups/import_record", post_body)
body = json.loads(body)
self.expected_success(201, resp.status)
@@ -124,7 +112,3 @@
if int(time.time()) - start_time >= self.build_timeout:
raise exceptions.TimeoutException
time.sleep(self.build_interval)
-
-
-class BackupsClient(BaseBackupsClient):
- """Volume V1 Backups client"""
diff --git a/tempest/services/volume/json/extensions_client.py b/tempest/services/volume/base/base_extensions_client.py
similarity index 91%
rename from tempest/services/volume/json/extensions_client.py
rename to tempest/services/volume/base/base_extensions_client.py
index d7d3197..afc3f6b 100644
--- a/tempest/services/volume/json/extensions_client.py
+++ b/tempest/services/volume/base/base_extensions_client.py
@@ -26,7 +26,3 @@
body = json.loads(body)
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
-
-
-class ExtensionsClient(BaseExtensionsClient):
- """Volume V1 extensions client."""
diff --git a/tempest/services/volume/json/qos_client.py b/tempest/services/volume/base/base_qos_client.py
similarity index 98%
rename from tempest/services/volume/json/qos_client.py
rename to tempest/services/volume/base/base_qos_client.py
index c79168c..c7f6c6e 100644
--- a/tempest/services/volume/json/qos_client.py
+++ b/tempest/services/volume/base/base_qos_client.py
@@ -155,7 +155,3 @@
resp, body = self.get(url)
self.expected_success(202, resp.status)
return service_client.ResponseBody(resp, body)
-
-
-class QosSpecsClient(BaseQosSpecsClient):
- """Volume V1 QoS client."""
diff --git a/tempest/services/volume/json/snapshots_client.py b/tempest/services/volume/base/base_snapshots_client.py
similarity index 98%
rename from tempest/services/volume/json/snapshots_client.py
rename to tempest/services/volume/base/base_snapshots_client.py
index 77c9dd1..fac90e4 100644
--- a/tempest/services/volume/json/snapshots_client.py
+++ b/tempest/services/volume/base/base_snapshots_client.py
@@ -196,7 +196,3 @@
resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body)
self.expected_success(202, resp.status)
return service_client.ResponseBody(resp, body)
-
-
-class SnapshotsClient(BaseSnapshotsClient):
- """Client class to send CRUD Volume V1 API requests."""
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/base/base_volumes_client.py
similarity index 98%
rename from tempest/services/volume/json/volumes_client.py
rename to tempest/services/volume/base/base_volumes_client.py
index c2a76f0..c7302e8 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/base/base_volumes_client.py
@@ -334,7 +334,3 @@
post_body = json.dumps({'os-retype': post_body})
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
self.expected_success(202, resp.status)
-
-
-class VolumesClient(BaseVolumesClient):
- """Client class to send CRUD Volume V1 API requests"""
diff --git a/tempest/services/volume/json/__init__.py b/tempest/services/volume/v1/__init__.py
similarity index 100%
copy from tempest/services/volume/json/__init__.py
copy to tempest/services/volume/v1/__init__.py
diff --git a/tempest/services/volume/json/__init__.py b/tempest/services/volume/v1/json/__init__.py
similarity index 100%
rename from tempest/services/volume/json/__init__.py
rename to tempest/services/volume/v1/json/__init__.py
diff --git a/tempest/services/volume/json/admin/__init__.py b/tempest/services/volume/v1/json/admin/__init__.py
similarity index 100%
rename from tempest/services/volume/json/admin/__init__.py
rename to tempest/services/volume/v1/json/admin/__init__.py
diff --git a/tempest/services/volume/v2/json/admin/volume_quotas_client.py b/tempest/services/volume/v1/json/admin/hosts_client.py
similarity index 69%
copy from tempest/services/volume/v2/json/admin/volume_quotas_client.py
copy to tempest/services/volume/v1/json/admin/hosts_client.py
index 80fffc7..3b52968 100644
--- a/tempest/services/volume/v2/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/v1/json/admin/hosts_client.py
@@ -1,4 +1,4 @@
-# Copyright 2014 OpenStack Foundation
+# Copyright 2013 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -13,9 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json.admin import volume_quotas_client
+from tempest.services.volume.base.admin import base_hosts_client
-class VolumeQuotasV2Client(volume_quotas_client.BaseVolumeQuotasClient):
- """Client class to send CRUD Volume V2 API requests"""
- api_version = "v2"
+class HostsClient(base_hosts_client.BaseHostsClient):
+ """Client class to send CRUD Volume Host API V1 requests"""
diff --git a/tempest/services/volume/v2/json/admin/volume_types_client.py b/tempest/services/volume/v1/json/admin/quotas_client.py
similarity index 67%
copy from tempest/services/volume/v2/json/admin/volume_types_client.py
copy to tempest/services/volume/v1/json/admin/quotas_client.py
index 78fe8e5..27fc301 100644
--- a/tempest/services/volume/v2/json/admin/volume_types_client.py
+++ b/tempest/services/volume/v1/json/admin/quotas_client.py
@@ -1,5 +1,4 @@
-# Copyright 2012 OpenStack Foundation
-# All Rights Reserved.
+# Copyright (C) 2014 eNovance SAS <licensing@enovance.com>
#
# 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
@@ -13,10 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-
-from tempest.services.volume.json.admin import volume_types_client
+from tempest.services.volume.base.admin import base_quotas_client
-class VolumeTypesV2Client(volume_types_client.BaseVolumeTypesClient):
- """Client class to send CRUD Volume V2 API requests"""
- api_version = "v2"
+class QuotasClient(base_quotas_client.BaseQuotasClient):
+ """Client class to send CRUD Volume Type API V1 requests"""
diff --git a/tempest/services/volume/v2/json/admin/volume_quotas_client.py b/tempest/services/volume/v1/json/admin/services_client.py
similarity index 69%
copy from tempest/services/volume/v2/json/admin/volume_quotas_client.py
copy to tempest/services/volume/v1/json/admin/services_client.py
index 80fffc7..2bffd55 100644
--- a/tempest/services/volume/v2/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/v1/json/admin/services_client.py
@@ -1,4 +1,4 @@
-# Copyright 2014 OpenStack Foundation
+# Copyright 2014 NEC Corporation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -13,9 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json.admin import volume_quotas_client
+from tempest.services.volume.base.admin import base_services_client
-class VolumeQuotasV2Client(volume_quotas_client.BaseVolumeQuotasClient):
- """Client class to send CRUD Volume V2 API requests"""
- api_version = "v2"
+class ServicesClient(base_services_client.BaseServicesClient):
+ """Volume V1 volume services client"""
diff --git a/tempest/services/volume/v2/json/admin/volume_types_client.py b/tempest/services/volume/v1/json/admin/types_client.py
similarity index 74%
copy from tempest/services/volume/v2/json/admin/volume_types_client.py
copy to tempest/services/volume/v1/json/admin/types_client.py
index 78fe8e5..0e84296 100644
--- a/tempest/services/volume/v2/json/admin/volume_types_client.py
+++ b/tempest/services/volume/v1/json/admin/types_client.py
@@ -13,10 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-
-from tempest.services.volume.json.admin import volume_types_client
+from tempest.services.volume.base.admin import base_types_client
-class VolumeTypesV2Client(volume_types_client.BaseVolumeTypesClient):
- """Client class to send CRUD Volume V2 API requests"""
- api_version = "v2"
+class TypesClient(base_types_client.BaseTypesClient):
+ """Volume V1 Volume Types client"""
diff --git a/tempest/services/volume/v2/json/admin/volume_quotas_client.py b/tempest/services/volume/v1/json/availability_zone_client.py
similarity index 69%
copy from tempest/services/volume/v2/json/admin/volume_quotas_client.py
copy to tempest/services/volume/v1/json/availability_zone_client.py
index 80fffc7..3a27027 100644
--- a/tempest/services/volume/v2/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/v1/json/availability_zone_client.py
@@ -1,4 +1,4 @@
-# Copyright 2014 OpenStack Foundation
+# Copyright 2014 NEC Corporation.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -13,9 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json.admin import volume_quotas_client
+from tempest.services.volume.base import base_availability_zone_client
-class VolumeQuotasV2Client(volume_quotas_client.BaseVolumeQuotasClient):
- """Client class to send CRUD Volume V2 API requests"""
- api_version = "v2"
+class AvailabilityZoneClient(
+ base_availability_zone_client.BaseAvailabilityZoneClient):
+ """Volume V1 availability zone client."""
diff --git a/tempest/services/volume/v2/json/admin/volume_hosts_client.py b/tempest/services/volume/v1/json/backups_client.py
similarity index 74%
copy from tempest/services/volume/v2/json/admin/volume_hosts_client.py
copy to tempest/services/volume/v1/json/backups_client.py
index 649c9ec..ac6db6a 100644
--- a/tempest/services/volume/v2/json/admin/volume_hosts_client.py
+++ b/tempest/services/volume/v1/json/backups_client.py
@@ -13,10 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-
-from tempest.services.volume.json.admin import volume_hosts_client
+from tempest.services.volume.base import base_backups_client
-class VolumeHostsV2Client(volume_hosts_client.BaseVolumeHostsClient):
- """Client class to send CRUD Volume V2 API requests"""
- api_version = "v2"
+class BackupsClient(base_backups_client.BaseBackupsClient):
+ """Volume V1 Backups client"""
diff --git a/tempest/services/volume/v2/json/admin/volume_types_client.py b/tempest/services/volume/v1/json/extensions_client.py
similarity index 74%
copy from tempest/services/volume/v2/json/admin/volume_types_client.py
copy to tempest/services/volume/v1/json/extensions_client.py
index 78fe8e5..f99d0f5 100644
--- a/tempest/services/volume/v2/json/admin/volume_types_client.py
+++ b/tempest/services/volume/v1/json/extensions_client.py
@@ -13,10 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-
-from tempest.services.volume.json.admin import volume_types_client
+from tempest.services.volume.base import base_extensions_client
-class VolumeTypesV2Client(volume_types_client.BaseVolumeTypesClient):
- """Client class to send CRUD Volume V2 API requests"""
- api_version = "v2"
+class ExtensionsClient(base_extensions_client.BaseExtensionsClient):
+ """Volume V1 extensions client."""
diff --git a/tempest/services/volume/v2/json/admin/volume_quotas_client.py b/tempest/services/volume/v1/json/qos_client.py
similarity index 69%
copy from tempest/services/volume/v2/json/admin/volume_quotas_client.py
copy to tempest/services/volume/v1/json/qos_client.py
index 80fffc7..b2b2195 100644
--- a/tempest/services/volume/v2/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/v1/json/qos_client.py
@@ -1,4 +1,3 @@
-# Copyright 2014 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -13,9 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json.admin import volume_quotas_client
+from tempest.services.volume.base import base_qos_client
-class VolumeQuotasV2Client(volume_quotas_client.BaseVolumeQuotasClient):
- """Client class to send CRUD Volume V2 API requests"""
- api_version = "v2"
+class QosSpecsClient(base_qos_client.BaseQosSpecsClient):
+ """Volume V1 QoS client."""
diff --git a/tempest/services/volume/v2/json/admin/volume_quotas_client.py b/tempest/services/volume/v1/json/snapshots_client.py
similarity index 66%
copy from tempest/services/volume/v2/json/admin/volume_quotas_client.py
copy to tempest/services/volume/v1/json/snapshots_client.py
index 80fffc7..b039c2b 100644
--- a/tempest/services/volume/v2/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/v1/json/snapshots_client.py
@@ -1,6 +1,3 @@
-# Copyright 2014 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
@@ -13,9 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json.admin import volume_quotas_client
+from tempest.services.volume.base import base_snapshots_client
-class VolumeQuotasV2Client(volume_quotas_client.BaseVolumeQuotasClient):
- """Client class to send CRUD Volume V2 API requests"""
- api_version = "v2"
+class SnapshotsClient(base_snapshots_client.BaseSnapshotsClient):
+ """Client class to send CRUD Volume V1 API requests."""
diff --git a/tempest/services/volume/v2/json/admin/volume_types_client.py b/tempest/services/volume/v1/json/volumes_client.py
similarity index 74%
copy from tempest/services/volume/v2/json/admin/volume_types_client.py
copy to tempest/services/volume/v1/json/volumes_client.py
index 78fe8e5..7782043 100644
--- a/tempest/services/volume/v2/json/admin/volume_types_client.py
+++ b/tempest/services/volume/v1/json/volumes_client.py
@@ -13,10 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-
-from tempest.services.volume.json.admin import volume_types_client
+from tempest.services.volume.base import base_volumes_client
-class VolumeTypesV2Client(volume_types_client.BaseVolumeTypesClient):
- """Client class to send CRUD Volume V2 API requests"""
- api_version = "v2"
+class VolumesClient(base_volumes_client.BaseVolumesClient):
+ """Client class to send CRUD Volume V1 API requests"""
diff --git a/tempest/services/volume/v2/json/admin/volume_hosts_client.py b/tempest/services/volume/v2/json/admin/hosts_client.py
similarity index 84%
rename from tempest/services/volume/v2/json/admin/volume_hosts_client.py
rename to tempest/services/volume/v2/json/admin/hosts_client.py
index 649c9ec..e092c6a 100644
--- a/tempest/services/volume/v2/json/admin/volume_hosts_client.py
+++ b/tempest/services/volume/v2/json/admin/hosts_client.py
@@ -13,10 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-
-from tempest.services.volume.json.admin import volume_hosts_client
+from tempest.services.volume.base.admin import base_hosts_client
-class VolumeHostsV2Client(volume_hosts_client.BaseVolumeHostsClient):
+class HostsClient(base_hosts_client.BaseHostsClient):
"""Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/admin/volume_quotas_client.py b/tempest/services/volume/v2/json/admin/quotas_client.py
similarity index 83%
rename from tempest/services/volume/v2/json/admin/volume_quotas_client.py
rename to tempest/services/volume/v2/json/admin/quotas_client.py
index 80fffc7..11e0e22 100644
--- a/tempest/services/volume/v2/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/v2/json/admin/quotas_client.py
@@ -13,9 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json.admin import volume_quotas_client
+from tempest.services.volume.base.admin import base_quotas_client
-class VolumeQuotasV2Client(volume_quotas_client.BaseVolumeQuotasClient):
+class QuotasClient(base_quotas_client.BaseQuotasClient):
"""Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/admin/volume_quotas_client.py b/tempest/services/volume/v2/json/admin/services_client.py
similarity index 83%
copy from tempest/services/volume/v2/json/admin/volume_quotas_client.py
copy to tempest/services/volume/v2/json/admin/services_client.py
index 80fffc7..db19ba9 100644
--- a/tempest/services/volume/v2/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/v2/json/admin/services_client.py
@@ -13,9 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json.admin import volume_quotas_client
+from tempest.services.volume.base.admin import base_services_client
-class VolumeQuotasV2Client(volume_quotas_client.BaseVolumeQuotasClient):
+class ServicesClient(base_services_client.BaseServicesClient):
"""Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/admin/volume_types_client.py b/tempest/services/volume/v2/json/admin/types_client.py
similarity index 84%
rename from tempest/services/volume/v2/json/admin/volume_types_client.py
rename to tempest/services/volume/v2/json/admin/types_client.py
index 78fe8e5..ecf5131 100644
--- a/tempest/services/volume/v2/json/admin/volume_types_client.py
+++ b/tempest/services/volume/v2/json/admin/types_client.py
@@ -13,10 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-
-from tempest.services.volume.json.admin import volume_types_client
+from tempest.services.volume.base.admin import base_types_client
-class VolumeTypesV2Client(volume_types_client.BaseVolumeTypesClient):
+class TypesClient(base_types_client.BaseTypesClient):
"""Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/admin/volume_services_client.py b/tempest/services/volume/v2/json/admin/volume_services_client.py
deleted file mode 100644
index 88eb82f..0000000
--- a/tempest/services/volume/v2/json/admin/volume_services_client.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2014 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.services.volume.json.admin import volume_services_client as vs_cli
-
-
-class VolumesServicesV2Client(vs_cli.BaseVolumesServicesClient):
- """Client class to send CRUD Volume V2 API requests"""
- api_version = "v2"
diff --git a/tempest/services/volume/v2/json/availability_zone_client.py b/tempest/services/volume/v2/json/availability_zone_client.py
index 2e1ab20..905ebdc 100644
--- a/tempest/services/volume/v2/json/availability_zone_client.py
+++ b/tempest/services/volume/v2/json/availability_zone_client.py
@@ -13,9 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json import availability_zone_client
+from tempest.services.volume.base import base_availability_zone_client
-class VolumeV2AvailabilityZoneClient(
- availability_zone_client.BaseVolumeAvailabilityZoneClient):
+class AvailabilityZoneClient(
+ base_availability_zone_client.BaseAvailabilityZoneClient):
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/backups_client.py b/tempest/services/volume/v2/json/backups_client.py
index 8e87505..78bab82 100644
--- a/tempest/services/volume/v2/json/backups_client.py
+++ b/tempest/services/volume/v2/json/backups_client.py
@@ -13,9 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json import backups_client
+from tempest.services.volume.base import base_backups_client
-class BackupsClientV2(backups_client.BaseBackupsClient):
+class BackupsClient(base_backups_client.BaseBackupsClient):
"""Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/extensions_client.py b/tempest/services/volume/v2/json/extensions_client.py
index 3e32c0c..245906f 100644
--- a/tempest/services/volume/v2/json/extensions_client.py
+++ b/tempest/services/volume/v2/json/extensions_client.py
@@ -13,8 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json import extensions_client
+from tempest.services.volume.base import base_extensions_client
-class ExtensionsV2Client(extensions_client.BaseExtensionsClient):
+class ExtensionsClient(base_extensions_client.BaseExtensionsClient):
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/qos_client.py b/tempest/services/volume/v2/json/qos_client.py
index 42bd1c9..3c0f74f 100644
--- a/tempest/services/volume/v2/json/qos_client.py
+++ b/tempest/services/volume/v2/json/qos_client.py
@@ -12,8 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json import qos_client
+from tempest.services.volume.base import base_qos_client
-class QosSpecsV2Client(qos_client.BaseQosSpecsClient):
+class QosSpecsClient(base_qos_client.BaseQosSpecsClient):
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/snapshots_client.py b/tempest/services/volume/v2/json/snapshots_client.py
index a94f9cd..a2d415f 100644
--- a/tempest/services/volume/v2/json/snapshots_client.py
+++ b/tempest/services/volume/v2/json/snapshots_client.py
@@ -10,10 +10,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json import snapshots_client
+from tempest.services.volume.base import base_snapshots_client
-class SnapshotsV2Client(snapshots_client.BaseSnapshotsClient):
+class SnapshotsClient(base_snapshots_client.BaseSnapshotsClient):
"""Client class to send CRUD Volume V2 API requests."""
api_version = "v2"
create_resp = 202
diff --git a/tempest/services/volume/v2/json/volumes_client.py b/tempest/services/volume/v2/json/volumes_client.py
index a56a7be..b7d9dfb 100644
--- a/tempest/services/volume/v2/json/volumes_client.py
+++ b/tempest/services/volume/v2/json/volumes_client.py
@@ -13,10 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.volume.json import volumes_client
+from tempest.services.volume.base import base_volumes_client
-class VolumesV2Client(volumes_client.BaseVolumesClient):
+class VolumesClient(base_volumes_client.BaseVolumesClient):
"""Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
create_resp = 202
diff --git a/tempest/stress/README.rst b/tempest/stress/README.rst
index 4f1f56c..33842fd 100644
--- a/tempest/stress/README.rst
+++ b/tempest/stress/README.rst
@@ -33,17 +33,17 @@
The stress test framework can automatically discover test inside the tempest
test suite. All test flag with the `@stresstest` decorator will be executed.
-In order to use this discovery you have to be in the tempest root directory
-and execute the following:
+In order to use this discovery you have to install tempest CLI, be in the
+tempest root directory and execute the following:
- run-tempest-stress -a -d 30
+ tempest run-stress -a -d 30
Running the sample test
-----------------------
To test installation, do the following:
- run-tempest-stress -t tempest/stress/etc/server-create-destroy-test.json -d 30
+ tempest run-stress -t tempest/stress/etc/server-create-destroy-test.json -d 30
This sample test tries to create a few VMs and kill a few VMs.
diff --git a/tempest/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
index 6bac570..4f8c6bd 100644
--- a/tempest/stress/actions/ssh_floating.py
+++ b/tempest/stress/actions/ssh_floating.py
@@ -91,7 +91,7 @@
self.logger.info("deleted %s" % self.server_id)
def _create_sec_group(self):
- sec_grp_cli = self.manager.security_groups_client
+ sec_grp_cli = self.manager.compute_security_groups_client
s_name = data_utils.rand_name('sec_grp')
s_description = data_utils.rand_name('desc')
self.sec_grp = sec_grp_cli.create_security_group(
@@ -103,7 +103,7 @@
from_port=-1, to_port=-1)
def _destroy_sec_grp(self):
- sec_grp_cli = self.manager.security_groups_client
+ sec_grp_cli = self.manager.compute_security_groups_client
sec_grp_cli.delete_security_group(self.sec_grp['id'])
def _create_floating_ip(self):
diff --git a/tempest/stress/actions/volume_attach_verify.py b/tempest/stress/actions/volume_attach_verify.py
index fa0bb8b..2a23291 100644
--- a/tempest/stress/actions/volume_attach_verify.py
+++ b/tempest/stress/actions/volume_attach_verify.py
@@ -54,7 +54,7 @@
self.logger.info("deleted server: %s" % self.server_id)
def _create_sec_group(self):
- sec_grp_cli = self.manager.security_groups_client
+ sec_grp_cli = self.manager.compute_security_groups_client
s_name = data_utils.rand_name('sec_grp')
s_description = data_utils.rand_name('desc')
self.sec_grp = sec_grp_cli.create_security_group(
@@ -66,7 +66,7 @@
from_port=-1, to_port=-1)
def _destroy_sec_grp(self):
- sec_grp_cli = self.manager.security_groups_client
+ sec_grp_cli = self.manager.compute_security_groups_client
sec_grp_cli.delete_security_group(self.sec_grp['id'])
def _create_floating_ip(self):
diff --git a/tempest/stress/cleanup.py b/tempest/stress/cleanup.py
index 993359d..5c25e32 100644
--- a/tempest/stress/cleanup.py
+++ b/tempest/stress/cleanup.py
@@ -48,7 +48,7 @@
except Exception:
pass
- secgrp_client = admin_manager.security_groups_client
+ secgrp_client = admin_manager.compute_security_groups_client
secgrp = (secgrp_client.list_security_groups(all_tenants=True)
['security_groups'])
secgrp_del = [grp for grp in secgrp if grp['name'] != 'default']
@@ -74,12 +74,11 @@
for user in users:
if user['name'].startswith("stress_user"):
admin_manager.identity_client.delete_user(user['id'])
-
- tenants = admin_manager.identity_client.list_tenants()['tenants']
+ tenants = admin_manager.tenants_client.list_tenants()['tenants']
LOG.info("Cleanup::remove %s tenants" % len(tenants))
for tenant in tenants:
if tenant['name'].startswith("stress_tenant"):
- admin_manager.identity_client.delete_tenant(tenant['id'])
+ admin_manager.tenants_client.delete_tenant(tenant['id'])
# We have to delete snapshots first or
# volume deletion may block
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index 8359efd..cac848b 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -146,14 +146,16 @@
password = "pass"
if CONF.identity.auth_version == 'v2':
identity_client = admin_manager.identity_client
+ projects_client = admin_manager.tenants_client
else:
identity_client = admin_manager.identity_v3_client
+ projects_client = None
credentials_client = cred_client.get_creds_client(
- identity_client)
+ identity_client, projects_client)
project = credentials_client.create_project(
name=tenant_name, description=tenant_name)
user = credentials_client.create_user(username, password,
- project['id'], "email")
+ project, "email")
# Add roles specified in config file
for conf_role in CONF.auth.tempest_roles:
credentials_client.assign_user_role(user, project,
diff --git a/tempest/test.py b/tempest/test.py
index 7b508ac..8e961f4 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -27,6 +27,7 @@
from oslo_serialization import jsonutils as json
from oslo_utils import importutils
import six
+from tempest_lib import decorators
import testscenarios
import testtools
@@ -43,6 +44,8 @@
CONF = config.CONF
+idempotent_id = decorators.idempotent_id
+
def attr(**kwargs):
"""A decorator which applies the testtools attr decorator
@@ -62,23 +65,6 @@
return decorator
-def idempotent_id(id):
- """Stub for metadata decorator"""
- if not isinstance(id, six.string_types):
- raise TypeError('Test idempotent_id must be string not %s'
- '' % type(id).__name__)
- uuid.UUID(id)
-
- def decorator(f):
- f = testtools.testcase.attr('id-%s' % id)(f)
- if f.__doc__:
- f.__doc__ = 'Test idempotent id: %s\n%s' % (id, f.__doc__)
- else:
- f.__doc__ = 'Test idempotent id: %s' % id
- return f
- return decorator
-
-
def get_service_list():
service_list = {
'compute': CONF.service_available.nova,
@@ -450,15 +436,18 @@
"""
if CONF.identity.auth_version == 'v2':
client = self.os_admin.identity_client
+ project_client = self.os_admin.tenants_client
else:
client = self.os_admin.identity_v3_client
+ project_client = None
try:
domain = client.auth_provider.credentials.project_domain_name
except AttributeError:
domain = 'Default'
- return cred_client.get_creds_client(client, domain)
+ return cred_client.get_creds_client(client, project_client,
+ project_domain_name=domain)
@classmethod
def get_identity_version(cls):
@@ -495,7 +484,7 @@
:param credential_type: string - primary, alt or admin
:param roles: list of roles
- :returns the created client manager
+ :returns: the created client manager
:raises skipException: if the requested credentials are not available
"""
if all([roles, credential_type]):
@@ -612,8 +601,8 @@
admin_creds = cred_provider.get_admin_creds()
admin_manager = clients.Manager(admin_creds)
networks_client = admin_manager.compute_networks_client
- return fixed_network.get_tenant_network(cred_provider,
- networks_client)
+ return fixed_network.get_tenant_network(
+ cred_provider, networks_client, CONF.compute.fixed_network_name)
def assertEmpty(self, list, msg=None):
self.assertTrue(len(list) == 0, msg)
diff --git a/tempest/tests/cmd/test_javelin.py b/tempest/tests/cmd/test_javelin.py
index fc3d984..56bc96c 100644
--- a/tempest/tests/cmd/test_javelin.py
+++ b/tempest/tests/cmd/test_javelin.py
@@ -85,31 +85,33 @@
class TestCreateResources(JavelinUnitTest):
def test_create_tenants(self):
- self.fake_client.identity.list_tenants.return_value = {'tenants': []}
+ self.fake_client.tenants.list_tenants.return_value = {'tenants': []}
self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
return_value=self.fake_client))
javelin.create_tenants([self.fake_object['name']])
- mocked_function = self.fake_client.identity.create_tenant
+ mocked_function = self.fake_client.tenants.create_tenant
mocked_function.assert_called_once_with(self.fake_object['name'])
def test_create_duplicate_tenant(self):
- self.fake_client.identity.list_tenants.return_value = {'tenants': [
+ self.fake_client.tenants.list_tenants.return_value = {'tenants': [
{'name': self.fake_object['name']}]}
self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
return_value=self.fake_client))
javelin.create_tenants([self.fake_object['name']])
- mocked_function = self.fake_client.identity.create_tenant
+ mocked_function = self.fake_client.tenants.create_tenant
self.assertFalse(mocked_function.called)
def test_create_users(self):
- self.fake_client.identity.get_tenant_by_name.return_value = \
- self.fake_object['tenant']
- self.fake_client.identity.get_user_by_username.side_effect = \
- lib_exc.NotFound("user is not found")
+ self.useFixture(mockpatch.Patch(
+ 'tempest.common.identity.get_tenant_by_name',
+ return_value=self.fake_object['tenant']))
+ self.useFixture(mockpatch.Patch(
+ 'tempest.common.identity.get_user_by_username',
+ side_effect=lib_exc.NotFound("user is not found")))
self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
return_value=self.fake_client))
@@ -125,8 +127,9 @@
enabled=True)
def test_create_user_missing_tenant(self):
- self.fake_client.identity.get_tenant_by_name.side_effect = \
- lib_exc.NotFound("tenant is not found")
+ self.useFixture(mockpatch.Patch(
+ 'tempest.common.identity.get_tenant_by_name',
+ side_effect=lib_exc.NotFound("tenant is not found")))
self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
return_value=self.fake_client))
@@ -289,13 +292,14 @@
fake_tenant = self.fake_object['tenant']
fake_auth = self.fake_client
- fake_auth.identity.get_tenant_by_name.return_value = fake_tenant
-
+ self.useFixture(mockpatch.Patch(
+ 'tempest.common.identity.get_tenant_by_name',
+ return_value=fake_tenant))
self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
return_value=fake_auth))
javelin.destroy_tenants([fake_tenant])
- mocked_function = fake_auth.identity.delete_tenant
+ mocked_function = fake_auth.tenants.delete_tenant
mocked_function.assert_called_once_with(fake_tenant['id'])
def test_destroy_users(self):
@@ -304,9 +308,13 @@
fake_tenant = self.fake_object['tenant']
fake_auth = self.fake_client
- fake_auth.identity.get_tenant_by_name.return_value = fake_tenant
- fake_auth.identity.get_user_by_username.return_value = fake_user
+ fake_auth.tenants.list_tenants.return_value = \
+ {'tenants': [fake_tenant]}
+ fake_auth.identity.list_users.return_value = {'users': [fake_user]}
+ self.useFixture(mockpatch.Patch(
+ 'tempest.common.identity.get_user_by_username',
+ return_value=fake_user))
self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
return_value=fake_auth))
diff --git a/tempest/tests/common/test_api_version_request.py b/tempest/tests/common/test_api_version_request.py
new file mode 100644
index 0000000..38fbfc1
--- /dev/null
+++ b/tempest/tests/common/test_api_version_request.py
@@ -0,0 +1,146 @@
+# Copyright 2014 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.common import api_version_request
+from tempest import exceptions
+from tempest.tests import base
+
+
+class APIVersionRequestTests(base.TestCase):
+ def test_valid_version_strings(self):
+ def _test_string(version, exp_major, exp_minor):
+ v = api_version_request.APIVersionRequest(version)
+ self.assertEqual(v.ver_major, exp_major)
+ self.assertEqual(v.ver_minor, exp_minor)
+
+ _test_string("1.1", 1, 1)
+ _test_string("2.10", 2, 10)
+ _test_string("5.234", 5, 234)
+ _test_string("12.5", 12, 5)
+ _test_string("2.0", 2, 0)
+ _test_string("2.200", 2, 200)
+
+ def test_null_version(self):
+ v = api_version_request.APIVersionRequest()
+ self.assertTrue(v.is_null())
+
+ def test_invalid_version_strings(self):
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "2")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "200")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "2.1.4")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "200.23.66.3")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "5 .3")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "5. 3")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "5.03")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "02.1")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "2.001")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, " 2.1")
+
+ self.assertRaises(exceptions.InvalidAPIVersionString,
+ api_version_request.APIVersionRequest, "2.1 ")
+
+ def test_version_comparisons(self):
+ vers2_0 = api_version_request.APIVersionRequest("2.0")
+ vers2_5 = api_version_request.APIVersionRequest("2.5")
+ vers5_23 = api_version_request.APIVersionRequest("5.23")
+ v_null = api_version_request.APIVersionRequest()
+ v_latest = api_version_request.APIVersionRequest('latest')
+
+ self.assertTrue(v_null < vers2_5)
+ self.assertTrue(vers2_0 < vers2_5)
+ self.assertTrue(vers2_0 <= vers2_5)
+ self.assertTrue(vers2_0 <= vers2_0)
+ self.assertTrue(vers2_5 > v_null)
+ self.assertTrue(vers5_23 > vers2_5)
+ self.assertTrue(vers2_0 >= vers2_0)
+ self.assertTrue(vers5_23 >= vers2_5)
+ self.assertTrue(vers2_0 != vers2_5)
+ self.assertTrue(vers2_0 == vers2_0)
+ self.assertTrue(vers2_0 != v_null)
+ self.assertTrue(v_null == v_null)
+ self.assertTrue(vers2_0 <= v_latest)
+ self.assertTrue(vers2_0 != v_latest)
+ self.assertTrue(v_latest == v_latest)
+ self.assertRaises(TypeError, vers2_0.__lt__, "2.1")
+
+ def test_version_matches(self):
+ vers2_0 = api_version_request.APIVersionRequest("2.0")
+ vers2_5 = api_version_request.APIVersionRequest("2.5")
+ vers2_45 = api_version_request.APIVersionRequest("2.45")
+ vers3_3 = api_version_request.APIVersionRequest("3.3")
+ vers3_23 = api_version_request.APIVersionRequest("3.23")
+ vers4_0 = api_version_request.APIVersionRequest("4.0")
+ v_null = api_version_request.APIVersionRequest()
+ v_latest = api_version_request.APIVersionRequest('latest')
+
+ def _check_version_matches(version, version1, version2, check=True):
+ if check:
+ msg = "Version %s does not matches with [%s - %s] range"
+ self.assertTrue(version.matches(version1, version2),
+ msg % (version.get_string(),
+ version1.get_string(),
+ version2.get_string()))
+ else:
+ msg = "Version %s matches with [%s - %s] range"
+ self.assertFalse(version.matches(version1, version2),
+ msg % (version.get_string(),
+ version1.get_string(),
+ version2.get_string()))
+
+ _check_version_matches(vers2_5, vers2_0, vers2_45)
+ _check_version_matches(vers2_5, vers2_0, v_null)
+ _check_version_matches(vers2_0, vers2_0, vers2_5)
+ _check_version_matches(vers3_3, vers2_5, vers3_3)
+ _check_version_matches(vers3_3, v_null, vers3_3)
+ _check_version_matches(vers3_3, v_null, vers4_0)
+ _check_version_matches(vers2_0, vers2_5, vers2_45, False)
+ _check_version_matches(vers3_23, vers2_5, vers3_3, False)
+ _check_version_matches(vers2_5, vers2_45, vers2_0, False)
+ _check_version_matches(vers2_5, vers2_0, v_latest)
+ _check_version_matches(v_latest, v_latest, v_latest)
+ _check_version_matches(vers2_5, v_latest, v_latest, False)
+ _check_version_matches(v_latest, vers2_0, vers4_0, False)
+
+ self.assertRaises(ValueError, v_null.matches, vers2_0, vers2_45)
+
+ def test_get_string(self):
+ vers_string = ["3.23", "latest"]
+ for ver in vers_string:
+ ver_obj = api_version_request.APIVersionRequest(ver)
+ self.assertEqual(ver, ver_obj.get_string())
+
+ self.assertIsNotNone(
+ api_version_request.APIVersionRequest().get_string)
diff --git a/tempest/tests/common/test_api_version_utils.py b/tempest/tests/common/test_api_version_utils.py
new file mode 100644
index 0000000..33024b6
--- /dev/null
+++ b/tempest/tests/common/test_api_version_utils.py
@@ -0,0 +1,194 @@
+# 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 oslo_config import cfg
+import testtools
+
+from tempest.api.compute import base as compute_base
+from tempest.common import api_version_utils
+from tempest import config
+from tempest import exceptions
+from tempest.tests import base
+from tempest.tests import fake_config
+
+
+class VersionTestNoneTolatest(compute_base.BaseV2ComputeTest):
+ min_microversion = None
+ max_microversion = 'latest'
+
+
+class VersionTestNoneTo2_2(compute_base.BaseV2ComputeTest):
+ min_microversion = None
+ max_microversion = '2.2'
+
+
+class VersionTest2_3ToLatest(compute_base.BaseV2ComputeTest):
+ min_microversion = '2.3'
+ max_microversion = 'latest'
+
+
+class VersionTest2_5To2_10(compute_base.BaseV2ComputeTest):
+ min_microversion = '2.5'
+ max_microversion = '2.10'
+
+
+class VersionTest2_10To2_10(compute_base.BaseV2ComputeTest):
+ min_microversion = '2.10'
+ max_microversion = '2.10'
+
+
+class InvalidVersionTest(compute_base.BaseV2ComputeTest):
+ min_microversion = '2.11'
+ max_microversion = '2.1'
+
+
+class TestMicroversionsTestsClass(base.TestCase):
+
+ def setUp(self):
+ super(TestMicroversionsTestsClass, self).setUp()
+ self.useFixture(fake_config.ConfigFixture())
+ self.stubs.Set(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
+
+ def _test_version(self, cfg_min, cfg_max,
+ expected_pass_tests,
+ expected_skip_tests):
+ cfg.CONF.set_default('min_microversion',
+ cfg_min, group='compute-feature-enabled')
+ cfg.CONF.set_default('max_microversion',
+ cfg_max, group='compute-feature-enabled')
+ try:
+ for test_class in expected_pass_tests:
+ test_class.skip_checks()
+ for test_class in expected_skip_tests:
+ self.assertRaises(testtools.TestCase.skipException,
+ test_class.skip_checks)
+ except testtools.TestCase.skipException as e:
+ raise testtools.TestCase.failureException(e.message)
+
+ def test_config_version_none_none(self):
+ expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2]
+ expected_skip_tests = [VersionTest2_3ToLatest, VersionTest2_5To2_10,
+ VersionTest2_10To2_10]
+ self._test_version(None, None,
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_version_none_23(self):
+ expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
+ VersionTest2_3ToLatest]
+ expected_skip_tests = [VersionTest2_5To2_10, VersionTest2_10To2_10]
+ self._test_version(None, '2.3',
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_version_22_latest(self):
+ expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
+ VersionTest2_3ToLatest, VersionTest2_5To2_10,
+ VersionTest2_10To2_10]
+ expected_skip_tests = []
+ self._test_version('2.2', 'latest',
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_version_22_23(self):
+ expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
+ VersionTest2_3ToLatest]
+ expected_skip_tests = [VersionTest2_5To2_10, VersionTest2_10To2_10]
+ self._test_version('2.2', '2.3',
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_version_210_210(self):
+ expected_pass_tests = [VersionTestNoneTolatest,
+ VersionTest2_3ToLatest,
+ VersionTest2_5To2_10,
+ VersionTest2_10To2_10]
+ expected_skip_tests = [VersionTestNoneTo2_2]
+ self._test_version('2.10', '2.10',
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_version_none_latest(self):
+ expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
+ VersionTest2_3ToLatest, VersionTest2_5To2_10,
+ VersionTest2_10To2_10]
+ expected_skip_tests = []
+ self._test_version(None, 'latest',
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_version_latest_latest(self):
+ expected_pass_tests = [VersionTestNoneTolatest, VersionTest2_3ToLatest]
+ expected_skip_tests = [VersionTestNoneTo2_2, VersionTest2_5To2_10,
+ VersionTest2_10To2_10]
+ self._test_version('latest', 'latest',
+ expected_pass_tests,
+ expected_skip_tests)
+
+ def test_config_invalid_version(self):
+ cfg.CONF.set_default('min_microversion',
+ '2.5', group='compute-feature-enabled')
+ cfg.CONF.set_default('max_microversion',
+ '2.1', group='compute-feature-enabled')
+ self.assertRaises(exceptions.InvalidConfiguration,
+ VersionTestNoneTolatest.skip_checks)
+
+ def test_config_version_invalid_test_version(self):
+ cfg.CONF.set_default('min_microversion',
+ None, group='compute-feature-enabled')
+ cfg.CONF.set_default('max_microversion',
+ '2.13', group='compute-feature-enabled')
+ self.assertRaises(exceptions.InvalidConfiguration,
+ InvalidVersionTest.skip_checks)
+
+
+class TestVersionSkipLogic(base.TestCase):
+
+ def _test_version(self, test_min_version, test_max_version,
+ cfg_min_version, cfg_max_version, expected_skip=False):
+ try:
+ api_version_utils.check_skip_with_microversion(test_min_version,
+ test_max_version,
+ cfg_min_version,
+ cfg_max_version)
+ except testtools.TestCase.skipException as e:
+ if not expected_skip:
+ raise testtools.TestCase.failureException(e.message)
+
+ def test_version_min_in_range(self):
+ self._test_version('2.2', '2.10', '2.1', '2.7')
+
+ def test_version_max_in_range(self):
+ self._test_version('2.1', '2.3', '2.2', '2.7')
+
+ def test_version_cfg_in_range(self):
+ self._test_version('2.2', '2.9', '2.3', '2.7')
+
+ def test_version_equal(self):
+ self._test_version('2.2', '2.2', '2.2', '2.2')
+
+ def test_version_below_cfg_min(self):
+ self._test_version('2.2', '2.4', '2.5', '2.7', expected_skip=True)
+
+ def test_version_above_cfg_max(self):
+ self._test_version('2.8', '2.9', '2.3', '2.7', expected_skip=True)
+
+ def test_version_min_greater_than_max(self):
+ self.assertRaises(exceptions.InvalidConfiguration,
+ self._test_version, '2.8', '2.7', '2.3', '2.7')
+
+ def test_cfg_version_min_greater_than_max(self):
+ self.assertRaises(exceptions.InvalidConfiguration,
+ self._test_version, '2.2', '2.7', '2.9', '2.7')
diff --git a/tempest/tests/common/test_dynamic_creds.py b/tempest/tests/common/test_dynamic_creds.py
index 78064a7..10acd14 100644
--- a/tempest/tests/common/test_dynamic_creds.py
+++ b/tempest/tests/common/test_dynamic_creds.py
@@ -24,6 +24,8 @@
from tempest import exceptions
from tempest.services.identity.v2.json import identity_client as \
json_iden_client
+from tempest.services.identity.v2.json import tenants_client as \
+ json_tenants_client
from tempest.services.network.json import network_client as json_network_client
from tempest.tests import base
from tempest.tests import fake_config
@@ -74,7 +76,7 @@
def _mock_tenant_create(self, id, name):
tenant_fix = self.useFixture(mockpatch.PatchObject(
- json_iden_client.IdentityClient,
+ json_tenants_client.TenantsClient,
'create_tenant',
return_value=(service_client.ResponseBody
(200, {'tenant': {'id': id, 'name': name}}))))
@@ -240,8 +242,8 @@
'tempest.services.identity.v2.json.identity_client.'
'IdentityClient.delete_user')
tenant_mock = self.patch(
- 'tempest.services.identity.v2.json.identity_client.'
- 'IdentityClient.delete_tenant')
+ 'tempest.services.identity.v2.json.tenants_client.'
+ 'TenantsClient.delete_tenant')
creds.clear_creds()
# Verify user delete calls
calls = user_mock.mock_calls
@@ -371,8 +373,8 @@
creds.get_admin_creds()
self.patch('tempest.services.identity.v2.json.identity_client.'
'IdentityClient.delete_user')
- self.patch('tempest.services.identity.v2.json.identity_client.'
- 'IdentityClient.delete_tenant')
+ self.patch('tempest.services.identity.v2.json.tenants_client.'
+ 'TenantsClient.delete_tenant')
net = mock.patch.object(creds.networks_admin_client,
'delete_network')
net_mock = net.start()
diff --git a/tempest/tests/common/test_preprov_creds.py b/tempest/tests/common/test_preprov_creds.py
index 36dd976..fd7df16 100644
--- a/tempest/tests/common/test_preprov_creds.py
+++ b/tempest/tests/common/test_preprov_creds.py
@@ -17,17 +17,17 @@
import mock
from oslo_concurrency.fixture import lockutils as lockutils_fixtures
-from oslo_concurrency import lockutils
from oslo_config import cfg
from oslotest import mockpatch
+import shutil
import six
from tempest_lib import auth
+from tempest_lib import exceptions as lib_exc
from tempest_lib.services.identity.v2 import token_client
from tempest.common import cred_provider
from tempest.common import preprov_creds
from tempest import config
-from tempest import exceptions
from tempest.tests import base
from tempest.tests import fake_config
from tempest.tests import fake_http
@@ -38,7 +38,11 @@
fixed_params = {'name': 'test class',
'identity_version': 'v2',
- 'admin_role': 'admin'}
+ 'test_accounts_file': 'fake_accounts_file',
+ 'accounts_lock_dir': 'fake_locks_dir',
+ 'admin_role': 'admin',
+ 'object_storage_operator_role': 'operator',
+ 'object_storage_reseller_admin_role': 'reseller'}
def setUp(self):
super(TestPreProvisionedCredentials, self).setUp()
@@ -77,9 +81,13 @@
self.accounts_mock = self.useFixture(mockpatch.Patch(
'tempest.common.preprov_creds.read_accounts_yaml',
return_value=self.test_accounts))
- cfg.CONF.set_default('test_accounts_file', 'fake_path', group='auth')
self.useFixture(mockpatch.Patch('os.path.isfile', return_value=True))
+ def tearDown(self):
+ super(TestPreProvisionedCredentials, self).tearDown()
+ shutil.rmtree(self.fixed_params['accounts_lock_dir'],
+ ignore_errors=True)
+
def _get_hash_list(self, accounts_list):
hash_list = []
for account in accounts_list:
@@ -147,11 +155,10 @@
with mock.patch('six.moves.builtins.open', mock.mock_open(),
create=True) as open_mock:
test_account_class._get_free_hash(hash_list)
- lock_path = os.path.join(lockutils.get_lock_path(
- preprov_creds.CONF), 'test_accounts', hash_list[0])
+ lock_path = os.path.join(self.fixed_params['accounts_lock_dir'],
+ hash_list[0])
open_mock.assert_called_once_with(lock_path, 'w')
- mkdir_path = os.path.join(
- preprov_creds.CONF.oslo_concurrency.lock_path, 'test_accounts')
+ mkdir_path = os.path.join(self.fixed_params['accounts_lock_dir'])
mkdir_mock.mock.assert_called_once_with(mkdir_path)
@mock.patch('oslo_concurrency.lockutils.lock')
@@ -165,7 +172,7 @@
**self.fixed_params)
with mock.patch('six.moves.builtins.open', mock.mock_open(),
create=True):
- self.assertRaises(exceptions.InvalidConfiguration,
+ self.assertRaises(lib_exc.InvalidCredentials,
test_account_class._get_free_hash, hash_list)
@mock.patch('oslo_concurrency.lockutils.lock')
@@ -187,9 +194,8 @@
with mock.patch('six.moves.builtins.open', mock.mock_open(),
create=True) as open_mock:
test_account_class._get_free_hash(hash_list)
- lock_path = os.path.join(
- lockutils.get_lock_path(preprov_creds.CONF),
- 'test_accounts', hash_list[3])
+ lock_path = os.path.join(self.fixed_params['accounts_lock_dir'],
+ hash_list[3])
open_mock.assert_has_calls([mock.call(lock_path, 'w')])
@mock.patch('oslo_concurrency.lockutils.lock')
@@ -204,11 +210,9 @@
remove_mock = self.useFixture(mockpatch.Patch('os.remove'))
rmdir_mock = self.useFixture(mockpatch.Patch('os.rmdir'))
test_account_class.remove_hash(hash_list[2])
- hash_path = os.path.join(lockutils.get_lock_path(preprov_creds.CONF),
- 'test_accounts',
+ hash_path = os.path.join(self.fixed_params['accounts_lock_dir'],
hash_list[2])
- lock_path = os.path.join(preprov_creds.CONF.oslo_concurrency.lock_path,
- 'test_accounts')
+ lock_path = self.fixed_params['accounts_lock_dir']
remove_mock.mock.assert_called_once_with(hash_path)
rmdir_mock.mock.assert_called_once_with(lock_path)
@@ -225,8 +229,7 @@
remove_mock = self.useFixture(mockpatch.Patch('os.remove'))
rmdir_mock = self.useFixture(mockpatch.Patch('os.rmdir'))
test_account_class.remove_hash(hash_list[2])
- hash_path = os.path.join(lockutils.get_lock_path(preprov_creds.CONF),
- 'test_accounts',
+ hash_path = os.path.join(self.fixed_params['accounts_lock_dir'],
hash_list[2])
remove_mock.mock.assert_called_once_with(hash_path)
rmdir_mock.mock.assert_not_called()
@@ -316,7 +319,7 @@
return_value=test_accounts))
test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
**self.fixed_params)
- with mock.patch('tempest.services.compute.json.networks_client.'
+ with mock.patch('tempest_lib.services.compute.networks_client.'
'NetworksClient.list_networks',
return_value={'networks': [{'name': 'network-2',
'id': 'fake-id',
diff --git a/tempest/tests/common/test_service_clients.py b/tempest/tests/common/test_service_clients.py
index 4225da8..c313071 100644
--- a/tempest/tests/common/test_service_clients.py
+++ b/tempest/tests/common/test_service_clients.py
@@ -18,14 +18,9 @@
from tempest.services.baremetal.v1.json import baremetal_client
from tempest.services.compute.json import floating_ips_client
-from tempest.services.compute.json import interfaces_client
-from tempest.services.compute.json import quota_classes_client
from tempest.services.compute.json import security_group_rules_client
from tempest.services.compute.json import server_groups_client
from tempest.services.compute.json import servers_client
-from tempest.services.compute.json import services_client
-from tempest.services.compute.json import volumes_client \
- as compute_volumes_client
from tempest.services.data_processing.v1_1 import data_processing_client
from tempest.services.database.json import flavors_client as db_flavor_client
from tempest.services.database.json import versions_client as db_version_client
@@ -38,34 +33,39 @@
from tempest.services.identity.v3.json import policy_client
from tempest.services.identity.v3.json import region_client
from tempest.services.identity.v3.json import service_client
-from tempest.services.image.v1.json import image_client
-from tempest.services.image.v2.json import image_client as image_v2_client
+from tempest.services.image.v1.json import images_client
+from tempest.services.image.v2.json import images_client as images_v2_client
from tempest.services.messaging.json import messaging_client
from tempest.services.network.json import network_client
from tempest.services.object_storage import account_client
from tempest.services.object_storage import container_client
from tempest.services.object_storage import object_client
from tempest.services.orchestration.json import orchestration_client
+from tempest.services.telemetry.json import alarming_client
from tempest.services.telemetry.json import telemetry_client
-from tempest.services.volume.json.admin import volume_hosts_client
-from tempest.services.volume.json.admin import volume_quotas_client
-from tempest.services.volume.json.admin import volume_services_client
-from tempest.services.volume.json.admin import volume_types_client
-from tempest.services.volume.json import availability_zone_client \
+from tempest.services.volume.v1.json.admin import hosts_client \
+ as volume_hosts_client
+from tempest.services.volume.v1.json.admin import quotas_client \
+ as volume_quotas_client
+from tempest.services.volume.v1.json.admin import services_client \
+ as volume_services_client
+from tempest.services.volume.v1.json.admin import types_client \
+ as volume_types_client
+from tempest.services.volume.v1.json import availability_zone_client \
as volume_az_client
-from tempest.services.volume.json import backups_client
-from tempest.services.volume.json import extensions_client \
+from tempest.services.volume.v1.json import backups_client
+from tempest.services.volume.v1.json import extensions_client \
as volume_extensions_client
-from tempest.services.volume.json import qos_client
-from tempest.services.volume.json import snapshots_client
-from tempest.services.volume.json import volumes_client
-from tempest.services.volume.v2.json.admin import volume_hosts_client \
+from tempest.services.volume.v1.json import qos_client
+from tempest.services.volume.v1.json import snapshots_client
+from tempest.services.volume.v1.json import volumes_client
+from tempest.services.volume.v2.json.admin import hosts_client \
as volume_v2_hosts_client
-from tempest.services.volume.v2.json.admin import volume_quotas_client \
+from tempest.services.volume.v2.json.admin import quotas_client \
as volume_v2_quotas_client
-from tempest.services.volume.v2.json.admin import volume_services_client \
+from tempest.services.volume.v2.json.admin import services_client \
as volume_v2_services_client
-from tempest.services.volume.v2.json.admin import volume_types_client \
+from tempest.services.volume.v2.json.admin import types_client \
as volume_v2_types_client
from tempest.services.volume.v2.json import availability_zone_client \
as volume_v2_az_client
@@ -88,13 +88,9 @@
test_clients = [
baremetal_client.BaremetalClient,
floating_ips_client.FloatingIPsClient,
- interfaces_client.InterfacesClient,
- quota_classes_client.QuotaClassesClient,
security_group_rules_client.SecurityGroupRulesClient,
server_groups_client.ServerGroupsClient,
servers_client.ServersClient,
- services_client.ServicesClient,
- compute_volumes_client.VolumesClient,
data_processing_client.DataProcessingClient,
db_flavor_client.DatabaseFlavorsClient,
db_version_client.DatabaseVersionsClient,
@@ -105,26 +101,27 @@
object_client.ObjectClient,
orchestration_client.OrchestrationClient,
telemetry_client.TelemetryClient,
+ alarming_client.AlarmingClient,
qos_client.QosSpecsClient,
- volume_hosts_client.VolumeHostsClient,
- volume_quotas_client.VolumeQuotasClient,
- volume_services_client.VolumesServicesClient,
- volume_types_client.VolumeTypesClient,
- volume_az_client.VolumeAvailabilityZoneClient,
+ volume_hosts_client.HostsClient,
+ volume_quotas_client.QuotasClient,
+ volume_services_client.ServicesClient,
+ volume_types_client.TypesClient,
+ volume_az_client.AvailabilityZoneClient,
backups_client.BackupsClient,
volume_extensions_client.ExtensionsClient,
snapshots_client.SnapshotsClient,
volumes_client.VolumesClient,
- volume_v2_hosts_client.VolumeHostsV2Client,
- volume_v2_quotas_client.VolumeQuotasV2Client,
- volume_v2_services_client.VolumesServicesV2Client,
- volume_v2_types_client.VolumeTypesV2Client,
- volume_v2_az_client.VolumeV2AvailabilityZoneClient,
- volume_v2_backups_client.BackupsClientV2,
- volume_v2_extensions_client.ExtensionsV2Client,
- volume_v2_qos_client.QosSpecsV2Client,
- volume_v2_snapshots_client.SnapshotsV2Client,
- volume_v2_volumes_client.VolumesV2Client,
+ volume_v2_hosts_client.HostsClient,
+ volume_v2_quotas_client.QuotasClient,
+ volume_v2_services_client.ServicesClient,
+ volume_v2_types_client.TypesClient,
+ volume_v2_az_client.AvailabilityZoneClient,
+ volume_v2_backups_client.BackupsClient,
+ volume_v2_extensions_client.ExtensionsClient,
+ volume_v2_qos_client.QosSpecsClient,
+ volume_v2_snapshots_client.SnapshotsClient,
+ volume_v2_volumes_client.VolumesClient,
identity_v2_identity_client.IdentityClient,
credentials_client.CredentialsClient,
endpoints_client.EndPointClient,
@@ -132,8 +129,8 @@
policy_client.PolicyClient,
region_client.RegionClient,
service_client.ServiceClient,
- image_client.ImageClient,
- image_v2_client.ImageClientV2
+ images_client.ImagesClient,
+ images_v2_client.ImagesClientV2
]
for client in test_clients:
diff --git a/tempest/tests/common/test_waiters.py b/tempest/tests/common/test_waiters.py
index 68a8295..c7cc638 100644
--- a/tempest/tests/common/test_waiters.py
+++ b/tempest/tests/common/test_waiters.py
@@ -18,7 +18,7 @@
from tempest.common import waiters
from tempest import exceptions
-from tempest.services.volume.json import volumes_client
+from tempest.services.volume.base import base_volumes_client
from tempest.tests import base
@@ -53,7 +53,7 @@
def test_wait_for_volume_status_error_restoring(self, mock_sleep):
# Tests that the wait method raises VolumeRestoreErrorException if
# the volume status is 'error_restoring'.
- client = mock.Mock(spec=volumes_client.BaseVolumesClient,
+ client = mock.Mock(spec=base_volumes_client.BaseVolumesClient,
build_interval=1)
volume1 = {'volume': {'status': 'restoring-backup'}}
volume2 = {'volume': {'status': 'error_restoring'}}
diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
index 3ff8e0d..e596aab 100644
--- a/tempest/tests/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -146,8 +146,11 @@
self._assert_exec_called_with(
"sudo ip addr add %s/%s dev %s" % (ip, '28', nic))
- def test_turn_nic_on(self):
+ def test_set_nic_state(self):
nic = 'eth0'
- self.conn.turn_nic_on(nic)
+ self.conn.set_nic_state(nic)
self._assert_exec_called_with(
'sudo ip link set %s up' % nic)
+ self.conn.set_nic_state(nic, "down")
+ self._assert_exec_called_with(
+ 'sudo ip link set %s down' % nic)
diff --git a/tempest/tests/services/compute/test_base_compute_client.py b/tempest/tests/services/compute/test_base_compute_client.py
new file mode 100644
index 0000000..13461e4
--- /dev/null
+++ b/tempest/tests/services/compute/test_base_compute_client.py
@@ -0,0 +1,72 @@
+# 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 httplib2
+import mock
+from tempest_lib.common import rest_client
+
+from tempest.services.compute.json import base as base_compute_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestClientWithoutMicroversionHeader(base.BaseComputeServiceTest):
+
+ def setUp(self):
+ super(TestClientWithoutMicroversionHeader, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = base_compute_client.BaseComputeClient(
+ fake_auth, 'compute', 'regionOne')
+
+ def test_no_microverion_header(self):
+ header = self.client.get_headers()
+ self.assertNotIn('X-OpenStack-Nova-API-Version', header)
+
+ def test_no_microverion_header_in_raw_request(self):
+ def raw_request(*args, **kwargs):
+ self.assertNotIn('X-OpenStack-Nova-API-Version', kwargs['headers'])
+ return (httplib2.Response({'status': 200}), {})
+
+ with mock.patch.object(rest_client.RestClient,
+ 'raw_request') as mock_get:
+ mock_get.side_effect = raw_request
+ self.client.get('fake_url')
+
+
+class TestClientWithMicroversionHeader(base.BaseComputeServiceTest):
+
+ def setUp(self):
+ super(TestClientWithMicroversionHeader, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = base_compute_client.BaseComputeClient(
+ fake_auth, 'compute', 'regionOne')
+ self.client.api_microversion = '2.2'
+
+ def test_microverion_header(self):
+ header = self.client.get_headers()
+ self.assertIn('X-OpenStack-Nova-API-Version', header)
+ self.assertEqual(self.client.api_microversion,
+ header['X-OpenStack-Nova-API-Version'])
+
+ def test_microverion_header_in_raw_request(self):
+ def raw_request(*args, **kwargs):
+ self.assertIn('X-OpenStack-Nova-API-Version', kwargs['headers'])
+ self.assertEqual(self.client.api_microversion,
+ kwargs['headers']['X-OpenStack-Nova-API-Version'])
+ return (httplib2.Response({'status': 200}), {})
+
+ with mock.patch.object(rest_client.RestClient,
+ 'raw_request') as mock_get:
+ mock_get.side_effect = raw_request
+ self.client.get('fake_url')
diff --git a/tempest/tests/services/compute/test_images_client.py b/tempest/tests/services/compute/test_images_client.py
deleted file mode 100644
index 1d532b7..0000000
--- a/tempest/tests/services/compute/test_images_client.py
+++ /dev/null
@@ -1,240 +0,0 @@
-# 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 images_client
-from tempest.tests import fake_auth_provider
-from tempest.tests.services.compute import base
-
-
-class TestImagesClient(base.BaseComputeServiceTest):
- # Data Dictionaries used for testing #
- FAKE_IMAGE_METADATA = {
- "list":
- {"metadata": {
- "auto_disk_config": "True",
- "Label": "Changed"
- }},
- "set_item":
- {"meta": {
- "auto_disk_config": "True"
- }},
- "show_item":
- {"meta": {
- "kernel_id": "nokernel",
- }},
- "update":
- {"metadata": {
- "kernel_id": "False",
- "Label": "UpdatedImage"
- }},
- "set":
- {"metadata": {
- "Label": "Changed",
- "auto_disk_config": "True"
- }},
- "delete_item": {}
- }
-
- FAKE_IMAGE_DATA = {
- "list":
- {"images": [
- {"id": "70a599e0-31e7-49b7-b260-868f441e862b",
- "links": [
- {"href": "http://openstack.example.com/v2/openstack" +
- "/images/70a599e0-31e7-49b7-b260-868f441e862b",
- "rel": "self"
- }
- ],
- "name": "fakeimage7"
- }]},
- "show": {"image": {
- "created": "2011-01-01T01:02:03Z",
- "id": "70a599e0-31e7-49b7-b260-868f441e862b",
- "links": [
- {
- "href": "http://openstack.example.com/v2/openstack" +
- "/images/70a599e0-31e7-49b7-b260-868f441e862b",
- "rel": "self"
- },
- ],
- "metadata": {
- "architecture": "x86_64",
- "auto_disk_config": "True",
- "kernel_id": "nokernel",
- "ramdisk_id": "nokernel"
- },
- "minDisk": 0,
- "minRam": 0,
- "name": "fakeimage7",
- "progress": 100,
- "status": "ACTIVE",
- "updated": "2011-01-01T01:02:03Z"}},
- "delete": {}
- }
- func2mock = {
- 'get': 'tempest.common.service_client.ServiceClient.get',
- 'post': 'tempest.common.service_client.ServiceClient.post',
- 'put': 'tempest.common.service_client.ServiceClient.put',
- 'delete': 'tempest.common.service_client.ServiceClient.delete'}
- # Variable definition
- FAKE_IMAGE_ID = FAKE_IMAGE_DATA['show']['image']['id']
- FAKE_CREATE_INFO = {'location': 'None'}
- FAKE_METADATA = FAKE_IMAGE_METADATA['show_item']['meta']
-
- def setUp(self):
- super(TestImagesClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = images_client.ImagesClient(fake_auth,
- "compute", "regionOne")
-
- def _test_image_operation(self, operation="delete", bytes_body=False):
- response_code = 200
- mock_operation = self.func2mock['get']
- expected_op = self.FAKE_IMAGE_DATA[operation]
- params = {"image_id": self.FAKE_IMAGE_ID}
- if operation == 'list':
- function = self.client.list_images
- elif operation == 'show':
- function = self.client.show_image
- else:
- function = self.client.delete_image
- mock_operation = self.func2mock['delete']
- response_code = 204
-
- self.check_service_client_function(
- function, mock_operation, expected_op,
- bytes_body, response_code, **params)
-
- def _test_image_metadata(self, operation="set_item", bytes_body=False):
- response_code = 200
- expected_op = self.FAKE_IMAGE_METADATA[operation]
- if operation == 'list':
- function = self.client.list_image_metadata
- mock_operation = self.func2mock['get']
- params = {"image_id": self.FAKE_IMAGE_ID}
-
- elif operation == 'set':
- function = self.client.set_image_metadata
- mock_operation = self.func2mock['put']
- params = {"image_id": "_dummy_data",
- "meta": self.FAKE_METADATA}
-
- elif operation == 'update':
- function = self.client.update_image_metadata
- mock_operation = self.func2mock['post']
- params = {"image_id": self.FAKE_IMAGE_ID,
- "meta": self.FAKE_METADATA}
-
- elif operation == 'show_item':
- mock_operation = self.func2mock['get']
- function = self.client.show_image_metadata_item
- params = {"image_id": self.FAKE_IMAGE_ID,
- "key": "123"}
-
- elif operation == 'delete_item':
- function = self.client.delete_image_metadata_item
- mock_operation = self.func2mock['delete']
- response_code = 204
- params = {"image_id": self.FAKE_IMAGE_ID,
- "key": "123"}
-
- else:
- function = self.client.set_image_metadata_item
- mock_operation = self.func2mock['put']
- params = {"image_id": self.FAKE_IMAGE_ID,
- "key": "123",
- "meta": self.FAKE_METADATA}
-
- self.check_service_client_function(
- function, mock_operation, expected_op,
- bytes_body, response_code, **params)
-
- def _test_resource_deleted(self, bytes_body=False):
- params = {"id": self.FAKE_IMAGE_ID}
- expected_op = self.FAKE_IMAGE_DATA['show']['image']
- self.useFixture(mockpatch.Patch('tempest.services.compute.json'
- '.images_client.ImagesClient.show_image',
- side_effect=lib_exc.NotFound))
- self.assertEqual(True, self.client.is_resource_deleted(**params))
- tempdata = copy.deepcopy(self.FAKE_IMAGE_DATA['show'])
- tempdata['image']['id'] = None
- self.useFixture(mockpatch.Patch('tempest.services.compute.json'
- '.images_client.ImagesClient.show_image',
- return_value=expected_op))
- self.assertEqual(False, self.client.is_resource_deleted(**params))
-
- def test_list_images_with_str_body(self):
- self._test_image_operation('list')
-
- def test_list_images_with_bytes_body(self):
- self._test_image_operation('list', True)
-
- def test_show_image_with_str_body(self):
- self._test_image_operation('show')
-
- def test_show_image_with_bytes_body(self):
- self._test_image_operation('show', True)
-
- def test_delete_image_with_str_body(self):
- self._test_image_operation('delete')
-
- def test_delete_image_with_bytes_body(self):
- self._test_image_operation('delete', True)
-
- def test_list_image_metadata_with_str_body(self):
- self._test_image_metadata('list')
-
- def test_list_image_metadata_with_bytes_body(self):
- self._test_image_metadata('list', True)
-
- def test_set_image_metadata_with_str_body(self):
- self._test_image_metadata('set')
-
- def test_set_image_metadata_with_bytes_body(self):
- self._test_image_metadata('set', True)
-
- def test_update_image_metadata_with_str_body(self):
- self._test_image_metadata('update')
-
- def test_update_image_metadata_with_bytes_body(self):
- self._test_image_metadata('update', True)
-
- def test_set_image_metadata_item_with_str_body(self):
- self._test_image_metadata()
-
- def test_set_image_metadata_item_with_bytes_body(self):
- self._test_image_metadata(bytes_body=True)
-
- def test_show_image_metadata_item_with_str_body(self):
- self._test_image_metadata('show_item')
-
- def test_show_image_metadata_item_with_bytes_body(self):
- self._test_image_metadata('show_item', True)
-
- def test_delete_image_metadata_item_with_str_body(self):
- self._test_image_metadata('delete_item')
-
- def test_delete_image_metadata_item_with_bytes_body(self):
- self._test_image_metadata('delete_item', True)
-
- def test_resource_delete_with_str_body(self):
- self._test_resource_deleted()
-
- def test_resource_delete_with_bytes_body(self):
- self._test_resource_deleted(True)
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
deleted file mode 100644
index b4af9d5..0000000
--- a/tempest/tests/services/compute/test_instance_usage_audit_log_client.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# 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 datetime
-
-from tempest_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import instance_usage_audit_log_client
-from tempest.tests.services.compute import base
-
-
-class TestInstanceUsagesAuditLogClient(base.BaseComputeServiceTest):
-
- FAKE_AUDIT_LOG = {
- "hosts_not_run": [
- "f4eb7cfd155f4574967f8b55a7faed75"
- ],
- "log": {},
- "num_hosts": 1,
- "num_hosts_done": 0,
- "num_hosts_not_run": 1,
- "num_hosts_running": 0,
- "overall_status": "0 of 1 hosts done. 0 errors.",
- "period_beginning": "2012-12-01 00:00:00",
- "period_ending": "2013-01-01 00:00:00",
- "total_errors": 0,
- "total_instances": 0
- }
-
- def setUp(self):
- super(TestInstanceUsagesAuditLogClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = (instance_usage_audit_log_client.
- InstanceUsagesAuditLogClient(fake_auth, 'compute',
- 'regionOne'))
-
- def _test_list_instance_usage_audit_logs(self, bytes_body=False):
- self.check_service_client_function(
- self.client.list_instance_usage_audit_logs,
- 'tempest.common.service_client.ServiceClient.get',
- {"instance_usage_audit_logs": self.FAKE_AUDIT_LOG},
- bytes_body)
-
- def test_list_instance_usage_audit_logs_with_str_body(self):
- self._test_list_instance_usage_audit_logs()
-
- def test_list_instance_usage_audit_logs_with_bytes_body(self):
- self._test_list_instance_usage_audit_logs(bytes_body=True)
-
- def _test_show_instance_usage_audit_log(self, bytes_body=False):
- before_time = datetime.datetime(2012, 12, 1, 0, 0)
- self.check_service_client_function(
- self.client.show_instance_usage_audit_log,
- 'tempest.common.service_client.ServiceClient.get',
- {"instance_usage_audit_log": self.FAKE_AUDIT_LOG},
- bytes_body,
- time_before=before_time)
-
- def test_show_instance_usage_audit_log_with_str_body(self):
- self._test_show_instance_usage_audit_log()
-
- def test_show_network_with_bytes_body_with_bytes_body(self):
- self._test_show_instance_usage_audit_log(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_interfaces_client.py b/tempest/tests/services/compute/test_interfaces_client.py
deleted file mode 100644
index 235585a..0000000
--- a/tempest/tests/services/compute/test_interfaces_client.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# 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 interfaces_client
-from tempest.tests import fake_auth_provider
-from tempest.tests.services.compute import base
-
-
-class TestInterfacesClient(base.BaseComputeServiceTest):
- # Data Values to be used for testing #
- FAKE_INTERFACE_DATA = {
- "fixed_ips": [{
- "ip_address": "192.168.1.1",
- "subnet_id": "f8a6e8f8-c2ec-497c-9f23-da9616de54ef"
- }],
- "mac_addr": "fa:16:3e:4c:2c:30",
- "net_id": "3cb9bc59-5699-4588-a4b1-b87f96708bc6",
- "port_id": "ce531f90-199f-48c0-816c-13e38010b442",
- "port_state": "ACTIVE"}
-
- FAKE_SHOW_DATA = {
- "interfaceAttachment": FAKE_INTERFACE_DATA}
- FAKE_LIST_DATA = {
- "interfaceAttachments": [FAKE_INTERFACE_DATA]}
-
- FAKE_SERVER_ID = "ec14c864-096e-4e27-bb8a-2c2b4dc6f3f5"
- FAKE_PORT_ID = FAKE_SHOW_DATA['interfaceAttachment']['port_id']
- func2mock = {
- 'delete': 'tempest.common.service_client.ServiceClient.delete',
- 'get': 'tempest.common.service_client.ServiceClient.get',
- 'post': 'tempest.common.service_client.ServiceClient.post'}
-
- def setUp(self):
- super(TestInterfacesClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = interfaces_client.InterfacesClient(fake_auth,
- "compute",
- "regionOne")
-
- def _test_interface_operation(self, operation="create", bytes_body=False):
- response_code = 200
- expected_op = self.FAKE_SHOW_DATA
- mock_operation = self.func2mock['get']
- params = {'server_id': self.FAKE_SERVER_ID,
- 'port_id': self.FAKE_PORT_ID}
- if operation == 'list':
- expected_op = self.FAKE_LIST_DATA
- function = self.client.list_interfaces
- params = {'server_id': self.FAKE_SERVER_ID}
- elif operation == 'show':
- function = self.client.show_interface
- elif operation == 'delete':
- expected_op = {}
- mock_operation = self.func2mock['delete']
- function = self.client.delete_interface
- response_code = 202
- else:
- function = self.client.create_interface
- mock_operation = self.func2mock['post']
-
- self.check_service_client_function(
- function, mock_operation, expected_op,
- bytes_body, response_code, **params)
-
- def test_list_interfaces_with_str_body(self):
- self._test_interface_operation('list')
-
- def test_list_interfaces_with_bytes_body(self):
- self._test_interface_operation('list', True)
-
- def test_show_interface_with_str_body(self):
- self._test_interface_operation('show')
-
- def test_show_interface_with_bytes_body(self):
- self._test_interface_operation('show', True)
-
- def test_delete_interface_with_str_body(self):
- self._test_interface_operation('delete')
-
- def test_delete_interface_with_bytes_body(self):
- self._test_interface_operation('delete', True)
-
- def test_create_interface_with_str_body(self):
- self._test_interface_operation()
-
- def test_create_interface_with_bytes_body(self):
- self._test_interface_operation(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_limits_client.py b/tempest/tests/services/compute/test_limits_client.py
deleted file mode 100644
index 733d3d1..0000000
--- a/tempest/tests/services/compute/test_limits_client.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# 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 limits_client
-from tempest.tests.services.compute import base
-
-
-class TestLimitsClient(base.BaseComputeServiceTest):
-
- def setUp(self):
- super(TestLimitsClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = limits_client.LimitsClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_show_limits(self, bytes_body=False):
- expected = {
- "limits": {
- "rate": [],
- "absolute": {
- "maxServerMeta": 128,
- "maxPersonality": 5,
- "totalServerGroupsUsed": 0,
- "maxImageMeta": 128,
- "maxPersonalitySize": 10240,
- "maxServerGroups": 10,
- "maxSecurityGroupRules": 20,
- "maxTotalKeypairs": 100,
- "totalCoresUsed": 0,
- "totalRAMUsed": 0,
- "totalInstancesUsed": 0,
- "maxSecurityGroups": 10,
- "totalFloatingIpsUsed": 0,
- "maxTotalCores": 20,
- "totalSecurityGroupsUsed": 0,
- "maxTotalFloatingIps": 10,
- "maxTotalInstances": 10,
- "maxTotalRAMSize": 51200,
- "maxServerGroupMembers": 10
- }
- }
- }
-
- self.check_service_client_function(
- self.client.show_limits,
- 'tempest.common.service_client.ServiceClient.get',
- expected,
- bytes_body)
-
- def test_show_limits_with_str_body(self):
- self._test_show_limits()
-
- def test_show_limits_with_bytes_body(self):
- self._test_show_limits(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_migrations_client.py b/tempest/tests/services/compute/test_migrations_client.py
deleted file mode 100644
index 55f2ef2..0000000
--- a/tempest/tests/services/compute/test_migrations_client.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# 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 migrations_client
-from tempest.tests.services.compute import base
-
-
-class TestMigrationsClient(base.BaseComputeServiceTest):
- FAKE_MIGRATION_INFO = {"migrations": [{
- "created_at": "2012-10-29T13:42:02",
- "dest_compute": "compute2",
- "dest_host": "1.2.3.4",
- "dest_node": "node2",
- "id": 1234,
- "instance_uuid": "e9e4fdd7-f956-44ff-bfeb-d654a96ab3a2",
- "new_instance_type_id": 2,
- "old_instance_type_id": 1,
- "source_compute": "compute1",
- "source_node": "node1",
- "status": "finished",
- "updated_at": "2012-10-29T13:42:02"}]}
-
- def setUp(self):
- super(TestMigrationsClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.mg_client_obj = migrations_client.MigrationsClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_list_migrations(self, bytes_body=False):
- self.check_service_client_function(
- self.mg_client_obj.list_migrations,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_MIGRATION_INFO,
- bytes_body)
-
- def test_list_migration_with_str_body(self):
- self._test_list_migrations()
-
- def test_list_migration_with_bytes_body(self):
- self._test_list_migrations(True)
diff --git a/tempest/tests/services/compute/test_networks_client.py b/tempest/tests/services/compute/test_networks_client.py
deleted file mode 100644
index cec8262..0000000
--- a/tempest/tests/services/compute/test_networks_client.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# 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 networks_client
-from tempest.tests.services.compute import base
-
-
-class TestNetworksClient(base.BaseComputeServiceTest):
-
- FAKE_NETWORK = {
- "bridge": None,
- "vpn_public_port": None,
- "dhcp_start": None,
- "bridge_interface": None,
- "share_address": None,
- "updated_at": None,
- "id": "34d5ae1e-5659-49cf-af80-73bccd7d7ad3",
- "cidr_v6": None,
- "deleted_at": None,
- "gateway": None,
- "rxtx_base": None,
- "label": u'30d7',
- "priority": None,
- "project_id": None,
- "vpn_private_address": None,
- "deleted": None,
- "vlan": None,
- "broadcast": None,
- "netmask": None,
- "injected": None,
- "cidr": None,
- "vpn_public_address": None,
- "multi_host": None,
- "enable_dhcp": None,
- "dns2": None,
- "created_at": None,
- "host": None,
- "mtu": None,
- "gateway_v6": None,
- "netmask_v6": None,
- "dhcp_server": None,
- "dns1": None
- }
-
- network_id = "34d5ae1e-5659-49cf-af80-73bccd7d7ad3"
-
- FAKE_NETWORKS = [FAKE_NETWORK]
-
- def setUp(self):
- super(TestNetworksClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = networks_client.NetworksClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_list_networks(self, bytes_body=False):
- fake_list = {"networks": self.FAKE_NETWORKS}
- self.check_service_client_function(
- self.client.list_networks,
- 'tempest.common.service_client.ServiceClient.get',
- fake_list,
- bytes_body)
-
- def test_list_networks_with_str_body(self):
- self._test_list_networks()
-
- def test_list_networks_with_bytes_body(self):
- self._test_list_networks(bytes_body=True)
-
- def _test_show_network(self, bytes_body=False):
- self.check_service_client_function(
- self.client.show_network,
- 'tempest.common.service_client.ServiceClient.get',
- {"network": self.FAKE_NETWORK},
- bytes_body,
- network_id=self.network_id
- )
-
- def test_show_network_with_str_body(self):
- self._test_show_network()
-
- def test_show_network_with_bytes_body(self):
- self._test_show_network(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_quota_classes_client.py b/tempest/tests/services/compute/test_quota_classes_client.py
deleted file mode 100644
index 29800a2..0000000
--- a/tempest/tests/services/compute/test_quota_classes_client.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# 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 tempest_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import quota_classes_client
-from tempest.tests.services.compute import base
-
-
-class TestQuotaClassesClient(base.BaseComputeServiceTest):
-
- FAKE_QUOTA_CLASS_SET = {
- "injected_file_content_bytes": 10240,
- "metadata_items": 128,
- "server_group_members": 10,
- "server_groups": 10,
- "ram": 51200,
- "floating_ips": 10,
- "key_pairs": 100,
- "id": u'\u2740(*\xb4\u25e1`*)\u2740',
- "instances": 10,
- "security_group_rules": 20,
- "security_groups": 10,
- "injected_files": 5,
- "cores": 20,
- "fixed_ips": -1,
- "injected_file_path_bytes": 255,
- }
-
- def setUp(self):
- super(TestQuotaClassesClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = quota_classes_client.QuotaClassesClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_show_quota_class_set(self, bytes_body=False):
- fake_body = {'quota_class_set': self.FAKE_QUOTA_CLASS_SET}
- self.check_service_client_function(
- self.client.show_quota_class_set,
- 'tempest.common.service_client.ServiceClient.get',
- fake_body,
- bytes_body,
- quota_class_id="test")
-
- def test_show_quota_class_set_with_str_body(self):
- self._test_show_quota_class_set()
-
- def test_show_quota_class_set_with_bytes_body(self):
- self._test_show_quota_class_set(bytes_body=True)
-
- def test_update_quota_class_set(self):
- fake_quota_class_set = copy.deepcopy(self.FAKE_QUOTA_CLASS_SET)
- fake_quota_class_set.pop("id")
- fake_body = {'quota_class_set': fake_quota_class_set}
- self.check_service_client_function(
- self.client.update_quota_class_set,
- 'tempest.common.service_client.ServiceClient.put',
- fake_body,
- quota_class_id="test")
diff --git a/tempest/tests/services/compute/test_quotas_client.py b/tempest/tests/services/compute/test_quotas_client.py
deleted file mode 100644
index 9a9d8fe..0000000
--- a/tempest/tests/services/compute/test_quotas_client.py
+++ /dev/null
@@ -1,93 +0,0 @@
-# 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 tempest_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import quotas_client
-from tempest.tests.services.compute import base
-
-
-class TestQuotasClient(base.BaseComputeServiceTest):
-
- FAKE_QUOTA_SET = {
- "quota_set": {
- "injected_file_content_bytes": 10240,
- "metadata_items": 128,
- "server_group_members": 10,
- "server_groups": 10,
- "ram": 51200,
- "floating_ips": 10,
- "key_pairs": 100,
- "id": "8421f7be61064f50b680465c07f334af",
- "instances": 10,
- "security_group_rules": 20,
- "injected_files": 5,
- "cores": 20,
- "fixed_ips": -1,
- "injected_file_path_bytes": 255,
- "security_groups": 10}
- }
-
- project_id = "8421f7be61064f50b680465c07f334af"
-
- def setUp(self):
- super(TestQuotasClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = quotas_client.QuotasClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_show_quota_set(self, bytes_body=False):
- self.check_service_client_function(
- self.client.show_quota_set,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_QUOTA_SET,
- to_utf=bytes_body,
- tenant_id=self.project_id)
-
- def test_show_quota_set_with_str_body(self):
- self._test_show_quota_set()
-
- def test_show_quota_set_with_bytes_body(self):
- self._test_show_quota_set(bytes_body=True)
-
- def _test_show_default_quota_set(self, bytes_body=False):
- self.check_service_client_function(
- self.client.show_default_quota_set,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_QUOTA_SET,
- to_utf=bytes_body,
- tenant_id=self.project_id)
-
- def test_show_default_quota_set_with_str_body(self):
- self._test_show_quota_set()
-
- def test_show_default_quota_set_with_bytes_body(self):
- self._test_show_quota_set(bytes_body=True)
-
- def test_update_quota_set(self):
- fake_quota_set = copy.deepcopy(self.FAKE_QUOTA_SET)
- fake_quota_set['quota_set'].pop("id")
- self.check_service_client_function(
- self.client.update_quota_set,
- 'tempest.common.service_client.ServiceClient.put',
- fake_quota_set,
- tenant_id=self.project_id)
-
- def test_delete_quota_set(self):
- self.check_service_client_function(
- self.client.delete_quota_set,
- 'tempest.common.service_client.ServiceClient.delete',
- {}, status=202, tenant_id=self.project_id)
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
deleted file mode 100644
index 99ab305..0000000
--- a/tempest/tests/services/compute/test_security_group_default_rules_client.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# 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_groups_client.py b/tempest/tests/services/compute/test_security_groups_client.py
deleted file mode 100644
index 9e40b96..0000000
--- a/tempest/tests/services/compute/test_security_groups_client.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# 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 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.services.compute import base
-
-
-class TestSecurityGroupsClient(base.BaseComputeServiceTest):
-
- FAKE_SECURITY_GROUP_INFO = [{
- "description": "default",
- "id": "3fb26eb3-581b-4420-9963-b0879a026506",
- "name": "default",
- "rules": [],
- "tenant_id": "openstack"
- }]
-
- def setUp(self):
- super(TestSecurityGroupsClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = security_groups_client.SecurityGroupsClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_list_security_groups(self, bytes_body=False):
- self.check_service_client_function(
- self.client.list_security_groups,
- 'tempest.common.service_client.ServiceClient.get',
- {"security_groups": self.FAKE_SECURITY_GROUP_INFO},
- to_utf=bytes_body)
-
- def test_list_security_groups_with_str_body(self):
- self._test_list_security_groups()
-
- def test_list_security_groups_with_bytes_body(self):
- self._test_list_security_groups(bytes_body=True)
-
- def _test_show_security_group(self, bytes_body=False):
- self.check_service_client_function(
- self.client.show_security_group,
- 'tempest.common.service_client.ServiceClient.get',
- {"security_group": self.FAKE_SECURITY_GROUP_INFO[0]},
- to_utf=bytes_body,
- security_group_id='fake-id')
-
- def test_show_security_group_with_str_body(self):
- self._test_show_security_group()
-
- def test_show_security_group_with_bytes_body(self):
- self._test_show_security_group(bytes_body=True)
-
- def _test_create_security_group(self, bytes_body=False):
- post_body = {"name": "test", "description": "test_group"}
- self.check_service_client_function(
- self.client.create_security_group,
- 'tempest.common.service_client.ServiceClient.post',
- {"security_group": self.FAKE_SECURITY_GROUP_INFO[0]},
- to_utf=bytes_body,
- kwargs=post_body)
-
- def test_create_security_group_with_str_body(self):
- self._test_create_security_group()
-
- def test_create_security_group_with_bytes_body(self):
- self._test_create_security_group(bytes_body=True)
-
- def _test_update_security_group(self, bytes_body=False):
- req_body = {"name": "test", "description": "test_group"}
- self.check_service_client_function(
- self.client.update_security_group,
- 'tempest.common.service_client.ServiceClient.put',
- {"security_group": self.FAKE_SECURITY_GROUP_INFO[0]},
- to_utf=bytes_body,
- security_group_id='fake-id',
- kwargs=req_body)
-
- def test_update_security_group_with_str_body(self):
- self._test_update_security_group()
-
- def test_update_security_group_with_bytes_body(self):
- self._test_update_security_group(bytes_body=True)
-
- def test_delete_security_group(self):
- self.check_service_client_function(
- self.client.delete_security_group,
- 'tempest.common.service_client.ServiceClient.delete',
- {}, status=202, security_group_id='fake-id')
-
- def test_is_resource_deleted_true(self):
- mod = ('tempest.services.compute.json.security_groups_client.'
- 'SecurityGroupsClient.show_security_group')
- self.useFixture(mockpatch.Patch(mod, side_effect=lib_exc.NotFound))
- self.assertTrue(self.client.is_resource_deleted('fake-id'))
-
- def test_is_resource_deleted_false(self):
- mod = ('tempest.services.compute.json.security_groups_client.'
- 'SecurityGroupsClient.show_security_group')
- self.useFixture(mockpatch.Patch(mod, return_value='success'))
- self.assertFalse(self.client.is_resource_deleted('fake-id'))
diff --git a/tempest/tests/services/compute/test_servers_client.py b/tempest/tests/services/compute/test_servers_client.py
index e347cf1..1fd0740 100644
--- a/tempest/tests/services/compute/test_servers_client.py
+++ b/tempest/tests/services/compute/test_servers_client.py
@@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
from tempest.services.compute.json import servers_client
from tempest.tests import fake_auth_provider
from tempest.tests.services.compute import base
@@ -34,6 +35,24 @@
"name": u"new\u1234-server-test"}]
}
+ FAKE_SERVER_DIAGNOSTICS = {
+ "cpu0_time": 17300000000,
+ "memory": 524288,
+ "vda_errors": -1,
+ "vda_read": 262144,
+ "vda_read_req": 112,
+ "vda_write": 5778432,
+ "vda_write_req": 488,
+ "vnet1_rx": 2070139,
+ "vnet1_rx_drop": 0,
+ "vnet1_rx_errors": 0,
+ "vnet1_rx_packets": 26701,
+ "vnet1_tx": 140208,
+ "vnet1_tx_drop": 0,
+ "vnet1_tx_errors": 0,
+ "vnet1_tx_packets": 662
+ }
+
FAKE_SERVER_GET = {'server': {
"accessIPv4": "",
"accessIPv6": "",
@@ -116,6 +135,48 @@
]}
}
+ FAKE_COMMON_VOLUME = {
+ "id": "a6b0875b-6b5d-4a5a-81eb-0c3aa62e5fdb",
+ "device": "fake-device",
+ "volumeId": "a6b0875b-46ca-475e-917e-0c3aa62e5fdb",
+ "serverId": "616fb98f-46ca-475e-917e-2563e5a8cd19"
+ }
+
+ FAKE_VIRTUAL_INTERFACES = {
+ "id": "a6b0875b-46ca-475e-917e-0c3aa62e5fdb",
+ "mac_address": "00:25:90:5b:f8:c3",
+ "OS-EXT-VIF-NET:net_id": "fake-os-net-id"
+ }
+
+ FAKE_INSTANCE_ACTIONS = {
+ "action": "fake-action",
+ "request_id": "16fb98f-46ca-475e-917e-2563e5a8cd19",
+ "user_id": "16fb98f-46ca-475e-917e-2563e5a8cd12",
+ "project_id": "16fb98f-46ca-475e-917e-2563e5a8cd34",
+ "start_time": "09MAR2015 11:15",
+ "message": "fake-msg",
+ "instance_uuid": "16fb98f-46ca-475e-917e-2563e5a8cd12"
+ }
+
+ FAKE_VNC_CONSOLE = {
+ "type": "fake-type",
+ "url": "http://os.co/v2/616fb98f-46ca-475e-917e-2563e5a8cd19"
+ }
+
+ FAKE_INSTANCE_ACTION_EVENTS = {
+ "event": "fake-event",
+ "start_time": "09MAR2015 11:15",
+ "finish_time": "09MAR2015 11:15",
+ "result": "fake-result",
+ "traceback": "fake-trace-back"
+ }
+
+ FAKE_INSTANCE_WITH_EVENTS = copy.deepcopy(FAKE_INSTANCE_ACTIONS)
+ FAKE_INSTANCE_WITH_EVENTS['events'] = [FAKE_INSTANCE_ACTION_EVENTS]
+
+ FAKE_REBUILD_SERVER = copy.deepcopy(FAKE_SERVER_GET)
+ FAKE_REBUILD_SERVER['server']['adminPass'] = 'fake-admin-pass'
+
server_id = FAKE_SERVER_GET['server']['id']
network_id = 'a6b0875b-6b5d-4a5a-81eb-0c3aa62e5fdb'
@@ -206,7 +267,733 @@
self.client.list_addresses_by_network,
'tempest.common.service_client.ServiceClient.get',
self.FAKE_ADDRESS['addresses'],
- bytes_body,
server_id=self.server_id,
network_id=self.network_id
)
+
+ def test_action_with_str_body(self):
+ self._test_action()
+
+ def test_action_with_bytes_body(self):
+ self._test_action(True)
+
+ def _test_action(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.action,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ server_id=self.server_id,
+ action_name='fake-action-name',
+ schema={'status_code': 200}
+ )
+
+ def test_create_backup_with_str_body(self):
+ self._test_create_backup()
+
+ def test_create_backup_with_bytes_body(self):
+ self._test_create_backup(True)
+
+ def _test_create_backup(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.create_backup,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id,
+ backup_type='fake-backup',
+ rotation='fake-rotation',
+ name='fake-name'
+ )
+
+ def test_change_password_with_str_body(self):
+ self._test_change_password()
+
+ def test_change_password_with_bytes_body(self):
+ self._test_change_password(True)
+
+ def _test_change_password(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.change_password,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id,
+ adminPass='fake-admin-pass'
+ )
+
+ def test_show_password_with_str_body(self):
+ self._test_show_password()
+
+ def test_show_password_with_bytes_body(self):
+ self._test_show_password(True)
+
+ def _test_show_password(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_password,
+ 'tempest.common.service_client.ServiceClient.get',
+ {'password': 'fake-password'},
+ server_id=self.server_id
+ )
+
+ def test_delete_password_with_str_body(self):
+ self._test_delete_password()
+
+ def test_delete_password_with_bytes_body(self):
+ self._test_delete_password(True)
+
+ def _test_delete_password(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.delete_password,
+ 'tempest.common.service_client.ServiceClient.delete',
+ {},
+ status=204,
+ server_id=self.server_id
+ )
+
+ def test_reboot_server_with_str_body(self):
+ self._test_reboot_server()
+
+ def test_reboot_server_with_bytes_body(self):
+ self._test_reboot_server(True)
+
+ def _test_reboot_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.reboot_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id,
+ type='fake-reboot-type'
+ )
+
+ def test_rebuild_server_with_str_body(self):
+ self._test_rebuild_server()
+
+ def test_rebuild_server_with_bytes_body(self):
+ self._test_rebuild_server(True)
+
+ def _test_rebuild_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.rebuild_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ self.FAKE_REBUILD_SERVER,
+ status=202,
+ server_id=self.server_id,
+ image_ref='fake-image-ref'
+ )
+
+ def test_resize_server_with_str_body(self):
+ self._test_resize_server()
+
+ def test_resize_server_with_bytes_body(self):
+ self._test_resize_server(True)
+
+ def _test_resize_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.resize_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id,
+ flavor_ref='fake-flavor-ref'
+ )
+
+ def test_confirm_resize_server_with_str_body(self):
+ self._test_confirm_resize_server()
+
+ def test_confirm_resize_server_with_bytes_body(self):
+ self._test_confirm_resize_server(True)
+
+ def _test_confirm_resize_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.confirm_resize_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=204,
+ server_id=self.server_id
+ )
+
+ def test_revert_resize_server_with_str_body(self):
+ self._test_revert_resize()
+
+ def test_revert_resize_server_with_bytes_body(self):
+ self._test_revert_resize(True)
+
+ def _test_revert_resize(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.revert_resize_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_list_server_metadata_with_str_body(self):
+ self._test_list_server_metadata()
+
+ def test_list_server_metadata_with_bytes_body(self):
+ self._test_list_server_metadata()
+
+ def _test_list_server_metadata(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_server_metadata,
+ 'tempest.common.service_client.ServiceClient.get',
+ {'metadata': {'fake-key': 'fake-meta-data'}},
+ server_id=self.server_id
+ )
+
+ def test_set_server_metadata_with_str_body(self):
+ self._test_set_server_metadata()
+
+ def test_set_server_metadata_with_bytes_body(self):
+ self._test_set_server_metadata(True)
+
+ def _test_set_server_metadata(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.set_server_metadata,
+ 'tempest.common.service_client.ServiceClient.put',
+ {'metadata': {'fake-key': 'fake-meta-data'}},
+ server_id=self.server_id,
+ meta='fake-meta'
+ )
+
+ def test_update_server_metadata_with_str_body(self):
+ self._test_update_server_metadata()
+
+ def test_update_server_metadata_with_bytes_body(self):
+ self._test_update_server_metadata(True)
+
+ def _test_update_server_metadata(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.update_server_metadata,
+ 'tempest.common.service_client.ServiceClient.post',
+ {'metadata': {'fake-key': 'fake-meta-data'}},
+ server_id=self.server_id,
+ meta='fake-meta'
+ )
+
+ def test_show_server_metadata_item_with_str_body(self):
+ self._test_show_server_metadata()
+
+ def test_show_server_metadata_item_with_bytes_body(self):
+ self._test_show_server_metadata(True)
+
+ def _test_show_server_metadata(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_server_metadata_item,
+ 'tempest.common.service_client.ServiceClient.get',
+ {'meta': {'fake-key': 'fake-meta-data'}},
+ server_id=self.server_id,
+ key='fake-key'
+ )
+
+ def test_set_server_metadata_item_with_str_body(self):
+ self._test_set_server_metadata_item()
+
+ def test_set_server_metadata_item_with_bytes_body(self):
+ self._test_set_server_metadata_item(True)
+
+ def _test_set_server_metadata_item(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.set_server_metadata_item,
+ 'tempest.common.service_client.ServiceClient.put',
+ {'meta': {'fake-key': 'fake-meta-data'}},
+ server_id=self.server_id,
+ key='fake-key',
+ meta='fake-meta'
+ )
+
+ def test_delete_server_metadata_item_with_str_body(self):
+ self._test_delete_server_metadata()
+
+ def test_delete_server_metadata_item_with_bytes_body(self):
+ self._test_delete_server_metadata(True)
+
+ def _test_delete_server_metadata(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.delete_server_metadata_item,
+ 'tempest.common.service_client.ServiceClient.delete',
+ {},
+ status=204,
+ server_id=self.server_id,
+ key='fake-key'
+ )
+
+ def test_stop_server_with_str_body(self):
+ self._test_stop_server()
+
+ def test_stop_server_with_bytes_body(self):
+ self._test_stop_server(True)
+
+ def _test_stop_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.stop_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_start_server_with_str_body(self):
+ self._test_start_server()
+
+ def test_start_server_with_bytes_body(self):
+ self._test_start_server(True)
+
+ def _test_start_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.start_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_attach_volume_with_str_body(self):
+ self._test_attach_volume_server()
+
+ def test_attach_volume_with_bytes_body(self):
+ self._test_attach_volume_server(True)
+
+ def _test_attach_volume_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.attach_volume,
+ 'tempest.common.service_client.ServiceClient.post',
+ {'volumeAttachment': self.FAKE_COMMON_VOLUME},
+ server_id=self.server_id
+ )
+
+ def test_detach_volume_with_str_body(self):
+ self._test_detach_volume_server()
+
+ def test_detach_volume_with_bytes_body(self):
+ self._test_detach_volume_server(True)
+
+ def _test_detach_volume_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.detach_volume,
+ 'tempest.common.service_client.ServiceClient.delete',
+ {},
+ status=202,
+ server_id=self.server_id,
+ volume_id=self.FAKE_COMMON_VOLUME['volumeId']
+ )
+
+ def test_show_volume_attachment_with_str_body(self):
+ self._test_show_volume_attachment()
+
+ def test_show_volume_attachment_with_bytes_body(self):
+ self._test_show_volume_attachment(True)
+
+ def _test_show_volume_attachment(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_volume_attachment,
+ 'tempest.common.service_client.ServiceClient.get',
+ {'volumeAttachment': self.FAKE_COMMON_VOLUME},
+ server_id=self.server_id,
+ attach_id='fake-attach-id'
+ )
+
+ def test_list_volume_attachments_with_str_body(self):
+ self._test_list_volume_attachments()
+
+ def test_list_volume_attachments_with_bytes_body(self):
+ self._test_list_volume_attachments(True)
+
+ def _test_list_volume_attachments(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_volume_attachments,
+ 'tempest.common.service_client.ServiceClient.get',
+ {'volumeAttachments': [self.FAKE_COMMON_VOLUME]},
+ server_id=self.server_id
+ )
+
+ def test_add_security_group_with_str_body(self):
+ self._test_add_security_group()
+
+ def test_add_security_group_with_bytes_body(self):
+ self._test_add_security_group(True)
+
+ def _test_add_security_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.add_security_group,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id,
+ name='fake-name'
+ )
+
+ def test_remove_security_group_with_str_body(self):
+ self._test_remove_security_group()
+
+ def test_remove_security_group_with_bytes_body(self):
+ self._test_remove_security_group(True)
+
+ def _test_remove_security_group(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.remove_security_group,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id,
+ name='fake-name'
+ )
+
+ def test_live_migrate_server_with_str_body(self):
+ self._test_live_migrate_server()
+
+ def test_live_migrate_server_with_bytes_body(self):
+ self._test_live_migrate_server(True)
+
+ def _test_live_migrate_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.live_migrate_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_migrate_server_with_str_body(self):
+ self._test_migrate_server()
+
+ def test_migrate_server_with_bytes_body(self):
+ self._test_migrate_server(True)
+
+ def _test_migrate_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.migrate_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_lock_server_with_str_body(self):
+ self._test_lock_server()
+
+ def test_lock_server_with_bytes_body(self):
+ self._test_lock_server(True)
+
+ def _test_lock_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.lock_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_unlock_server_with_str_body(self):
+ self._test_unlock_server()
+
+ def test_unlock_server_with_bytes_body(self):
+ self._test_unlock_server(True)
+
+ def _test_unlock_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.unlock_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_suspend_server_with_str_body(self):
+ self._test_suspend_server()
+
+ def test_suspend_server_with_bytes_body(self):
+ self._test_suspend_server(True)
+
+ def _test_suspend_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.suspend_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_resume_server_with_str_body(self):
+ self._test_resume_server()
+
+ def test_resume_server_with_bytes_body(self):
+ self._test_resume_server(True)
+
+ def _test_resume_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.resume_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_pause_server_with_str_body(self):
+ self._test_pause_server()
+
+ def test_pause_server_with_bytes_body(self):
+ self._test_pause_server(True)
+
+ def _test_pause_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.pause_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_unpause_server_with_str_body(self):
+ self._test_unpause_server()
+
+ def test_unpause_server_with_bytes_body(self):
+ self._test_unpause_server(True)
+
+ def _test_unpause_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.unpause_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_reset_state_with_str_body(self):
+ self._test_reset_state()
+
+ def test_reset_state_with_bytes_body(self):
+ self._test_reset_state(True)
+
+ def _test_reset_state(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.reset_state,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id,
+ state='fake-state'
+ )
+
+ def test_shelve_server_with_str_body(self):
+ self._test_shelve_server()
+
+ def test_shelve_server_with_bytes_body(self):
+ self._test_shelve_server(True)
+
+ def _test_shelve_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.shelve_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_unshelve_server_with_str_body(self):
+ self._test_unshelve_server()
+
+ def test_unshelve_server_with_bytes_body(self):
+ self._test_unshelve_server(True)
+
+ def _test_unshelve_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.unshelve_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_shelve_offload_server_with_str_body(self):
+ self._test_shelve_offload_server()
+
+ def test_shelve_offload_server_with_bytes_body(self):
+ self._test_shelve_offload_server(True)
+
+ def _test_shelve_offload_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.shelve_offload_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_get_console_output_with_str_body(self):
+ self._test_get_console_output()
+
+ def test_get_console_output_with_bytes_body(self):
+ self._test_get_console_output(True)
+
+ def _test_get_console_output(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.get_console_output,
+ 'tempest.common.service_client.ServiceClient.post',
+ {'output': 'fake-output'},
+ server_id=self.server_id,
+ length='fake-length'
+ )
+
+ def test_list_virtual_interfaces_with_str_body(self):
+ self._test_list_virtual_interfaces()
+
+ def test_list_virtual_interfaces_with_bytes_body(self):
+ self._test_list_virtual_interfaces(True)
+
+ def _test_list_virtual_interfaces(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_virtual_interfaces,
+ 'tempest.common.service_client.ServiceClient.get',
+ {'virtual_interfaces': [self.FAKE_VIRTUAL_INTERFACES]},
+ server_id=self.server_id
+ )
+
+ def test_rescue_server_with_str_body(self):
+ self._test_rescue_server()
+
+ def test_rescue_server_with_bytes_body(self):
+ self._test_rescue_server(True)
+
+ def _test_rescue_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.rescue_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {'adminPass': 'fake-admin-pass'},
+ server_id=self.server_id
+ )
+
+ def test_unrescue_server_with_str_body(self):
+ self._test_unrescue_server()
+
+ def test_unrescue_server_with_bytes_body(self):
+ self._test_unrescue_server(True)
+
+ def _test_unrescue_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.unrescue_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_show_server_diagnostics_with_str_body(self):
+ self._test_show_server_diagnostics()
+
+ def test_show_server_diagnostics_with_bytes_body(self):
+ self._test_show_server_diagnostics(True)
+
+ def _test_show_server_diagnostics(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_server_diagnostics,
+ 'tempest.common.service_client.ServiceClient.get',
+ self.FAKE_SERVER_DIAGNOSTICS,
+ status=200,
+ server_id=self.server_id
+ )
+
+ def test_list_instance_actions_with_str_body(self):
+ self._test_list_instance_actions()
+
+ def test_list_instance_actions_with_bytes_body(self):
+ self._test_list_instance_actions(True)
+
+ def _test_list_instance_actions(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_instance_actions,
+ 'tempest.common.service_client.ServiceClient.get',
+ {'instanceActions': [self.FAKE_INSTANCE_ACTIONS]},
+ server_id=self.server_id
+ )
+
+ def test_show_instance_action_with_str_body(self):
+ self._test_show_instance_action()
+
+ def test_show_instance_action_with_bytes_body(self):
+ self._test_show_instance_action(True)
+
+ def _test_show_instance_action(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.show_instance_action,
+ 'tempest.common.service_client.ServiceClient.get',
+ {'instanceAction': self.FAKE_INSTANCE_WITH_EVENTS},
+ server_id=self.server_id,
+ request_id='fake-request-id'
+ )
+
+ def test_force_delete_server_with_str_body(self):
+ self._test_force_delete_server()
+
+ def test_force_delete_server_with_bytes_body(self):
+ self._test_force_delete_server(True)
+
+ def _test_force_delete_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.force_delete_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_restore_soft_deleted_server_with_str_body(self):
+ self._test_restore_soft_deleted_server()
+
+ def test_restore_soft_deleted_server_with_bytes_body(self):
+ self._test_restore_soft_deleted_server(True)
+
+ def _test_restore_soft_deleted_server(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.restore_soft_deleted_server,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_reset_network_with_str_body(self):
+ self._test_reset_network()
+
+ def test_reset_network_with_bytes_body(self):
+ self._test_reset_network(True)
+
+ def _test_reset_network(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.reset_network,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_inject_network_info_with_str_body(self):
+ self._test_inject_network_info()
+
+ def test_inject_network_info_with_bytes_body(self):
+ self._test_inject_network_info(True)
+
+ def _test_inject_network_info(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.inject_network_info,
+ 'tempest.common.service_client.ServiceClient.post',
+ {},
+ status=202,
+ server_id=self.server_id
+ )
+
+ def test_get_vnc_console_with_str_body(self):
+ self._test_get_vnc_console()
+
+ def test_get_vnc_console_with_bytes_body(self):
+ self._test_get_vnc_console(True)
+
+ def _test_get_vnc_console(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.get_vnc_console,
+ 'tempest.common.service_client.ServiceClient.post',
+ {'console': self.FAKE_VNC_CONSOLE},
+ server_id=self.server_id,
+ type='fake-console-type'
+ )
diff --git a/tempest/tests/services/compute/test_services_client.py b/tempest/tests/services/compute/test_services_client.py
deleted file mode 100644
index fce28e8..0000000
--- a/tempest/tests/services/compute/test_services_client.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# 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 tempest_lib.tests import fake_auth_provider
-
-from tempest.services.compute.json import services_client
-from tempest.tests.services.compute import base
-
-
-class TestServicesClient(base.BaseComputeServiceTest):
-
- FAKE_SERVICES = {
- "services":
- [{
- "status": "enabled",
- "binary": "nova-conductor",
- "zone": "internal",
- "state": "up",
- "updated_at": "2015-08-19T06:50:55.000000",
- "host": "controller",
- "disabled_reason": None,
- "id": 1
- }]
- }
-
- FAKE_SERVICE = {
- "service":
- {
- "status": "enabled",
- "binary": "nova-conductor",
- "host": "controller"
- }
- }
-
- def setUp(self):
- super(TestServicesClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = services_client.ServicesClient(
- fake_auth, 'compute', 'regionOne')
-
- def test_list_services_with_str_body(self):
- self.check_service_client_function(
- self.client.list_services,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_SERVICES)
-
- def test_list_services_with_bytes_body(self):
- self.check_service_client_function(
- self.client.list_services,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_SERVICES, to_utf=True)
-
- def _test_enable_service(self, bytes_body=False):
- self.check_service_client_function(
- self.client.enable_service,
- 'tempest.common.service_client.ServiceClient.put',
- self.FAKE_SERVICE,
- bytes_body,
- host_name="nova-conductor", binary="controller")
-
- def test_enable_service_with_str_body(self):
- self._test_enable_service()
-
- def test_enable_service_with_bytes_body(self):
- self._test_enable_service(bytes_body=True)
-
- def _test_disable_service(self, bytes_body=False):
- fake_service = copy.deepcopy(self.FAKE_SERVICE)
- fake_service["service"]["status"] = "disable"
-
- self.check_service_client_function(
- 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_disable_service()
-
- def test_disable_service_with_bytes_body(self):
- self._test_disable_service(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_snapshots_client.py b/tempest/tests/services/compute/test_snapshots_client.py
deleted file mode 100644
index c24c6ae..0000000
--- a/tempest/tests/services/compute/test_snapshots_client.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# 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 oslotest import mockpatch
-from tempest_lib import exceptions as lib_exc
-
-from tempest.services.compute.json import snapshots_client
-from tempest.tests import fake_auth_provider
-from tempest.tests.services.compute import base
-
-
-class TestSnapshotsClient(base.BaseComputeServiceTest):
-
- FAKE_SNAPSHOT = {
- "createdAt": "2015-10-02T16:27:54.724209",
- "displayDescription": u"Another \u1234.",
- "displayName": u"v\u1234-001",
- "id": "100",
- "size": 100,
- "status": "available",
- "volumeId": "12"
- }
-
- FAKE_SNAPSHOTS = {"snapshots": [FAKE_SNAPSHOT]}
-
- def setUp(self):
- super(TestSnapshotsClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = snapshots_client.SnapshotsClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_create_snapshot(self, bytes_body=False):
- self.check_service_client_function(
- self.client.create_snapshot,
- 'tempest.common.service_client.ServiceClient.post',
- {"snapshot": self.FAKE_SNAPSHOT},
- to_utf=bytes_body, status=200,
- volume_id=self.FAKE_SNAPSHOT["volumeId"])
-
- def test_create_snapshot_with_str_body(self):
- self._test_create_snapshot()
-
- def test_create_shapshot_with_bytes_body(self):
- self._test_create_snapshot(bytes_body=True)
-
- def _test_show_snapshot(self, bytes_body=False):
- self.check_service_client_function(
- self.client.show_snapshot,
- 'tempest.common.service_client.ServiceClient.get',
- {"snapshot": self.FAKE_SNAPSHOT},
- to_utf=bytes_body, snapshot_id=self.FAKE_SNAPSHOT["id"])
-
- def test_show_snapshot_with_str_body(self):
- self._test_show_snapshot()
-
- def test_show_snapshot_with_bytes_body(self):
- self._test_show_snapshot(bytes_body=True)
-
- def _test_list_snapshots(self, bytes_body=False, **params):
- self.check_service_client_function(
- self.client.list_snapshots,
- 'tempest.common.service_client.ServiceClient.get',
- self.FAKE_SNAPSHOTS, to_utf=bytes_body, **params)
-
- def test_list_snapshots_with_str_body(self):
- self._test_list_snapshots()
-
- def test_list_snapshots_with_byte_body(self):
- self._test_list_snapshots(bytes_body=True)
-
- def test_list_snapshots_with_params(self):
- self._test_list_snapshots('fake')
-
- def test_delete_snapshot(self):
- self.check_service_client_function(
- self.client.delete_snapshot,
- 'tempest.common.service_client.ServiceClient.delete',
- {}, status=202, snapshot_id=self.FAKE_SNAPSHOT['id'])
-
- def test_is_resource_deleted_true(self):
- module = ('tempest.services.compute.json.snapshots_client.'
- 'SnapshotsClient.show_snapshot')
- 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.snapshots_client.'
- 'SnapshotsClient.show_snapshot')
- self.useFixture(mockpatch.Patch(
- module, return_value={}))
- self.assertFalse(self.client.is_resource_deleted('fake-id'))
diff --git a/tempest/tests/services/compute/test_tenant_networks_client.py b/tempest/tests/services/compute/test_tenant_networks_client.py
deleted file mode 100644
index 691792a..0000000
--- a/tempest/tests/services/compute/test_tenant_networks_client.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# 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 tenant_networks_client
-from tempest.tests.services.compute import base
-
-
-class TestTenantNetworksClient(base.BaseComputeServiceTest):
-
- FAKE_NETWORK = {
- "cidr": "None",
- "id": "c2329eb4-cc8e-4439-ac4c-932369309e36",
- "label": u'\u30d7'
- }
-
- FAKE_NETWORKS = [FAKE_NETWORK]
-
- NETWORK_ID = FAKE_NETWORK['id']
-
- def setUp(self):
- super(TestTenantNetworksClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = tenant_networks_client.TenantNetworksClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_list_tenant_networks(self, bytes_body=False):
- self.check_service_client_function(
- self.client.list_tenant_networks,
- 'tempest.common.service_client.ServiceClient.get',
- {"networks": self.FAKE_NETWORKS},
- bytes_body)
-
- def test_list_tenant_networks_with_str_body(self):
- self._test_list_tenant_networks()
-
- def test_list_tenant_networks_with_bytes_body(self):
- self._test_list_tenant_networks(bytes_body=True)
-
- def _test_show_tenant_network(self, bytes_body=False):
- self.check_service_client_function(
- self.client.show_tenant_network,
- 'tempest.common.service_client.ServiceClient.get',
- {"network": self.FAKE_NETWORK},
- bytes_body,
- network_id=self.NETWORK_ID)
-
- def test_show_tenant_network_with_str_body(self):
- self._test_show_tenant_network()
-
- def test_show_tenant_network_with_bytes_body(self):
- self._test_show_tenant_network(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_tenant_usages_client.py b/tempest/tests/services/compute/test_tenant_usages_client.py
deleted file mode 100644
index 58e0b7a..0000000
--- a/tempest/tests/services/compute/test_tenant_usages_client.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# 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 tenant_usages_client
-from tempest.tests.services.compute import base
-
-
-class TestTenantUsagesClient(base.BaseComputeServiceTest):
-
- FAKE_SERVER_USAGES = [{
- "ended_at": None,
- "flavor": "m1.tiny",
- "hours": 1.0,
- "instance_id": "1f1deceb-17b5-4c04-84c7-e0d4499c8fe0",
- "local_gb": 1,
- "memory_mb": 512,
- "name": "new-server-test",
- "started_at": "2012-10-08T20:10:44.541277",
- "state": "active",
- "tenant_id": "openstack",
- "uptime": 3600,
- "vcpus": 1
- }]
-
- FAKE_TENANT_USAGES = [{
- "server_usages": FAKE_SERVER_USAGES,
- "start": "2012-10-08T21:10:44.587336",
- "stop": "2012-10-08T22:10:44.587336",
- "tenant_id": "openstack",
- "total_hours": 1,
- "total_local_gb_usage": 1,
- "total_memory_mb_usage": 512,
- "total_vcpus_usage": 1
- }]
-
- def setUp(self):
- super(TestTenantUsagesClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = tenant_usages_client.TenantUsagesClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_list_tenant_usages(self, bytes_body=False):
- self.check_service_client_function(
- self.client.list_tenant_usages,
- 'tempest.common.service_client.ServiceClient.get',
- {"tenant_usages": self.FAKE_TENANT_USAGES},
- to_utf=bytes_body)
-
- def test_list_tenant_usages_with_str_body(self):
- self._test_list_tenant_usages()
-
- def test_list_tenant_usages_with_bytes_body(self):
- self._test_list_tenant_usages(bytes_body=True)
-
- def _test_show_tenant_usage(self, bytes_body=False):
- self.check_service_client_function(
- self.client.show_tenant_usage,
- 'tempest.common.service_client.ServiceClient.get',
- {"tenant_usage": self.FAKE_TENANT_USAGES[0]},
- to_utf=bytes_body,
- tenant_id='openstack')
-
- def test_show_tenant_usage_with_str_body(self):
- self._test_show_tenant_usage()
-
- def test_show_tenant_usage_with_bytes_body(self):
- self._test_show_tenant_usage(bytes_body=True)
diff --git a/tempest/tests/services/compute/test_volumes_client.py b/tempest/tests/services/compute/test_volumes_client.py
deleted file mode 100644
index 33d4bad..0000000
--- a/tempest/tests/services/compute/test_volumes_client.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# 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_client
-from tempest.tests import fake_auth_provider
-from tempest.tests.services.compute import base
-
-
-class TestVolumesClient(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(TestVolumesClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = volumes_client.VolumesClient(
- 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_client.'
- 'VolumesClient.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_client.'
- 'VolumesClient.show_volume')
- self.useFixture(mockpatch.Patch(
- module, return_value={}))
- self.assertFalse(self.client.is_resource_deleted('fake-id'))
diff --git a/tempest/tests/test_glance_http.py b/tempest/tests/test_glance_http.py
index 105caec..db9db34 100644
--- a/tempest/tests/test_glance_http.py
+++ b/tempest/tests/test_glance_http.py
@@ -13,14 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-import socket
-
import mock
-from oslo_serialization import jsonutils as json
from oslotest import mockpatch
import six
from six.moves import http_client as httplib
-from tempest_lib import exceptions as lib_exc
from tempest.common import glance_http
from tempest import exceptions
@@ -56,60 +52,6 @@
'getresponse', return_value=resp))
return resp
- def test_json_request_without_content_type_header_in_response(self):
- self._set_response_fixture({}, 200, 'fake_response_body')
- self.assertRaises(lib_exc.InvalidContentType,
- self.client.json_request, 'GET', '/images')
-
- def test_json_request_with_xml_content_type_header_in_request(self):
- self.assertRaises(lib_exc.InvalidContentType,
- self.client.json_request, 'GET', '/images',
- headers={'Content-Type': 'application/xml'})
-
- def test_json_request_with_xml_content_type_header_in_response(self):
- self._set_response_fixture({'content-type': 'application/xml'},
- 200, 'fake_response_body')
- self.assertRaises(lib_exc.InvalidContentType,
- self.client.json_request, 'GET', '/images')
-
- def test_json_request_with_json_content_type_header_only_in_resp(self):
- self._set_response_fixture({'content-type': 'application/json'},
- 200, 'fake_response_body')
- resp, body = self.client.json_request('GET', '/images')
- self.assertEqual(200, resp.status)
- self.assertEqual('fake_response_body', body)
-
- def test_json_request_with_json_content_type_header_in_req_and_resp(self):
- self._set_response_fixture({'content-type': 'application/json'},
- 200, 'fake_response_body')
- resp, body = self.client.json_request('GET', '/images', headers={
- 'Content-Type': 'application/json'})
- self.assertEqual(200, resp.status)
- self.assertEqual('fake_response_body', body)
-
- def test_json_request_fails_to_json_loads(self):
- self._set_response_fixture({'content-type': 'application/json'},
- 200, 'fake_response_body')
- self.useFixture(mockpatch.PatchObject(json, 'loads',
- side_effect=ValueError()))
- resp, body = self.client.json_request('GET', '/images')
- self.assertEqual(200, resp.status)
- self.assertEqual(body, 'fake_response_body')
-
- def test_json_request_socket_timeout(self):
- self.useFixture(mockpatch.PatchObject(httplib.HTTPConnection,
- 'request',
- side_effect=socket.timeout()))
- self.assertRaises(exceptions.TimeoutException,
- self.client.json_request, 'GET', '/images')
-
- def test_json_request_endpoint_not_found(self):
- self.useFixture(mockpatch.PatchObject(httplib.HTTPConnection,
- 'request',
- side_effect=socket.gaierror()))
- self.assertRaises(exceptions.EndpointNotFound,
- self.client.json_request, 'GET', '/images')
-
def test_raw_request(self):
self._set_response_fixture({}, 200, 'fake_response_body')
resp, body = self.client.raw_request('GET', '/images')
@@ -141,22 +83,22 @@
self.assertEqual(call_count - 1, req_body.tell())
def test_get_connection_class_for_https(self):
- conn_class = self.client.get_connection_class('https')
+ conn_class = self.client._get_connection_class('https')
self.assertEqual(glance_http.VerifiedHTTPSConnection, conn_class)
def test_get_connection_class_for_http(self):
- conn_class = (self.client.get_connection_class('http'))
+ conn_class = (self.client._get_connection_class('http'))
self.assertEqual(httplib.HTTPConnection, conn_class)
def test_get_connection_http(self):
- self.assertTrue(isinstance(self.client.get_connection(),
+ self.assertTrue(isinstance(self.client._get_connection(),
httplib.HTTPConnection))
def test_get_connection_https(self):
endpoint = 'https://fake_url.com'
self.fake_auth.base_url = mock.MagicMock(return_value=endpoint)
self.client = glance_http.HTTPClient(self.fake_auth, {})
- self.assertTrue(isinstance(self.client.get_connection(),
+ self.assertTrue(isinstance(self.client._get_connection(),
glance_http.VerifiedHTTPSConnection))
def test_get_connection_url_not_fount(self):
@@ -164,37 +106,37 @@
side_effect=httplib.InvalidURL()
))
self.assertRaises(exceptions.EndpointNotFound,
- self.client.get_connection)
+ self.client._get_connection)
def test_get_connection_kwargs_default_for_http(self):
- kwargs = self.client.get_connection_kwargs('http')
+ kwargs = self.client._get_connection_kwargs('http')
self.assertEqual(600, kwargs['timeout'])
self.assertEqual(1, len(kwargs.keys()))
def test_get_connection_kwargs_set_timeout_for_http(self):
- kwargs = self.client.get_connection_kwargs('http', timeout=10,
- ca_certs='foo')
+ kwargs = self.client._get_connection_kwargs('http', timeout=10,
+ ca_certs='foo')
self.assertEqual(10, kwargs['timeout'])
# nothing more than timeout is evaluated for http connections
self.assertEqual(1, len(kwargs.keys()))
def test_get_connection_kwargs_default_for_https(self):
- kwargs = self.client.get_connection_kwargs('https')
+ kwargs = self.client._get_connection_kwargs('https')
self.assertEqual(600, kwargs['timeout'])
- self.assertEqual(None, kwargs['ca_certs'])
- self.assertEqual(None, kwargs['cert_file'])
- self.assertEqual(None, kwargs['key_file'])
+ self.assertIsNone(kwargs['ca_certs'])
+ self.assertIsNone(kwargs['cert_file'])
+ self.assertIsNone(kwargs['key_file'])
self.assertEqual(False, kwargs['insecure'])
self.assertEqual(True, kwargs['ssl_compression'])
self.assertEqual(6, len(kwargs.keys()))
def test_get_connection_kwargs_set_params_for_https(self):
- kwargs = self.client.get_connection_kwargs('https', timeout=10,
- ca_certs='foo',
- cert_file='/foo/bar.cert',
- key_file='/foo/key.pem',
- insecure=True,
- ssl_compression=False)
+ kwargs = self.client._get_connection_kwargs('https', timeout=10,
+ ca_certs='foo',
+ cert_file='/foo/bar.cert',
+ key_file='/foo/key.pem',
+ insecure=True,
+ ssl_compression=False)
self.assertEqual(10, kwargs['timeout'])
self.assertEqual('foo', kwargs['ca_certs'])
self.assertEqual('/foo/bar.cert', kwargs['cert_file'])
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index 49a1854..6c1b362 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -175,23 +175,23 @@
instance.add_tag('key1', value='value1')
tags = self.ec2_client.get_all_tags()
- td = {item.name: item.value for item in tags}
+ td = dict((item.name, item.value) for item in tags)
self.assertIn('key1', td)
self.assertEqual('value1', td['key1'])
tags = self.ec2_client.get_all_tags(filters={'key': 'key1'})
- td = {item.name: item.value for item in tags}
+ td = dict((item.name, item.value) for item in tags)
self.assertIn('key1', td)
self.assertEqual('value1', td['key1'])
tags = self.ec2_client.get_all_tags(filters={'value': 'value1'})
- td = {item.name: item.value for item in tags}
+ td = dict((item.name, item.value) for item in tags)
self.assertIn('key1', td)
self.assertEqual('value1', td['key1'])
tags = self.ec2_client.get_all_tags(filters={'key': 'value2'})
- td = {item.name: item.value for item in tags}
+ td = dict((item.name, item.value) for item in tags)
self.assertNotIn('key1', td)
for instance in reservation.instances:
diff --git a/test-requirements.txt b/test-requirements.txt
index db2b2ce..5b01ea9 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -5,7 +5,7 @@
# needed for doc build
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
python-subunit>=0.0.18
-oslosphinx>=2.5.0 # Apache-2.0
+oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
mox>=0.5.3
mock>=1.2
coverage>=3.6
diff --git a/tools/check_uuid.py b/tools/check_uuid.py
deleted file mode 100755
index a71ad39..0000000
--- a/tools/check_uuid.py
+++ /dev/null
@@ -1,358 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright 2014 Mirantis, Inc.
-#
-# 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 argparse
-import ast
-import importlib
-import inspect
-import os
-import sys
-import unittest
-import urllib
-import uuid
-
-DECORATOR_MODULE = 'test'
-DECORATOR_NAME = 'idempotent_id'
-DECORATOR_IMPORT = 'tempest.%s' % DECORATOR_MODULE
-IMPORT_LINE = 'from tempest import %s' % DECORATOR_MODULE
-DECORATOR_TEMPLATE = "@%s.%s('%%s')" % (DECORATOR_MODULE,
- DECORATOR_NAME)
-UNIT_TESTS_EXCLUDE = 'tempest.tests'
-
-
-class SourcePatcher(object):
-
- """"Lazy patcher for python source files"""
-
- def __init__(self):
- self.source_files = None
- self.patches = None
- self.clear()
-
- def clear(self):
- """Clear inner state"""
- self.source_files = {}
- self.patches = {}
-
- @staticmethod
- def _quote(s):
- return urllib.quote(s)
-
- @staticmethod
- def _unquote(s):
- return urllib.unquote(s)
-
- def add_patch(self, filename, patch, line_no):
- """Add lazy patch"""
- if filename not in self.source_files:
- with open(filename) as f:
- self.source_files[filename] = self._quote(f.read())
- patch_id = str(uuid.uuid4())
- if not patch.endswith('\n'):
- patch += '\n'
- self.patches[patch_id] = self._quote(patch)
- lines = self.source_files[filename].split(self._quote('\n'))
- lines[line_no - 1] = ''.join(('{%s:s}' % patch_id, lines[line_no - 1]))
- self.source_files[filename] = self._quote('\n').join(lines)
-
- def _save_changes(self, filename, source):
- print('%s fixed' % filename)
- with open(filename, 'w') as f:
- f.write(source)
-
- def apply_patches(self):
- """Apply all patches"""
- for filename in self.source_files:
- patched_source = self._unquote(
- self.source_files[filename].format(**self.patches)
- )
- self._save_changes(filename, patched_source)
- self.clear()
-
-
-class TestChecker(object):
-
- def __init__(self, package):
- self.package = package
- self.base_path = os.path.abspath(os.path.dirname(package.__file__))
-
- def _path_to_package(self, path):
- relative_path = path[len(self.base_path) + 1:]
- if relative_path:
- return '.'.join((self.package.__name__,) +
- tuple(relative_path.split('/')))
- else:
- return self.package.__name__
-
- def _modules_search(self):
- """Recursive search for python modules in base package"""
- modules = []
- for root, dirs, files in os.walk(self.base_path):
- if not os.path.exists(os.path.join(root, '__init__.py')):
- continue
- root_package = self._path_to_package(root)
- for item in files:
- if item.endswith('.py'):
- module_name = '.'.join((root_package,
- os.path.splitext(item)[0]))
- if not module_name.startswith(UNIT_TESTS_EXCLUDE):
- modules.append(module_name)
- return modules
-
- @staticmethod
- def _get_idempotent_id(test_node):
- # Return key-value dict with all metadata from @test.idempotent_id
- # decorators for test method
- idempotent_id = None
- for decorator in test_node.decorator_list:
- if (hasattr(decorator, 'func') and
- hasattr(decorator.func, 'attr') and
- decorator.func.attr == DECORATOR_NAME and
- hasattr(decorator.func, 'value') and
- decorator.func.value.id == DECORATOR_MODULE):
- for arg in decorator.args:
- idempotent_id = ast.literal_eval(arg)
- return idempotent_id
-
- @staticmethod
- def _is_decorator(line):
- return line.strip().startswith('@')
-
- @staticmethod
- def _is_def(line):
- return line.strip().startswith('def ')
-
- def _add_uuid_to_test(self, patcher, test_node, source_path):
- with open(source_path) as src:
- src_lines = src.read().split('\n')
- lineno = test_node.lineno
- insert_position = lineno
- while True:
- if (self._is_def(src_lines[lineno - 1]) or
- (self._is_decorator(src_lines[lineno - 1]) and
- (DECORATOR_TEMPLATE.split('(')[0] <=
- src_lines[lineno - 1].strip().split('(')[0]))):
- insert_position = lineno
- break
- lineno += 1
- patcher.add_patch(
- source_path,
- ' ' * test_node.col_offset + DECORATOR_TEMPLATE % uuid.uuid4(),
- insert_position
- )
-
- @staticmethod
- def _is_test_case(module, node):
- if (node.__class__ is ast.ClassDef and
- hasattr(module, node.name) and
- inspect.isclass(getattr(module, node.name))):
- return issubclass(getattr(module, node.name), unittest.TestCase)
-
- @staticmethod
- def _is_test_method(node):
- return (node.__class__ is ast.FunctionDef
- and node.name.startswith('test_'))
-
- @staticmethod
- def _next_node(body, node):
- if body.index(node) < len(body):
- return body[body.index(node) + 1]
-
- @staticmethod
- def _import_name(node):
- if type(node) == ast.Import:
- return node.names[0].name
- elif type(node) == ast.ImportFrom:
- return '%s.%s' % (node.module, node.names[0].name)
-
- def _add_import_for_test_uuid(self, patcher, src_parsed, source_path):
- with open(source_path) as f:
- src_lines = f.read().split('\n')
- line_no = 0
- tempest_imports = [node for node in src_parsed.body
- if self._import_name(node) and
- 'tempest.' in self._import_name(node)]
- if not tempest_imports:
- import_snippet = '\n'.join(('', IMPORT_LINE, ''))
- else:
- for node in tempest_imports:
- if self._import_name(node) < DECORATOR_IMPORT:
- continue
- else:
- line_no = node.lineno
- import_snippet = IMPORT_LINE
- break
- else:
- line_no = tempest_imports[-1].lineno
- while True:
- if (not src_lines[line_no - 1] or
- getattr(self._next_node(src_parsed.body,
- tempest_imports[-1]),
- 'lineno') == line_no or
- line_no == len(src_lines)):
- break
- line_no += 1
- import_snippet = '\n'.join((IMPORT_LINE, ''))
- patcher.add_patch(source_path, import_snippet, line_no)
-
- def get_tests(self):
- """Get test methods with sources from base package with metadata"""
- tests = {}
- for module_name in self._modules_search():
- tests[module_name] = {}
- module = importlib.import_module(module_name)
- source_path = '.'.join(
- (os.path.splitext(module.__file__)[0], 'py')
- )
- with open(source_path, 'r') as f:
- source = f.read()
- tests[module_name]['source_path'] = source_path
- tests[module_name]['tests'] = {}
- source_parsed = ast.parse(source)
- tests[module_name]['ast'] = source_parsed
- tests[module_name]['import_valid'] = (
- hasattr(module, DECORATOR_MODULE) and
- inspect.ismodule(getattr(module, DECORATOR_MODULE))
- )
- test_cases = (node for node in source_parsed.body
- if self._is_test_case(module, node))
- for node in test_cases:
- for subnode in filter(self._is_test_method, node.body):
- test_name = '%s.%s' % (node.name, subnode.name)
- tests[module_name]['tests'][test_name] = subnode
- return tests
-
- @staticmethod
- def _filter_tests(function, tests):
- """Filter tests with condition 'function(test_node) == True'"""
- result = {}
- for module_name in tests:
- for test_name in tests[module_name]['tests']:
- if function(module_name, test_name, tests):
- if module_name not in result:
- result[module_name] = {
- 'ast': tests[module_name]['ast'],
- 'source_path': tests[module_name]['source_path'],
- 'import_valid': tests[module_name]['import_valid'],
- 'tests': {}
- }
- result[module_name]['tests'][test_name] = \
- tests[module_name]['tests'][test_name]
- return result
-
- def find_untagged(self, tests):
- """Filter all tests without uuid in metadata"""
- def check_uuid_in_meta(module_name, test_name, tests):
- idempotent_id = self._get_idempotent_id(
- tests[module_name]['tests'][test_name])
- return not idempotent_id
- return self._filter_tests(check_uuid_in_meta, tests)
-
- def report_collisions(self, tests):
- """Reports collisions if there are any.
-
- Returns true if collisions exist.
- """
- uuids = {}
-
- def report(module_name, test_name, tests):
- test_uuid = self._get_idempotent_id(
- tests[module_name]['tests'][test_name])
- if not test_uuid:
- return
- if test_uuid in uuids:
- error_str = "%s:%s\n uuid %s collision: %s<->%s\n%s:%s" % (
- tests[module_name]['source_path'],
- tests[module_name]['tests'][test_name].lineno,
- test_uuid,
- test_name,
- uuids[test_uuid]['test_name'],
- uuids[test_uuid]['source_path'],
- uuids[test_uuid]['test_node'].lineno,
- )
- print(error_str)
- print("cannot automatically resolve the collision, please "
- "manually remove the duplicate value on the new test.")
- return True
- else:
- uuids[test_uuid] = {
- 'module': module_name,
- 'test_name': test_name,
- 'test_node': tests[module_name]['tests'][test_name],
- 'source_path': tests[module_name]['source_path']
- }
- return bool(self._filter_tests(report, tests))
-
- def report_untagged(self, tests):
- """Reports untagged tests if there are any.
-
- Returns true if untagged tests exist.
- """
- def report(module_name, test_name, tests):
- error_str = "%s:%s\nmissing @test.idempotent_id('...')\n%s\n" % (
- tests[module_name]['source_path'],
- tests[module_name]['tests'][test_name].lineno,
- test_name
- )
- print(error_str)
- return True
- return bool(self._filter_tests(report, tests))
-
- def fix_tests(self, tests):
- """Add uuids to all tests specified in tests and fix it"""
- patcher = SourcePatcher()
- for module_name in tests:
- add_import_once = True
- for test_name in tests[module_name]['tests']:
- if not tests[module_name]['import_valid'] and add_import_once:
- self._add_import_for_test_uuid(
- patcher,
- tests[module_name]['ast'],
- tests[module_name]['source_path']
- )
- add_import_once = False
- self._add_uuid_to_test(
- patcher, tests[module_name]['tests'][test_name],
- tests[module_name]['source_path'])
- patcher.apply_patches()
-
-
-def run():
- parser = argparse.ArgumentParser()
- parser.add_argument('--package', action='store', dest='package',
- default='tempest', type=str,
- help='Package with tests')
- parser.add_argument('--fix', action='store_true', dest='fix_tests',
- help='Attempt to fix tests without UUIDs')
- args = parser.parse_args()
- sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
- pkg = importlib.import_module(args.package)
- checker = TestChecker(pkg)
- errors = False
- tests = checker.get_tests()
- untagged = checker.find_untagged(tests)
- errors = checker.report_collisions(tests) or errors
- if args.fix_tests and untagged:
- checker.fix_tests(untagged)
- else:
- errors = checker.report_untagged(untagged) or errors
- if errors:
- sys.exit("@test.idempotent_id existence and uniqueness checks failed\n"
- "Run 'tox -v -euuidgen' to automatically fix tests with\n"
- "missing @test.idempotent_id decorators.")
-
-if __name__ == '__main__':
- run()
diff --git a/tools/colorizer.py b/tools/colorizer.py
deleted file mode 100755
index 3f68a51..0000000
--- a/tools/colorizer.py
+++ /dev/null
@@ -1,328 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2013, Nebula, Inc.
-# Copyright 2010 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
-# 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.
-#
-# Colorizer Code is borrowed from Twisted:
-# Copyright (c) 2001-2010 Twisted Matrix Laboratories.
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-"""Display a subunit stream through a colorized unittest test runner."""
-
-import heapq
-import sys
-import unittest
-
-import subunit
-import testtools
-
-
-class _AnsiColorizer(object):
- """A colorizer is an object that loosely wraps around a stream
-
- allowing callers to write text to the stream in a particular color.
-
- Colorizer classes must implement C{supported()} and C{write(text, color)}.
- """
- _colors = dict(black=30, red=31, green=32, yellow=33,
- blue=34, magenta=35, cyan=36, white=37)
-
- def __init__(self, stream):
- self.stream = stream
-
- def supported(cls, stream=sys.stdout):
- """Check the current platform supports coloring terminal output
-
- A class method that returns True if the current platform supports
- coloring terminal output using this method. Returns False otherwise.
- """
- if not stream.isatty():
- return False # auto color only on TTYs
- try:
- import curses
- except ImportError:
- return False
- else:
- try:
- try:
- return curses.tigetnum("colors") > 2
- except curses.error:
- curses.setupterm()
- return curses.tigetnum("colors") > 2
- except Exception:
- # guess false in case of error
- return False
- supported = classmethod(supported)
-
- def write(self, text, color):
- """Write the given text to the stream in the given color.
-
- @param text: Text to be written to the stream.
-
- @param color: A string label for a color. e.g. 'red', 'white'.
- """
- color = self._colors[color]
- self.stream.write('\x1b[%s;1m%s\x1b[0m' % (color, text))
-
-
-class _Win32Colorizer(object):
- """See _AnsiColorizer docstring."""
- def __init__(self, stream):
- import win32console
- red, green, blue, bold = (win32console.FOREGROUND_RED,
- win32console.FOREGROUND_GREEN,
- win32console.FOREGROUND_BLUE,
- win32console.FOREGROUND_INTENSITY)
- self.stream = stream
- self.screenBuffer = win32console.GetStdHandle(
- win32console.STD_OUT_HANDLE)
- self._colors = {'normal': red | green | blue,
- 'red': red | bold,
- 'green': green | bold,
- 'blue': blue | bold,
- 'yellow': red | green | bold,
- 'magenta': red | blue | bold,
- 'cyan': green | blue | bold,
- 'white': red | green | blue | bold}
-
- def supported(cls, stream=sys.stdout):
- try:
- import win32console
- screenBuffer = win32console.GetStdHandle(
- win32console.STD_OUT_HANDLE)
- except ImportError:
- return False
- import pywintypes
- try:
- screenBuffer.SetConsoleTextAttribute(
- win32console.FOREGROUND_RED |
- win32console.FOREGROUND_GREEN |
- win32console.FOREGROUND_BLUE)
- except pywintypes.error:
- return False
- else:
- return True
- supported = classmethod(supported)
-
- def write(self, text, color):
- color = self._colors[color]
- self.screenBuffer.SetConsoleTextAttribute(color)
- self.stream.write(text)
- self.screenBuffer.SetConsoleTextAttribute(self._colors['normal'])
-
-
-class _NullColorizer(object):
- """See _AnsiColorizer docstring."""
- def __init__(self, stream):
- self.stream = stream
-
- def supported(cls, stream=sys.stdout):
- return True
- supported = classmethod(supported)
-
- def write(self, text, color):
- self.stream.write(text)
-
-
-def get_elapsed_time_color(elapsed_time):
- if elapsed_time > 1.0:
- return 'red'
- elif elapsed_time > 0.25:
- return 'yellow'
- else:
- return 'green'
-
-
-class NovaTestResult(testtools.TestResult):
- def __init__(self, stream, descriptions, verbosity):
- super(NovaTestResult, self).__init__()
- self.stream = stream
- self.showAll = verbosity > 1
- self.num_slow_tests = 10
- self.slow_tests = [] # this is a fixed-sized heap
- self.colorizer = None
- # NOTE(vish): reset stdout for the terminal check
- stdout = sys.stdout
- sys.stdout = sys.__stdout__
- for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]:
- if colorizer.supported():
- self.colorizer = colorizer(self.stream)
- break
- sys.stdout = stdout
- self.start_time = None
- self.last_time = {}
- self.results = {}
- self.last_written = None
-
- def _writeElapsedTime(self, elapsed):
- color = get_elapsed_time_color(elapsed)
- self.colorizer.write(" %.2f" % elapsed, color)
-
- def _addResult(self, test, *args):
- try:
- name = test.id()
- except AttributeError:
- name = 'Unknown.unknown'
- test_class, test_name = name.rsplit('.', 1)
-
- elapsed = (self._now() - self.start_time).total_seconds()
- item = (elapsed, test_class, test_name)
- if len(self.slow_tests) >= self.num_slow_tests:
- heapq.heappushpop(self.slow_tests, item)
- else:
- heapq.heappush(self.slow_tests, item)
-
- self.results.setdefault(test_class, [])
- self.results[test_class].append((test_name, elapsed) + args)
- self.last_time[test_class] = self._now()
- self.writeTests()
-
- def _writeResult(self, test_name, elapsed, long_result, color,
- short_result, success):
- if self.showAll:
- self.stream.write(' %s' % str(test_name).ljust(66))
- self.colorizer.write(long_result, color)
- if success:
- self._writeElapsedTime(elapsed)
- self.stream.writeln()
- else:
- self.colorizer.write(short_result, color)
-
- def addSuccess(self, test):
- super(NovaTestResult, self).addSuccess(test)
- self._addResult(test, 'OK', 'green', '.', True)
-
- def addFailure(self, test, err):
- if test.id() == 'process-returncode':
- return
- super(NovaTestResult, self).addFailure(test, err)
- self._addResult(test, 'FAIL', 'red', 'F', False)
-
- def addError(self, test, err):
- super(NovaTestResult, self).addFailure(test, err)
- self._addResult(test, 'ERROR', 'red', 'E', False)
-
- def addSkip(self, test, reason=None, details=None):
- super(NovaTestResult, self).addSkip(test, reason, details)
- self._addResult(test, 'SKIP', 'blue', 'S', True)
-
- def startTest(self, test):
- self.start_time = self._now()
- super(NovaTestResult, self).startTest(test)
-
- def writeTestCase(self, cls):
- if not self.results.get(cls):
- return
- if cls != self.last_written:
- self.colorizer.write(cls, 'white')
- self.stream.writeln()
- for result in self.results[cls]:
- self._writeResult(*result)
- del self.results[cls]
- self.stream.flush()
- self.last_written = cls
-
- def writeTests(self):
- time = self.last_time.get(self.last_written, self._now())
- if not self.last_written or (self._now() - time).total_seconds() > 2.0:
- diff = 3.0
- while diff > 2.0:
- classes = self.results.keys()
- oldest = min(classes, key=lambda x: self.last_time[x])
- diff = (self._now() - self.last_time[oldest]).total_seconds()
- self.writeTestCase(oldest)
- else:
- self.writeTestCase(self.last_written)
-
- def done(self):
- self.stopTestRun()
-
- def stopTestRun(self):
- for cls in list(self.results.iterkeys()):
- self.writeTestCase(cls)
- self.stream.writeln()
- self.writeSlowTests()
-
- def writeSlowTests(self):
- # Pare out 'fast' tests
- slow_tests = [item for item in self.slow_tests
- if get_elapsed_time_color(item[0]) != 'green']
- if slow_tests:
- slow_total_time = sum(item[0] for item in slow_tests)
- slow = ("Slowest %i tests took %.2f secs:"
- % (len(slow_tests), slow_total_time))
- self.colorizer.write(slow, 'yellow')
- self.stream.writeln()
- last_cls = None
- # sort by name
- for elapsed, cls, name in sorted(slow_tests,
- key=lambda x: x[1] + x[2]):
- if cls != last_cls:
- self.colorizer.write(cls, 'white')
- self.stream.writeln()
- last_cls = cls
- self.stream.write(' %s' % str(name).ljust(68))
- self._writeElapsedTime(elapsed)
- self.stream.writeln()
-
- def printErrors(self):
- if self.showAll:
- self.stream.writeln()
- self.printErrorList('ERROR', self.errors)
- self.printErrorList('FAIL', self.failures)
-
- def printErrorList(self, flavor, errors):
- for test, err in errors:
- self.colorizer.write("=" * 70, 'red')
- self.stream.writeln()
- self.colorizer.write(flavor, 'red')
- self.stream.writeln(": %s" % test.id())
- self.colorizer.write("-" * 70, 'red')
- self.stream.writeln()
- self.stream.writeln("%s" % err)
-
-
-test = subunit.ProtocolTestCase(sys.stdin, passthrough=None)
-
-if sys.version_info[0:2] <= (2, 6):
- runner = unittest.TextTestRunner(verbosity=2)
-else:
- runner = unittest.TextTestRunner(verbosity=2, resultclass=NovaTestResult)
-
-if runner.run(test).wasSuccessful():
- exit_code = 0
-else:
- exit_code = 1
-sys.exit(exit_code)
diff --git a/tools/use_tempest_lib.sh b/tools/use_tempest_lib.sh
new file mode 100755
index 0000000..ca62c4a
--- /dev/null
+++ b/tools/use_tempest_lib.sh
@@ -0,0 +1,141 @@
+#!/bin/bash
+#
+# Use this script to use interfaces/files from tempest-lib.
+# Many files have been migrated to tempest-lib and tempest has
+# its own copy too.
+# This script helps to remove those from tempest and make use of tempest-lib.
+# It adds the change-id of each file on which they were migrated in lib.
+# This should only be done for files which were migrated to lib with
+# "Migrated" in commit message as done by tempest-lib/tools/migrate_from_tempest.sh script.
+# "Migrated" keyword is used to fetch the migration commit history from lib.
+# To use:
+# 1. Create a new branch in the tempest repo so not to destroy your current
+# working branch
+# 2. Run the script from the repo dir and specify the file paths relative to
+# the root tempest dir(only code and unit tests):
+#
+# tools/use_tempest_lib.sh.sh tempest/file1.py tempest/file2.py
+
+
+function usage {
+ echo "Usage: $0 [OPTION] file1 file2 .."
+ echo "Use files from tempest-lib"
+ echo -e "Input files should be tempest files with path. \n Example- tempest/file1.py tempest/file2.py .."
+ echo ""
+ echo "-s, --service_client Specify if files are service clients."
+ echo "-u, --tempest_lib_git_url Specify the repo to clone tempest-lib from."
+}
+
+function check_all_files_valid {
+ failed=0
+ for file in $files; do
+ # Get the latest change-id for each file
+ latest_commit_id=`git log -n1 -- $file | grep "^commit" | awk '{print $2}'`
+ cd $tmpdir
+ filename=`basename $file`
+ lib_path=`find ./ -name $filename`
+ if [ -z $lib_path ]; then
+ echo "ERROR: $filename does not exist in tempest-lib."
+ failed=$(( failed + 1))
+ cd - > /dev/null
+ continue
+ fi
+ # Get the CHANGE_ID of tempest-lib patch where file was migrated
+ migration_change_id=`git log -n1 --grep "Migrated" -- $lib_path | grep "Change-Id: " | awk '{print $2}'`
+ MIGRATION_IDS=`echo -e "$MIGRATION_IDS\n * $filename: $migration_change_id"`
+ # Get tempest CHANGE_ID of file which was migrated to lib
+ migrated_change_id=`git log -n1 --grep "Migrated" -- $lib_path | grep "* $filename"`
+ migrated_change_id=${migrated_change_id#*:}
+ cd - > /dev/null
+ # Get the commit-id of tempest which was migrated to tempest-lib
+ migrated_commit_id=`git log --grep "$migrated_change_id" -- $file | grep "^commit" | awk '{print $2}'`
+ DIFF=$(git diff $latest_commit_id $migrated_commit_id $file)
+ if [ "$DIFF" != "" ]; then
+ echo "ERROR: $filename in tempest has been updated after migration to tempest-lib. First sync the file to tempest-lib."
+ failed=$(( failed + 1))
+ fi
+ done
+ if [[ $failed -gt 0 ]]; then
+ echo "$failed files had issues"
+ exit $failed
+ fi
+}
+
+set -e
+
+service_client=0
+file_list=''
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -h|--help) usage; exit;;
+ -u|--tempest_lib_git_url) tempest_lib_git_url="$2"; shift;;
+ -s|--service_client) service_client=1;;
+ *) files="$files $1";;
+ esac
+ shift
+done
+
+if [ -z "$files" ]; then
+ usage; exit
+fi
+
+TEMPEST_LIB_GIT_URL=${tempest_lib_git_url:-git://git.openstack.org/openstack/tempest-lib}
+
+tmpdir=$(mktemp -d -t use-tempest-lib.XXXX)
+
+# Clone tempest-lib
+git clone $TEMPEST_LIB_GIT_URL $tmpdir
+
+# Checks all provided files are present in lib and
+# not updated in tempest after migration to lib.
+check_all_files_valid
+
+for file in $files; do
+ rm -f $file
+ tempest_dir=`pwd`
+ tempest_dir="$tempest_dir/tempest/"
+ tempest_dirname=`dirname $file`
+ lib_dirname=`echo $tempest_dirname | sed s@tempest\/@tempest_lib/\@`
+ # Convert tempest dirname to import string
+ tempest_import="${tempest_dirname//\//.}"
+ tempest_import=${tempest_import:2:${#tempest_import}}
+ if [ $service_client -eq 1 ]; then
+ # Remove /json path because tempest-lib supports JSON only without XML
+ lib_dirname=`echo $lib_dirname | sed s@\/json@@`
+ fi
+ # Convert tempest-lib dirname to import string
+ tempest_lib_import="${lib_dirname//\//.}"
+ tempest_lib_import=${tempest_lib_import:2:${#tempest_lib_import}}
+ module_name=`basename $file .py`
+ tempest_import1="from $tempest_import.$module_name"
+ tempest_lib_import1="from $tempest_lib_import.$module_name"
+ tempest_import2="from $tempest_import import $module_name"
+ tempest_lib_import2="from $tempest_lib_import import $module_name"
+ set +e
+ grep -rl "$tempest_import1" $tempest_dir | xargs sed -i'' s/"$tempest_import1"/"$tempest_lib_import1"/g 2> /dev/null
+ grep -rl "$tempest_import2" $tempest_dir | xargs sed -i'' s/"$tempest_import2"/"$tempest_lib_import2"/g 2> /dev/null
+ set -e
+ if [[ -z "$file_list" ]]; then
+ file_list="$module_name"
+ else
+ tmp_file_list="$file_list, $module_name"
+ char_size=`echo $tmp_file_list | wc -c`
+ if [ $char_size -lt 27 ]; then
+ file_list="$file_list, $module_name"
+ fi
+ fi
+done
+
+rm -rf $tmpdir
+echo "Completed. Run pep8 and fix error if any"
+
+git add -A tempest/
+# Generate a migration commit
+commit_message="Use $file_list from tempest-lib"
+pre_list=$"The files below have been migrated to tempest-lib\n"
+pre_list=`echo -e $pre_list`
+post_list=$"Now Tempest-lib provides those as stable interfaces. So Tempest should\nstart using those from lib and remove its own copy."
+post_list=`echo -e $post_list`
+
+git commit -m "$commit_message" -m "$pre_list" -m "$MIGRATION_IDS" -m "$post_list"
diff --git a/tox.ini b/tox.ini
index 892cfed..fedd04c 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = pep8,py27,py34
+envlist = pep8,py34,py27
minversion = 1.6
skipsdist = True
@@ -55,7 +55,7 @@
setenv = {[tempestenv]setenv}
deps = {[tempestenv]deps}
# The regex below is used to select which tests to run and exclude the slow tag:
-# See the testrepostiory bug: https://bugs.launchpad.net/testrepository/+bug/1208610
+# See the testrepository bug: https://bugs.launchpad.net/testrepository/+bug/1208610
commands =
find . -type f -name "*.pyc" -delete
bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty)) {posargs}'
@@ -65,7 +65,7 @@
setenv = {[tempestenv]setenv}
deps = {[tempestenv]deps}
# The regex below is used to select which tests to run and exclude the slow tag:
-# See the testrepostiory bug: https://bugs.launchpad.net/testrepository/+bug/1208610
+# See the testrepository bug: https://bugs.launchpad.net/testrepository/+bug/1208610
commands =
find . -type f -name "*.pyc" -delete
bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty)) {posargs}'
@@ -114,11 +114,11 @@
[testenv:pep8]
commands =
flake8 {posargs}
- python tools/check_uuid.py
+ check-uuid
[testenv:uuidgen]
commands =
- python tools/check_uuid.py --fix
+ check-uuid --fix
[hacking]
local-check-factory = tempest.hacking.checks.factory