Merge "Add config for Telemetry"
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage.py b/tempest/api/compute/admin/test_simple_tenant_usage.py
index a599f06..c416ad2 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage.py
@@ -18,7 +18,6 @@
import datetime
from tempest.api.compute import base
-from tempest import exceptions
from tempest.test import attr
import time
@@ -83,33 +82,6 @@
self.assertEqual(200, resp.status)
self.assertEqual(len(tenant_usage), 8)
- @attr(type=['negative', 'gate'])
- def test_get_usage_tenant_with_empty_tenant_id(self):
- # Get usage for a specific tenant empty
- params = {'start': self.start,
- 'end': self.end}
- self.assertRaises(exceptions.NotFound,
- self.adm_client.get_tenant_usage,
- '', params)
-
- @attr(type=['negative', 'gate'])
- def test_get_usage_tenant_with_invalid_date(self):
- # Get usage for tenant with invalid date
- params = {'start': self.end,
- 'end': self.start}
- self.assertRaises(exceptions.BadRequest,
- self.adm_client.get_tenant_usage,
- self.tenant_id, params)
-
- @attr(type=['negative', 'gate'])
- def test_list_usage_all_tenants_with_non_admin_user(self):
- # Get usage for all tenants with non admin user
- params = {'start': self.start,
- 'end': self.end,
- 'detailed': int(bool(True))}
- self.assertRaises(exceptions.Unauthorized,
- self.client.list_tenant_usages, params)
-
class TenantUsagesTestXML(TenantUsagesTestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
new file mode 100644
index 0000000..7e5168e
--- /dev/null
+++ b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
@@ -0,0 +1,76 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+
+import datetime
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class TenantUsagesNegativeTestJSON(base.BaseV2ComputeAdminTest):
+
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(TenantUsagesNegativeTestJSON, cls).setUpClass()
+ cls.adm_client = cls.os_adm.tenant_usages_client
+ cls.client = cls.os.tenant_usages_client
+ cls.identity_client = cls._get_identity_admin_client()
+ now = datetime.datetime.now()
+ cls.start = cls._parse_strtime(now - datetime.timedelta(days=1))
+ cls.end = cls._parse_strtime(now + datetime.timedelta(days=1))
+
+ @classmethod
+ def _parse_strtime(cls, at):
+ # Returns formatted datetime
+ return at.strftime('%Y-%m-%dT%H:%M:%S.%f')
+
+ @attr(type=['negative', 'gate'])
+ def test_get_usage_tenant_with_empty_tenant_id(self):
+ # Get usage for a specific tenant empty
+ params = {'start': self.start,
+ 'end': self.end}
+ self.assertRaises(exceptions.NotFound,
+ self.adm_client.get_tenant_usage,
+ '', params)
+
+ @attr(type=['negative', 'gate'])
+ def test_get_usage_tenant_with_invalid_date(self):
+ # Get usage for tenant with invalid date
+ params = {'start': self.end,
+ 'end': self.start}
+ resp, tenants = self.identity_client.list_tenants()
+ tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
+ self.client.tenant_name][0]
+ self.assertRaises(exceptions.BadRequest,
+ self.adm_client.get_tenant_usage,
+ tenant_id, params)
+
+ @attr(type=['negative', 'gate'])
+ def test_list_usage_all_tenants_with_non_admin_user(self):
+ # Get usage for all tenants with non admin user
+ params = {'start': self.start,
+ 'end': self.end,
+ 'detailed': int(bool(True))}
+ self.assertRaises(exceptions.Unauthorized,
+ self.client.list_tenant_usages, params)
+
+
+class TenantUsagesNegativeTestXML(TenantUsagesNegativeTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 1e5b6d2..b060f15 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -100,9 +100,8 @@
except exceptions.NotFound:
# The image may have already been deleted which is OK.
pass
- except Exception as exc:
- LOG.info('Exception raised deleting image %s', image_id)
- LOG.exception(exc)
+ except Exception:
+ LOG.exception('Exception raised deleting image %s' % image_id)
pass
@classmethod
@@ -214,8 +213,8 @@
try:
cls.servers_client.delete_server(server_id)
cls.servers_client.wait_for_server_termination(server_id)
- except Exception as exc:
- LOG.exception(exc)
+ except Exception:
+ LOG.exception('Failed to delete server %s' % server_id)
pass
resp, server = cls.create_test_server(wait_until='ACTIVE', **kwargs)
cls.password = server['adminPass']
@@ -266,12 +265,14 @@
cls.availability_zone_client = cls.os.availability_zone_v3_client
cls.interfaces_client = cls.os.interfaces_v3_client
cls.hypervisor_client = cls.os.hypervisor_v3_client
+ cls.keypairs_client = cls.os.keypairs_v3_client
cls.tenant_usages_client = cls.os.tenant_usages_v3_client
cls.volumes_client = cls.os.volumes_client
cls.certificates_client = cls.os.certificates_v3_client
cls.keypairs_client = cls.os.keypairs_v3_client
cls.aggregates_client = cls.os.aggregates_v3_client
cls.hosts_client = cls.os.hosts_v3_client
+ cls.quotas_client = cls.os.quotas_v3_client
@classmethod
def create_image_from_server(cls, server_id, **kwargs):
@@ -298,8 +299,8 @@
try:
cls.servers_client.delete_server(server_id)
cls.servers_client.wait_for_server_termination(server_id)
- except Exception as exc:
- LOG.exception(exc)
+ except Exception:
+ LOG.exception('Failed to delete server %s' % server_id)
pass
resp, server = cls.create_test_server(wait_until='ACTIVE', **kwargs)
cls.password = server['admin_password']
@@ -339,3 +340,4 @@
cls.flavors_admin_client = cls.os_adm.flavors_v3_client
cls.aggregates_admin_client = cls.os_adm.aggregates_v3_client
cls.hosts_admin_client = cls.os_adm.hosts_v3_client
+ cls.quotas_admin_client = cls.os_adm.quotas_v3_client
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions.py b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
index f4ad449..32e7b39 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -51,17 +51,15 @@
# Positive test:Allocation of a new floating IP to a project
# should be successful
resp, body = self.client.create_floating_ip()
- self.assertEqual(200, resp.status)
floating_ip_id_allocated = body['id']
- try:
- resp, floating_ip_details = \
- self.client.get_floating_ip_details(floating_ip_id_allocated)
- # Checking if the details of allocated IP is in list of floating IP
- resp, body = self.client.list_floating_ips()
- self.assertIn(floating_ip_details, body)
- finally:
- # Deleting the floating IP which is created in this method
- self.client.delete_floating_ip(floating_ip_id_allocated)
+ self.addCleanup(self.client.delete_floating_ip,
+ floating_ip_id_allocated)
+ self.assertEqual(200, resp.status)
+ resp, floating_ip_details = \
+ self.client.get_floating_ip_details(floating_ip_id_allocated)
+ # Checking if the details of allocated IP is in list of floating IP
+ resp, body = self.client.list_floating_ips()
+ self.assertIn(floating_ip_details, body)
@attr(type='gate')
def test_delete_floating_ip(self):
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips.py b/tempest/api/compute/floating_ips/test_list_floating_ips.py
index e4d03ae..9238994 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -54,25 +54,23 @@
def test_get_floating_ip_details(self):
# Positive test:Should be able to GET the details of floatingIP
# Creating a floating IP for which details are to be checked
- try:
- resp, body = self.client.create_floating_ip()
- floating_ip_instance_id = body['instance_id']
- floating_ip_ip = body['ip']
- floating_ip_fixed_ip = body['fixed_ip']
- floating_ip_id = body['id']
- resp, body = \
- self.client.get_floating_ip_details(floating_ip_id)
- self.assertEqual(200, resp.status)
- # Comparing the details of floating IP
- self.assertEqual(floating_ip_instance_id,
- body['instance_id'])
- self.assertEqual(floating_ip_ip, body['ip'])
- self.assertEqual(floating_ip_fixed_ip,
- body['fixed_ip'])
- self.assertEqual(floating_ip_id, body['id'])
- # Deleting the floating IP created in this method
- finally:
- self.client.delete_floating_ip(floating_ip_id)
+ resp, body = self.client.create_floating_ip()
+ floating_ip_id = body['id']
+ self.addCleanup(self.client.delete_floating_ip,
+ floating_ip_id)
+ floating_ip_instance_id = body['instance_id']
+ floating_ip_ip = body['ip']
+ floating_ip_fixed_ip = body['fixed_ip']
+ resp, body = \
+ self.client.get_floating_ip_details(floating_ip_id)
+ self.assertEqual(200, resp.status)
+ # Comparing the details of floating IP
+ self.assertEqual(floating_ip_instance_id,
+ body['instance_id'])
+ self.assertEqual(floating_ip_ip, body['ip'])
+ self.assertEqual(floating_ip_fixed_ip,
+ body['fixed_ip'])
+ self.assertEqual(floating_ip_id, body['id'])
@attr(type='gate')
def test_list_floating_ip_pools(self):
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index c711bd5..26cc3f6 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -46,10 +46,11 @@
try:
self.servers_client.wait_for_server_status(self.server_id,
'ACTIVE')
- except Exception as exc:
- LOG.exception(exc)
+ except Exception:
+ LOG.exception('server %s timed out to become ACTIVE. rebuilding'
+ % self.server_id)
# Rebuild server if cannot reach the ACTIVE state
- # Usually it means the server had a serius accident
+ # Usually it means the server had a serious accident
self.__class__.server_id = self.rebuild_server(self.server_id)
@classmethod
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
index b8a4304..5e235d1 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -45,10 +45,11 @@
try:
self.servers_client.wait_for_server_status(self.server_id,
'ACTIVE')
- except Exception as exc:
- LOG.exception(exc)
+ except Exception:
+ LOG.exception('server %s timed out to become ACTIVE. rebuilding'
+ % self.server_id)
# Rebuild server if cannot reach the ACTIVE state
- # Usually it means the server had a serius accident
+ # Usually it means the server had a serious accident
self._reset_server()
def _reset_server(self):
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index ac2ecba..bfdd8b2 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -59,8 +59,8 @@
resp, cls.image2 = cls.create_image_from_server(
cls.server1['id'], wait_until='ACTIVE')
cls.image2_id = cls.image2['id']
- except Exception as exc:
- LOG.exception(exc)
+ except Exception:
+ LOG.exception('setUpClass failed')
cls.tearDownClass()
raise
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index 080bd1a..91c350e 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -17,8 +17,7 @@
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class MultipleCreateTestJSON(base.BaseV2ComputeTest):
@@ -38,7 +37,7 @@
return resp, body
- @attr(type='gate')
+ @test.attr(type='gate')
def test_multiple_create(self):
resp, body = self._create_multiple_servers(wait_until='ACTIVE',
min_count=1,
@@ -49,39 +48,7 @@
self.assertEqual('202', resp['status'])
self.assertNotIn('reservation_id', body)
- @attr(type=['negative', 'gate'])
- def test_min_count_less_than_one(self):
- invalid_min_count = 0
- self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
- min_count=invalid_min_count)
-
- @attr(type=['negative', 'gate'])
- def test_min_count_non_integer(self):
- invalid_min_count = 2.5
- self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
- min_count=invalid_min_count)
-
- @attr(type=['negative', 'gate'])
- def test_max_count_less_than_one(self):
- invalid_max_count = 0
- self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
- max_count=invalid_max_count)
-
- @attr(type=['negative', 'gate'])
- def test_max_count_non_integer(self):
- invalid_max_count = 2.5
- self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
- max_count=invalid_max_count)
-
- @attr(type=['negative', 'gate'])
- def test_max_count_less_than_min_count(self):
- min_count = 3
- max_count = 2
- self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
- min_count=min_count,
- max_count=max_count)
-
- @attr(type='gate')
+ @test.attr(type='gate')
def test_multiple_create_with_reservation_return(self):
resp, body = self._create_multiple_servers(wait_until='ACTIVE',
min_count=1,
diff --git a/tempest/api/compute/servers/test_multiple_create_negative.py b/tempest/api/compute/servers/test_multiple_create_negative.py
new file mode 100644
index 0000000..a9d9945
--- /dev/null
+++ b/tempest/api/compute/servers/test_multiple_create_negative.py
@@ -0,0 +1,75 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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 tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest import test
+
+
+class MultipleCreateNegativeTestJSON(base.BaseV2ComputeTest):
+ _interface = 'json'
+ _name = 'multiple-create-test'
+
+ def _generate_name(self):
+ return data_utils.rand_name(self._name)
+
+ def _create_multiple_servers(self, name=None, wait_until=None, **kwargs):
+ """
+ This is the right way to create_multiple servers and manage to get the
+ created servers into the servers list to be cleaned up after all.
+ """
+ kwargs['name'] = kwargs.get('name', self._generate_name())
+ resp, body = self.create_test_server(**kwargs)
+
+ return resp, body
+
+ @test.attr(type=['negative', 'gate'])
+ def test_min_count_less_than_one(self):
+ invalid_min_count = 0
+ self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+ min_count=invalid_min_count)
+
+ @test.attr(type=['negative', 'gate'])
+ def test_min_count_non_integer(self):
+ invalid_min_count = 2.5
+ self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+ min_count=invalid_min_count)
+
+ @test.attr(type=['negative', 'gate'])
+ def test_max_count_less_than_one(self):
+ invalid_max_count = 0
+ self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+ max_count=invalid_max_count)
+
+ @test.attr(type=['negative', 'gate'])
+ def test_max_count_non_integer(self):
+ invalid_max_count = 2.5
+ self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+ max_count=invalid_max_count)
+
+ @test.attr(type=['negative', 'gate'])
+ def test_max_count_less_than_min_count(self):
+ min_count = 3
+ max_count = 2
+ self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+ min_count=min_count,
+ max_count=max_count)
+
+
+class MultipleCreateNegativeTestXML(MultipleCreateNegativeTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_quotas.py b/tempest/api/compute/v3/admin/test_quotas.py
index 66d41b8..e67ed8f 100644
--- a/tempest/api/compute/v3/admin/test_quotas.py
+++ b/tempest/api/compute/v3/admin/test_quotas.py
@@ -1,6 +1,6 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
-# Copyright 2012 OpenStack Foundation
+# Copyright 2013 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -17,41 +17,34 @@
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import config
from tempest import exceptions
-from tempest.test import attr
-from tempest.test import skip_because
-
-CONF = config.CONF
+from tempest import test
-class QuotasAdminTestJSON(base.BaseV2ComputeAdminTest):
+class QuotasAdminV3TestJSON(base.BaseV3ComputeAdminTest):
_interface = 'json'
force_tenant_isolation = True
@classmethod
def setUpClass(cls):
- super(QuotasAdminTestJSON, cls).setUpClass()
+ super(QuotasAdminV3TestJSON, cls).setUpClass()
cls.auth_url = cls.config.identity.uri
- cls.client = cls.os.quotas_client
- cls.adm_client = cls.os_adm.quotas_client
+ cls.client = cls.quotas_client
+ cls.adm_client = cls.quotas_admin_client
cls.identity_admin_client = cls._get_identity_admin_client()
- cls.sg_client = cls.security_groups_client
# NOTE(afazekas): these test cases should always create and use a new
# tenant most of them should be skipped if we can't do that
cls.demo_tenant_id = cls.isolated_creds.get_primary_user().get(
'tenantId')
- cls.default_quota_set = set(('injected_file_content_bytes',
- 'metadata_items', 'injected_files',
+ cls.default_quota_set = set(('metadata_items',
'ram', 'floating_ips',
'fixed_ips', 'key_pairs',
- 'injected_file_path_bytes',
'instances', 'security_group_rules',
'cores', 'security_groups'))
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_get_default_quotas(self):
# Admin can get the default resource quota set for a tenant
expected_quota_set = self.default_quota_set | set(['id'])
@@ -62,15 +55,14 @@
sorted(quota_set.keys()))
self.assertEqual(quota_set['id'], self.demo_tenant_id)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_update_all_quota_resources_for_tenant(self):
# Admin can update all the resource quota limits for a tenant
resp, default_quota_set = self.client.get_default_quota_set(
self.demo_tenant_id)
- new_quota_set = {'injected_file_content_bytes': 20480,
- 'metadata_items': 256, 'injected_files': 10,
+ new_quota_set = {'metadata_items': 256,
'ram': 10240, 'floating_ips': 20, 'fixed_ips': 10,
- 'key_pairs': 200, 'injected_file_path_bytes': 512,
+ 'key_pairs': 200,
'instances': 20, 'security_group_rules': 20,
'cores': 2, 'security_groups': 20}
# Update limits for all quota resources
@@ -83,10 +75,11 @@
self.addCleanup(self.adm_client.update_quota_set,
self.demo_tenant_id, **default_quota_set)
self.assertEqual(200, resp.status)
+ quota_set.pop('id')
self.assertEqual(new_quota_set, quota_set)
# TODO(afazekas): merge these test cases
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_updated_quotas(self):
# Verify that GET shows the updated quota set
tenant_name = data_utils.rand_name('cpu_quota_tenant_')
@@ -106,7 +99,7 @@
# TODO(afazekas): Add dedicated tenant to the skiped quota tests
# it can be moved into the setUpClass as well
- @attr(type='gate')
+ @test.attr(type='gate')
def test_create_server_when_cpu_quota_is_full(self):
# Disallow server creation when tenant's vcpu quota is full
resp, quota_set = self.client.get_quota_set(self.demo_tenant_id)
@@ -121,7 +114,7 @@
cores=default_vcpu_quota)
self.assertRaises(exceptions.OverLimit, self.create_test_server)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_create_server_when_memory_quota_is_full(self):
# Disallow server creation when tenant's memory quota is full
resp, quota_set = self.client.get_quota_set(self.demo_tenant_id)
@@ -136,14 +129,14 @@
ram=default_mem_quota)
self.assertRaises(exceptions.OverLimit, self.create_test_server)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_update_quota_normal_user(self):
self.assertRaises(exceptions.Unauthorized,
self.client.update_quota_set,
self.demo_tenant_id,
ram=0)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_server_when_instances_quota_is_full(self):
# Once instances quota limit is reached, disallow server creation
resp, quota_set = self.client.get_quota_set(self.demo_tenant_id)
@@ -157,66 +150,6 @@
instances=default_instances_quota)
self.assertRaises(exceptions.OverLimit, self.create_test_server)
- @skip_because(bug="1186354",
- condition=CONF.service_available.neutron)
- @attr(type=['negative', 'gate'])
- def test_security_groups_exceed_limit(self):
- # Negative test: Creation Security Groups over limit should FAIL
- resp, quota_set = self.client.get_quota_set(self.demo_tenant_id)
- default_sg_quota = quota_set['security_groups']
- sg_quota = 0 # Set the quota to zero to conserve resources
-
- resp, quota_set =\
- self.adm_client.update_quota_set(self.demo_tenant_id,
- force=True,
- security_groups=sg_quota)
-
- self.addCleanup(self.adm_client.update_quota_set,
- self.demo_tenant_id,
- security_groups=default_sg_quota)
-
- # Check we cannot create anymore
- self.assertRaises(exceptions.OverLimit,
- self.sg_client.create_security_group,
- "sg-overlimit", "sg-desc")
-
- @skip_because(bug="1186354",
- condition=CONF.service_available.neutron)
- @attr(type=['negative', 'gate'])
- def test_security_groups_rules_exceed_limit(self):
- # Negative test: Creation of Security Group Rules should FAIL
- # when we reach limit maxSecurityGroupRules
-
- resp, quota_set = self.client.get_quota_set(self.demo_tenant_id)
- default_sg_rules_quota = quota_set['security_group_rules']
- sg_rules_quota = 0 # Set the quota to zero to conserve resources
-
- resp, quota_set =\
- self.adm_client.update_quota_set(
- self.demo_tenant_id,
- force=True,
- security_group_rules=sg_rules_quota)
-
- self.addCleanup(self.adm_client.update_quota_set,
- self.demo_tenant_id,
- security_group_rules=default_sg_rules_quota)
-
- s_name = data_utils.rand_name('securitygroup-')
- s_description = data_utils.rand_name('description-')
- resp, securitygroup =\
- self.sg_client.create_security_group(s_name, s_description)
- self.addCleanup(self.sg_client.delete_security_group,
- securitygroup['id'])
-
- secgroup_id = securitygroup['id']
- ip_protocol = 'tcp'
-
- # Check we cannot create SG rule anymore
- self.assertRaises(exceptions.OverLimit,
- self.sg_client.create_security_group_rule,
- secgroup_id, ip_protocol, 1025, 1025)
-
-
-class QuotasAdminTestXML(QuotasAdminTestJSON):
+class QuotasAdminV3TestXML(QuotasAdminV3TestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_servers.py b/tempest/api/compute/v3/admin/test_servers.py
new file mode 100644
index 0000000..6fe3186
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_servers.py
@@ -0,0 +1,146 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 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.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+from tempest.test import skip_because
+
+
+class ServersAdminTestJSON(base.BaseV2ComputeAdminTest):
+
+ """
+ Tests Servers API using admin privileges
+ """
+
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(ServersAdminTestJSON, cls).setUpClass()
+ cls.client = cls.os_adm.servers_client
+ cls.non_admin_client = cls.servers_client
+ cls.flavors_client = cls.os_adm.flavors_client
+
+ cls.s1_name = data_utils.rand_name('server')
+ resp, server = cls.create_test_server(name=cls.s1_name,
+ wait_until='ACTIVE')
+ cls.s1_id = server['id']
+
+ cls.s2_name = data_utils.rand_name('server')
+ resp, server = cls.create_test_server(name=cls.s2_name,
+ wait_until='ACTIVE')
+
+ def _get_unused_flavor_id(self):
+ flavor_id = data_utils.rand_int_id(start=1000)
+ while True:
+ try:
+ resp, body = self.flavors_client.get_flavor_details(flavor_id)
+ except exceptions.NotFound:
+ break
+ flavor_id = data_utils.rand_int_id(start=1000)
+ return flavor_id
+
+ @attr(type='gate')
+ def test_list_servers_by_admin(self):
+ # Listing servers by admin user returns empty list by default
+ resp, body = self.client.list_servers_with_detail()
+ servers = body['servers']
+ self.assertEqual('200', resp['status'])
+ self.assertEqual([], servers)
+
+ @attr(type='gate')
+ def test_list_servers_by_admin_with_all_tenants(self):
+ # Listing servers by admin user with all tenants parameter
+ # Here should be listed all servers
+ params = {'all_tenants': ''}
+ resp, body = self.client.list_servers_with_detail(params)
+ servers = body['servers']
+ servers_name = map(lambda x: x['name'], servers)
+
+ self.assertIn(self.s1_name, servers_name)
+ self.assertIn(self.s2_name, servers_name)
+
+ @attr(type='gate')
+ def test_admin_delete_servers_of_others(self):
+ # Administrator can delete servers of others
+ _, server = self.create_test_server()
+ resp, _ = self.client.delete_server(server['id'])
+ self.assertEqual('204', resp['status'])
+ self.servers_client.wait_for_server_termination(server['id'])
+
+ @attr(type='gate')
+ def test_reset_state_server(self):
+ # Reset server's state to 'error'
+ resp, server = self.client.reset_state(self.s1_id)
+ self.assertEqual(202, resp.status)
+
+ # Verify server's state
+ resp, server = self.client.get_server(self.s1_id)
+ self.assertEqual(server['status'], 'ERROR')
+
+ # Reset server's state to 'active'
+ resp, server = self.client.reset_state(self.s1_id, state='active')
+ self.assertEqual(202, resp.status)
+
+ # Verify server's state
+ resp, server = self.client.get_server(self.s1_id)
+ self.assertEqual(server['status'], 'ACTIVE')
+
+ @attr(type='gate')
+ @skip_because(bug="1240043")
+ def test_get_server_diagnostics_by_admin(self):
+ # Retrieve server diagnostics by admin user
+ resp, diagnostic = self.client.get_server_diagnostics(self.s1_id)
+ self.assertEqual(200, resp.status)
+ basic_attrs = ['rx_packets', 'rx_errors', 'rx_drop',
+ 'tx_packets', 'tx_errors', 'tx_drop',
+ 'read_req', 'write_req', 'cpu', 'memory']
+ for key in basic_attrs:
+ self.assertIn(key, str(diagnostic.keys()))
+
+ @attr(type='gate')
+ def test_rebuild_server_in_error_state(self):
+ # The server in error state should be rebuilt using the provided
+ # image and changed to ACTIVE state
+
+ # resetting vm state require admin priviledge
+ resp, server = self.client.reset_state(self.s1_id, state='error')
+ self.assertEqual(202, resp.status)
+ resp, rebuilt_server = self.non_admin_client.rebuild(
+ self.s1_id, self.image_ref_alt)
+ self.addCleanup(self.non_admin_client.wait_for_server_status,
+ self.s1_id, 'ACTIVE')
+ self.addCleanup(self.non_admin_client.rebuild, self.s1_id,
+ self.image_ref)
+
+ # Verify the properties in the initial response are correct
+ self.assertEqual(self.s1_id, rebuilt_server['id'])
+ rebuilt_image_id = rebuilt_server['image']['id']
+ self.assertEqual(self.image_ref_alt, rebuilt_image_id)
+ self.assertEqual(self.flavor_ref, rebuilt_server['flavor']['id'])
+ self.non_admin_client.wait_for_server_status(rebuilt_server['id'],
+ 'ACTIVE',
+ raise_on_error=False)
+ # Verify the server properties after rebuilding
+ resp, server = self.non_admin_client.get_server(rebuilt_server['id'])
+ rebuilt_image_id = server['image']['id']
+ self.assertEqual(self.image_ref_alt, rebuilt_image_id)
+
+
+class ServersAdminTestXML(ServersAdminTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_servers_negative.py b/tempest/api/compute/v3/admin/test_servers_negative.py
new file mode 100644
index 0000000..77d873b
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_servers_negative.py
@@ -0,0 +1,143 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Huawei Technologies Co.,LTD.
+#
+# 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 uuid
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class ServersAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
+
+ """
+ Tests Servers API using admin privileges
+ """
+
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(ServersAdminNegativeTestJSON, cls).setUpClass()
+ cls.client = cls.os_adm.servers_client
+ cls.non_adm_client = cls.servers_client
+ cls.flavors_client = cls.os_adm.flavors_client
+ cls.identity_client = cls._get_identity_admin_client()
+ tenant = cls.identity_client.get_tenant_by_name(
+ cls.client.tenant_name)
+ cls.tenant_id = tenant['id']
+
+ cls.s1_name = data_utils.rand_name('server')
+ resp, server = cls.create_test_server(name=cls.s1_name,
+ wait_until='ACTIVE')
+ cls.s1_id = server['id']
+
+ def _get_unused_flavor_id(self):
+ flavor_id = data_utils.rand_int_id(start=1000)
+ while True:
+ try:
+ resp, body = self.flavors_client.get_flavor_details(flavor_id)
+ except exceptions.NotFound:
+ break
+ flavor_id = data_utils.rand_int_id(start=1000)
+ return flavor_id
+
+ @attr(type=['negative', 'gate'])
+ def test_resize_server_using_overlimit_ram(self):
+ flavor_name = data_utils.rand_name("flavor-")
+ flavor_id = self._get_unused_flavor_id()
+ resp, quota_set = self.quotas_client.get_default_quota_set(
+ self.tenant_id)
+ ram = int(quota_set['ram']) + 1
+ vcpus = 8
+ disk = 10
+ resp, flavor_ref = self.flavors_client.create_flavor(flavor_name,
+ ram, vcpus, disk,
+ flavor_id)
+ self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
+ self.assertRaises(exceptions.OverLimit,
+ self.client.resize,
+ self.servers[0]['id'],
+ flavor_ref['id'])
+
+ @attr(type=['negative', 'gate'])
+ def test_resize_server_using_overlimit_vcpus(self):
+ flavor_name = data_utils.rand_name("flavor-")
+ flavor_id = self._get_unused_flavor_id()
+ ram = 512
+ resp, quota_set = self.quotas_client.get_default_quota_set(
+ self.tenant_id)
+ vcpus = int(quota_set['cores']) + 1
+ disk = 10
+ resp, flavor_ref = self.flavors_client.create_flavor(flavor_name,
+ ram, vcpus, disk,
+ flavor_id)
+ self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
+ self.assertRaises(exceptions.OverLimit,
+ self.client.resize,
+ self.servers[0]['id'],
+ flavor_ref['id'])
+
+ @attr(type=['negative', 'gate'])
+ def test_reset_state_server_invalid_state(self):
+ self.assertRaises(exceptions.BadRequest,
+ self.client.reset_state, self.s1_id,
+ state='invalid')
+
+ @attr(type=['negative', 'gate'])
+ def test_reset_state_server_invalid_type(self):
+ self.assertRaises(exceptions.BadRequest,
+ self.client.reset_state, self.s1_id,
+ state=1)
+
+ @attr(type=['negative', 'gate'])
+ def test_reset_state_server_nonexistent_server(self):
+ self.assertRaises(exceptions.NotFound,
+ self.client.reset_state, '999')
+
+ @attr(type=['negative', 'gate'])
+ def test_get_server_diagnostics_by_non_admin(self):
+ # Non-admin user can not view server diagnostics according to policy
+ self.assertRaises(exceptions.Unauthorized,
+ self.non_adm_client.get_server_diagnostics,
+ self.s1_id)
+
+ @attr(type=['negative', 'gate'])
+ def test_migrate_non_existent_server(self):
+ # migrate a non existent server
+ self.assertRaises(exceptions.NotFound,
+ self.client.migrate_server,
+ str(uuid.uuid4()))
+
+ @attr(type=['negative', 'gate'])
+ def test_migrate_server_invalid_state(self):
+ # create server.
+ resp, server = self.create_test_server(wait_until='ACTIVE')
+ self.assertEqual(202, resp.status)
+ server_id = server['id']
+ # suspend the server.
+ resp, _ = self.client.suspend_server(server_id)
+ self.assertEqual(202, resp.status)
+ self.client.wait_for_server_status(server_id, 'SUSPENDED')
+ # migrate an suspended server should fail
+ self.assertRaises(exceptions.Conflict,
+ self.client.migrate_server,
+ server_id)
+
+
+class ServersAdminNegativeTestXML(ServersAdminNegativeTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_simple_tenant_usage.py b/tempest/api/compute/v3/admin/test_simple_tenant_usage.py
index 3fc58eb..99f2c52 100644
--- a/tempest/api/compute/v3/admin/test_simple_tenant_usage.py
+++ b/tempest/api/compute/v3/admin/test_simple_tenant_usage.py
@@ -18,7 +18,6 @@
import datetime
from tempest.api.compute import base
-from tempest import exceptions
from tempest.test import attr
import time
@@ -83,33 +82,6 @@
self.assertEqual(200, resp.status)
self.assertEqual(len(tenant_usage), 8)
- @attr(type=['negative', 'gate'])
- def test_get_usage_tenant_with_empty_tenant_id(self):
- # Get usage for a specific tenant empty
- params = {'start': self.start,
- 'end': self.end}
- self.assertRaises(exceptions.NotFound,
- self.adm_client.get_tenant_usage,
- '', params)
-
- @attr(type=['negative', 'gate'])
- def test_get_usage_tenant_with_invalid_date(self):
- # Get usage for tenant with invalid date
- params = {'start': self.end,
- 'end': self.start}
- self.assertRaises(exceptions.BadRequest,
- self.adm_client.get_tenant_usage,
- self.tenant_id, params)
-
- @attr(type=['negative', 'gate'])
- def test_list_usage_all_tenants_with_non_admin_user(self):
- # Get usage for all tenants with non admin user
- params = {'start': self.start,
- 'end': self.end,
- 'detailed': int(bool(True))}
- self.assertRaises(exceptions.Unauthorized,
- self.client.list_tenant_usages, params)
-
class TenantUsagesV3TestXML(TenantUsagesV3TestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_simple_tenant_usage_negative.py b/tempest/api/compute/v3/admin/test_simple_tenant_usage_negative.py
new file mode 100644
index 0000000..ef49ed7
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_simple_tenant_usage_negative.py
@@ -0,0 +1,76 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+
+import datetime
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class TenantUsagesNegativeV3TestJSON(base.BaseV3ComputeAdminTest):
+
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(TenantUsagesNegativeV3TestJSON, cls).setUpClass()
+ cls.adm_client = cls.os_adm.tenant_usages_client
+ cls.client = cls.os.tenant_usages_client
+ cls.identity_client = cls._get_identity_admin_client()
+ now = datetime.datetime.now()
+ cls.start = cls._parse_strtime(now - datetime.timedelta(days=1))
+ cls.end = cls._parse_strtime(now + datetime.timedelta(days=1))
+
+ @classmethod
+ def _parse_strtime(cls, at):
+ # Returns formatted datetime
+ return at.strftime('%Y-%m-%dT%H:%M:%S.%f')
+
+ @attr(type=['negative', 'gate'])
+ def test_get_usage_tenant_with_empty_tenant_id(self):
+ # Get usage for a specific tenant empty
+ params = {'start': self.start,
+ 'end': self.end}
+ self.assertRaises(exceptions.NotFound,
+ self.adm_client.get_tenant_usage,
+ '', params)
+
+ @attr(type=['negative', 'gate'])
+ def test_get_usage_tenant_with_invalid_date(self):
+ # Get usage for tenant with invalid date
+ params = {'start': self.end,
+ 'end': self.start}
+ resp, tenants = self.identity_client.list_tenants()
+ tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
+ self.client.tenant_name][0]
+ self.assertRaises(exceptions.BadRequest,
+ self.adm_client.get_tenant_usage,
+ tenant_id, params)
+
+ @attr(type=['negative', 'gate'])
+ def test_list_usage_all_tenants_with_non_admin_user(self):
+ # Get usage for all tenants with non admin user
+ params = {'start': self.start,
+ 'end': self.end,
+ 'detailed': int(bool(True))}
+ self.assertRaises(exceptions.Unauthorized,
+ self.client.list_tenant_usages, params)
+
+
+class TenantUsagesNegativeV3TestXML(TenantUsagesNegativeV3TestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_create_server.py b/tempest/api/compute/v3/servers/test_create_server.py
index 94175ab..e1bb160 100644
--- a/tempest/api/compute/v3/servers/test_create_server.py
+++ b/tempest/api/compute/v3/servers/test_create_server.py
@@ -24,19 +24,19 @@
from tempest.common.utils import data_utils
from tempest.common.utils.linux.remote_client import RemoteClient
from tempest import config
-from tempest.test import attr
+from tempest import test
CONF = config.CONF
-class ServersTestJSON(base.BaseV2ComputeTest):
+class ServersV3TestJSON(base.BaseV3ComputeTest):
_interface = 'json'
run_ssh = CONF.compute.run_ssh
disk_config = 'AUTO'
@classmethod
def setUpClass(cls):
- super(ServersTestJSON, cls).setUpClass()
+ super(ServersV3TestJSON, cls).setUpClass()
cls.meta = {'hello': 'world'}
cls.accessIPv4 = '1.1.1.1'
cls.accessIPv6 = '0000:0000:0000:0000:0000:babe:220.12.22.2'
@@ -47,36 +47,37 @@
cls.client = cls.servers_client
cli_resp = cls.create_test_server(name=cls.name,
meta=cls.meta,
- accessIPv4=cls.accessIPv4,
- accessIPv6=cls.accessIPv6,
+ access_ip_v4=cls.accessIPv4,
+ access_ip_v6=cls.accessIPv6,
personality=personality,
disk_config=cls.disk_config)
cls.resp, cls.server_initial = cli_resp
- cls.password = cls.server_initial['adminPass']
+ cls.password = cls.server_initial['admin_password']
cls.client.wait_for_server_status(cls.server_initial['id'], 'ACTIVE')
resp, cls.server = cls.client.get_server(cls.server_initial['id'])
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_create_server_response(self):
# Check that the required fields are returned with values
self.assertEqual(202, self.resp.status)
self.assertTrue(self.server_initial['id'] is not None)
- self.assertTrue(self.server_initial['adminPass'] is not None)
+ self.assertTrue(self.server_initial['admin_password'] is not None)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_verify_server_details(self):
# Verify the specified server attributes are set correctly
- self.assertEqual(self.accessIPv4, self.server['accessIPv4'])
+ self.assertEqual(self.accessIPv4,
+ self.server['os-access-ips:access_ip_v4'])
# NOTE(maurosr): See http://tools.ietf.org/html/rfc5952 (section 4)
# Here we compare directly with the canonicalized format.
- self.assertEqual(self.server['accessIPv6'],
+ self.assertEqual(self.server['os-access-ips:access_ip_v6'],
str(netaddr.IPAddress(self.accessIPv6)))
self.assertEqual(self.name, self.server['name'])
self.assertEqual(self.image_ref, self.server['image']['id'])
self.assertEqual(self.flavor_ref, self.server['flavor']['id'])
self.assertEqual(self.meta, self.server['metadata'])
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_list_servers(self):
# The created server should be in the list of all servers
resp, body = self.client.list_servers()
@@ -84,7 +85,7 @@
found = any([i for i in servers if i['id'] == self.server['id']])
self.assertTrue(found)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_list_servers_with_detail(self):
# The created server should be in the detailed list of all servers
resp, body = self.client.list_servers_with_detail()
@@ -93,14 +94,14 @@
self.assertTrue(found)
@testtools.skipIf(not run_ssh, 'Instance validation tests are disabled.')
- @attr(type='gate')
+ @test.attr(type='gate')
def test_can_log_into_created_server(self):
# Check that the user can authenticate with the generated password
linux_client = RemoteClient(self.server, self.ssh_user, self.password)
self.assertTrue(linux_client.can_authenticate())
@testtools.skipIf(not run_ssh, 'Instance validation tests are disabled.')
- @attr(type='gate')
+ @test.attr(type='gate')
def test_verify_created_server_vcpus(self):
# Verify that the number of vcpus reported by the instance matches
# the amount stated by the flavor
@@ -109,14 +110,14 @@
self.assertEqual(flavor['vcpus'], linux_client.get_number_of_vcpus())
@testtools.skipIf(not run_ssh, 'Instance validation tests are disabled.')
- @attr(type='gate')
+ @test.attr(type='gate')
def test_host_name_is_same_as_server_name(self):
# Verify the instance host name is the same as the server name
linux_client = RemoteClient(self.server, self.ssh_user, self.password)
self.assertTrue(linux_client.hostname_equals_servername(self.name))
-class ServersTestManualDisk(ServersTestJSON):
+class ServersV3TestManualDisk(ServersV3TestJSON):
disk_config = 'MANUAL'
@classmethod
@@ -124,8 +125,8 @@
if not CONF.compute_feature_enabled.disk_config:
msg = "DiskConfig extension not enabled."
raise cls.skipException(msg)
- super(ServersTestManualDisk, cls).setUpClass()
+ super(ServersV3TestManualDisk, cls).setUpClass()
-class ServersTestXML(ServersTestJSON):
+class ServersV3TestXML(ServersV3TestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_multiple_create.py b/tempest/api/compute/v3/servers/test_multiple_create.py
index 080bd1a..3ee46ad 100644
--- a/tempest/api/compute/v3/servers/test_multiple_create.py
+++ b/tempest/api/compute/v3/servers/test_multiple_create.py
@@ -18,10 +18,10 @@
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
-class MultipleCreateTestJSON(base.BaseV2ComputeTest):
+class MultipleCreateV3TestJSON(base.BaseV3ComputeTest):
_interface = 'json'
_name = 'multiple-create-test'
@@ -38,7 +38,7 @@
return resp, body
- @attr(type='gate')
+ @test.attr(type='gate')
def test_multiple_create(self):
resp, body = self._create_multiple_servers(wait_until='ACTIVE',
min_count=1,
@@ -49,31 +49,31 @@
self.assertEqual('202', resp['status'])
self.assertNotIn('reservation_id', body)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_min_count_less_than_one(self):
invalid_min_count = 0
self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
min_count=invalid_min_count)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_min_count_non_integer(self):
invalid_min_count = 2.5
self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
min_count=invalid_min_count)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_max_count_less_than_one(self):
invalid_max_count = 0
self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
max_count=invalid_max_count)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_max_count_non_integer(self):
invalid_max_count = 2.5
self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
max_count=invalid_max_count)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_max_count_less_than_min_count(self):
min_count = 3
max_count = 2
@@ -81,7 +81,7 @@
min_count=min_count,
max_count=max_count)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_multiple_create_with_reservation_return(self):
resp, body = self._create_multiple_servers(wait_until='ACTIVE',
min_count=1,
@@ -91,5 +91,5 @@
self.assertIn('reservation_id', body)
-class MultipleCreateTestXML(MultipleCreateTestJSON):
+class MultipleCreateV3TestXML(MultipleCreateV3TestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_servers.py b/tempest/api/compute/v3/servers/test_servers.py
index d72476d..9eff462 100644
--- a/tempest/api/compute/v3/servers/test_servers.py
+++ b/tempest/api/compute/v3/servers/test_servers.py
@@ -17,31 +17,31 @@
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
-class ServersTestJSON(base.BaseV2ComputeTest):
+class ServersV3TestJSON(base.BaseV3ComputeTest):
_interface = 'json'
@classmethod
def setUpClass(cls):
- super(ServersTestJSON, cls).setUpClass()
+ super(ServersV3TestJSON, cls).setUpClass()
cls.client = cls.servers_client
def tearDown(self):
self.clear_servers()
- super(ServersTestJSON, self).tearDown()
+ super(ServersV3TestJSON, self).tearDown()
- @attr(type='gate')
+ @test.attr(type='gate')
def test_create_server_with_admin_password(self):
# If an admin password is provided on server creation, the server's
# root password should be set to that password.
- resp, server = self.create_test_server(adminPass='testpassword')
+ resp, server = self.create_test_server(admin_password='testpassword')
# Verify the password is set correctly in the response
- self.assertEqual('testpassword', server['adminPass'])
+ self.assertEqual('testpassword', server['admin_password'])
- @attr(type='gate')
+ @test.attr(type='gate')
def test_create_with_existing_server_name(self):
# Creating a server with a name that already exists is allowed
@@ -60,7 +60,7 @@
name2 = server['name']
self.assertEqual(name1, name2)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_create_specify_keypair(self):
# Specify a keypair while creating a server
@@ -73,7 +73,7 @@
resp, server = self.client.get_server(server['id'])
self.assertEqual(key_name, server['key_name'])
- @attr(type='gate')
+ @test.attr(type='gate')
def test_update_server_name(self):
# The server name should be changed to the the provided value
resp, server = self.create_test_server(wait_until='ACTIVE')
@@ -88,46 +88,47 @@
resp, server = self.client.get_server(server['id'])
self.assertEqual('newname', server['name'])
- @attr(type='gate')
+ @test.attr(type='gate')
def test_update_access_server_address(self):
# The server's access addresses should reflect the provided values
resp, server = self.create_test_server(wait_until='ACTIVE')
# Update the IPv4 and IPv6 access addresses
resp, body = self.client.update_server(server['id'],
- accessIPv4='1.1.1.1',
- accessIPv6='::babe:202:202')
+ access_ip_v4='1.1.1.1',
+ access_ip_v6='::babe:202:202')
self.assertEqual(200, resp.status)
self.client.wait_for_server_status(server['id'], 'ACTIVE')
# Verify the access addresses have been updated
resp, server = self.client.get_server(server['id'])
- self.assertEqual('1.1.1.1', server['accessIPv4'])
- self.assertEqual('::babe:202:202', server['accessIPv6'])
+ self.assertEqual('1.1.1.1', server['os-access-ips:access_ip_v4'])
+ self.assertEqual('::babe:202:202',
+ server['os-access-ips:access_ip_v6'])
- @attr(type='gate')
+ @test.attr(type='gate')
def test_delete_server_while_in_building_state(self):
# Delete a server while it's VM state is Building
resp, server = self.create_test_server(wait_until='BUILD')
resp, _ = self.client.delete_server(server['id'])
self.assertEqual('204', resp['status'])
- @attr(type='gate')
+ @test.attr(type='gate')
def test_delete_active_server(self):
# Delete a server while it's VM state is Active
resp, server = self.create_test_server(wait_until='ACTIVE')
resp, _ = self.client.delete_server(server['id'])
self.assertEqual('204', resp['status'])
- @attr(type='gate')
+ @test.attr(type='gate')
def test_create_server_with_ipv6_addr_only(self):
# Create a server without an IPv4 address(only IPv6 address).
- resp, server = self.create_test_server(accessIPv6='2001:2001::3')
+ resp, server = self.create_test_server(access_ip_v6='2001:2001::3')
self.assertEqual('202', resp['status'])
self.client.wait_for_server_status(server['id'], 'ACTIVE')
resp, server = self.client.get_server(server['id'])
- self.assertEqual('2001:2001::3', server['accessIPv6'])
+ self.assertEqual('2001:2001::3', server['os-access-ips:access_ip_v6'])
-class ServersTestXML(ServersTestJSON):
+class ServersV3TestXML(ServersV3TestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/v3/test_live_block_migration.py b/tempest/api/compute/v3/test_live_block_migration.py
new file mode 100644
index 0000000..3de50c8
--- /dev/null
+++ b/tempest/api/compute/v3/test_live_block_migration.py
@@ -0,0 +1,173 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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.
+
+import random
+import string
+
+import testtools
+
+from tempest.api.compute import base
+from tempest import config
+from tempest import exceptions
+from tempest.test import attr
+
+
+class LiveBlockMigrationV3TestJSON(base.BaseV3ComputeAdminTest):
+ _host_key = 'os-extended-server-attributes:host'
+ _interface = 'json'
+
+ CONF = config.CONF
+
+ @classmethod
+ def setUpClass(cls):
+ super(LiveBlockMigrationV3TestJSON, cls).setUpClass()
+
+ cls.admin_hosts_client = cls.hosts_admin_client
+ cls.admin_servers_client = cls.servers_admin_client
+
+ cls.created_server_ids = []
+
+ def _get_compute_hostnames(self):
+ _resp, body = self.admin_hosts_client.list_hosts()
+ return [
+ host_record['host_name']
+ for host_record in body
+ if host_record['service'] == 'compute'
+ ]
+
+ def _get_server_details(self, server_id):
+ _resp, body = self.admin_servers_client.get_server(server_id)
+ return body
+
+ def _get_host_for_server(self, server_id):
+ return self._get_server_details(server_id)[self._host_key]
+
+ def _migrate_server_to(self, server_id, dest_host):
+ _resp, body = self.admin_servers_client.live_migrate_server(
+ server_id, dest_host,
+ self.config.compute_feature_enabled.
+ block_migration_for_live_migration)
+ return body
+
+ def _get_host_other_than(self, host):
+ for target_host in self._get_compute_hostnames():
+ if host != target_host:
+ return target_host
+
+ def _get_non_existing_host_name(self):
+ random_name = ''.join(
+ random.choice(string.ascii_uppercase) for x in range(20))
+
+ self.assertNotIn(random_name, self._get_compute_hostnames())
+
+ return random_name
+
+ def _get_server_status(self, server_id):
+ return self._get_server_details(server_id)['status']
+
+ def _get_an_active_server(self):
+ for server_id in self.created_server_ids:
+ if 'ACTIVE' == self._get_server_status(server_id):
+ return server_id
+ else:
+ _, server = self.create_test_server(wait_until="ACTIVE")
+ server_id = server['id']
+ self.password = server['admin_password']
+ self.password = 'password'
+ self.created_server_ids.append(server_id)
+ return server_id
+
+ def _volume_clean_up(self, server_id, volume_id):
+ resp, body = self.volumes_client.get_volume(volume_id)
+ if body['status'] == 'in-use':
+ self.servers_client.detach_volume(server_id, volume_id)
+ self.volumes_client.wait_for_volume_status(volume_id, 'available')
+ self.volumes_client.delete_volume(volume_id)
+
+ @testtools.skipIf(not CONF.compute_feature_enabled.live_migration,
+ 'Live migration not available')
+ @attr(type='gate')
+ def test_live_block_migration(self):
+ # Live block migrate an instance to another host
+ if len(self._get_compute_hostnames()) < 2:
+ raise self.skipTest(
+ "Less than 2 compute nodes, skipping migration test.")
+ server_id = self._get_an_active_server()
+ actual_host = self._get_host_for_server(server_id)
+ target_host = self._get_host_other_than(actual_host)
+ self._migrate_server_to(server_id, target_host)
+ self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
+ self.assertEqual(target_host, self._get_host_for_server(server_id))
+
+ @testtools.skipIf(not CONF.compute_feature_enabled.live_migration,
+ 'Live migration not available')
+ @attr(type='gate')
+ def test_invalid_host_for_migration(self):
+ # Migrating to an invalid host should not change the status
+ server_id = self._get_an_active_server()
+ target_host = self._get_non_existing_host_name()
+
+ self.assertRaises(exceptions.BadRequest, self._migrate_server_to,
+ server_id, target_host)
+ self.assertEqual('ACTIVE', self._get_server_status(server_id))
+
+ @testtools.skipIf(not CONF.compute_feature_enabled.live_migration or not
+ CONF.compute_feature_enabled.
+ block_migration_for_live_migration,
+ 'Block Live migration not available')
+ @testtools.skipIf(not CONF.compute_feature_enabled.
+ block_migrate_cinder_iscsi,
+ 'Block Live migration not configured for iSCSI')
+ @attr(type='gate')
+ def test_iscsi_volume(self):
+ # Live block migrate an instance to another host
+ if len(self._get_compute_hostnames()) < 2:
+ raise self.skipTest(
+ "Less than 2 compute nodes, skipping migration test.")
+ server_id = self._get_an_active_server()
+ actual_host = self._get_host_for_server(server_id)
+ target_host = self._get_host_other_than(actual_host)
+
+ resp, volume = self.volumes_client.create_volume(1,
+ display_name='test')
+
+ self.volumes_client.wait_for_volume_status(volume['id'],
+ 'available')
+ self.addCleanup(self._volume_clean_up, server_id, volume['id'])
+
+ # Attach the volume to the server
+ self.servers_client.attach_volume(server_id, volume['id'],
+ device='/dev/xvdb')
+ self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
+
+ self._migrate_server_to(server_id, target_host)
+ self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
+ self.assertEqual(target_host, self._get_host_for_server(server_id))
+
+ @classmethod
+ def tearDownClass(cls):
+ for server_id in cls.created_server_ids:
+ cls.servers_client.delete_server(server_id)
+
+ super(LiveBlockMigrationV3TestJSON, cls).tearDownClass()
+
+
+class LiveBlockMigrationV3TestXML(LiveBlockMigrationV3TestJSON):
+ _host_key = (
+ '{http://docs.openstack.org/compute/ext/'
+ 'extended_server_attributes/api/v3}host')
+ _interface = 'xml'
diff --git a/tempest/api/compute/v3/test_quotas.py b/tempest/api/compute/v3/test_quotas.py
index 475d055..d2f80a5 100644
--- a/tempest/api/compute/v3/test_quotas.py
+++ b/tempest/api/compute/v3/test_quotas.py
@@ -16,29 +16,27 @@
# under the License.
from tempest.api.compute import base
-from tempest.test import attr
+from tempest import test
-class QuotasTestJSON(base.BaseV2ComputeTest):
+class QuotasV3TestJSON(base.BaseV3ComputeTest):
_interface = 'json'
@classmethod
def setUpClass(cls):
- super(QuotasTestJSON, cls).setUpClass()
+ super(QuotasV3TestJSON, cls).setUpClass()
cls.client = cls.quotas_client
cls.admin_client = cls._get_identity_admin_client()
resp, tenants = cls.admin_client.list_tenants()
cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
cls.client.tenant_name][0]
- cls.default_quota_set = set(('injected_file_content_bytes',
- 'metadata_items', 'injected_files',
+ cls.default_quota_set = set(('metadata_items',
'ram', 'floating_ips',
'fixed_ips', 'key_pairs',
- 'injected_file_path_bytes',
'instances', 'security_group_rules',
'cores', 'security_groups'))
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_get_quotas(self):
# User can get the quota set for it's tenant
expected_quota_set = self.default_quota_set | set(['id'])
@@ -48,7 +46,7 @@
sorted(quota_set.keys()))
self.assertEqual(quota_set['id'], self.tenant_id)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_get_default_quotas(self):
# User can get the default quota set for it's tenant
expected_quota_set = self.default_quota_set | set(['id'])
@@ -58,7 +56,7 @@
sorted(quota_set.keys()))
self.assertEqual(quota_set['id'], self.tenant_id)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_compare_tenant_quotas_with_default_quotas(self):
# Tenants are created with the default quota values
resp, defualt_quota_set = \
@@ -69,5 +67,5 @@
self.assertEqual(defualt_quota_set, tenant_quota_set)
-class QuotasTestXML(QuotasTestJSON):
+class QuotasV3TestXML(QuotasV3TestJSON):
_interface = 'xml'
diff --git a/tempest/api/identity/admin/test_services.py b/tempest/api/identity/admin/test_services.py
index 7fe5171..872adb8 100644
--- a/tempest/api/identity/admin/test_services.py
+++ b/tempest/api/identity/admin/test_services.py
@@ -25,47 +25,47 @@
class ServicesTestJSON(base.BaseIdentityAdminTest):
_interface = 'json'
+ def _del_service(self, service_id):
+ # Deleting the service created in this method
+ resp, _ = self.client.delete_service(service_id)
+ self.assertEqual(resp['status'], '204')
+ # Checking whether service is deleted successfully
+ self.assertRaises(exceptions.NotFound, self.client.get_service,
+ service_id)
+
@attr(type='smoke')
def test_create_get_delete_service(self):
# GET Service
- try:
- # Creating a Service
- name = data_utils.rand_name('service-')
- type = data_utils.rand_name('type--')
- description = data_utils.rand_name('description-')
- resp, service_data = self.client.create_service(
- name, type, description=description)
- self.assertTrue(resp['status'].startswith('2'))
- # Verifying response body of create service
- self.assertIn('id', service_data)
- self.assertFalse(service_data['id'] is None)
- self.assertIn('name', service_data)
- self.assertEqual(name, service_data['name'])
- self.assertIn('type', service_data)
- self.assertEqual(type, service_data['type'])
- self.assertIn('description', service_data)
- self.assertEqual(description, service_data['description'])
- # Get service
- resp, fetched_service = self.client.get_service(service_data['id'])
- self.assertTrue(resp['status'].startswith('2'))
- # verifying the existence of service created
- self.assertIn('id', fetched_service)
- self.assertEqual(fetched_service['id'], service_data['id'])
- self.assertIn('name', fetched_service)
- self.assertEqual(fetched_service['name'], service_data['name'])
- self.assertIn('type', fetched_service)
- self.assertEqual(fetched_service['type'], service_data['type'])
- self.assertIn('description', fetched_service)
- self.assertEqual(fetched_service['description'],
- service_data['description'])
- finally:
- if 'service_data' in locals():
- # Deleting the service created in this method
- resp, _ = self.client.delete_service(service_data['id'])
- self.assertEqual(resp['status'], '204')
- # Checking whether service is deleted successfully
- self.assertRaises(exceptions.NotFound, self.client.get_service,
- service_data['id'])
+ # Creating a Service
+ name = data_utils.rand_name('service-')
+ type = data_utils.rand_name('type--')
+ description = data_utils.rand_name('description-')
+ resp, service_data = self.client.create_service(
+ name, type, description=description)
+ self.assertFalse(service_data['id'] is None)
+ self.addCleanup(self._del_service, service_data['id'])
+ self.assertTrue(resp['status'].startswith('2'))
+ # Verifying response body of create service
+ self.assertIn('id', service_data)
+ self.assertIn('name', service_data)
+ self.assertEqual(name, service_data['name'])
+ self.assertIn('type', service_data)
+ self.assertEqual(type, service_data['type'])
+ self.assertIn('description', service_data)
+ self.assertEqual(description, service_data['description'])
+ # Get service
+ resp, fetched_service = self.client.get_service(service_data['id'])
+ self.assertTrue(resp['status'].startswith('2'))
+ # verifying the existence of service created
+ self.assertIn('id', fetched_service)
+ self.assertEqual(fetched_service['id'], service_data['id'])
+ self.assertIn('name', fetched_service)
+ self.assertEqual(fetched_service['name'], service_data['name'])
+ self.assertIn('type', fetched_service)
+ self.assertEqual(fetched_service['type'], service_data['type'])
+ self.assertIn('description', fetched_service)
+ self.assertEqual(fetched_service['description'],
+ service_data['description'])
@attr(type='smoke')
def test_list_services(self):
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 5e13a5a..e1d28d7 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -12,10 +12,13 @@
# License for the specific language governing permissions and limitations
# under the License.
+import datetime
+import re
from tempest.api.identity import base
from tempest import clients
from tempest.common.utils.data_utils import rand_name
from tempest import exceptions
+from tempest.openstack.common import timeutils
from tempest.test import attr
@@ -115,7 +118,15 @@
summary=False):
self.assertIsNotNone(trust['id'])
self.assertEqual(impersonate, trust['impersonation'])
- self.assertEqual(expires, trust['expires_at'])
+ # FIXME(shardy): ref bug #1246383 we can't check the
+ # microsecond component of the expiry time, because mysql
+ # <5.6.4 doesn't support microseconds.
+ # expected format 2013-12-20T16:08:36.036987Z
+ if expires is not None:
+ expires_nousec = re.sub(r'\.([0-9]){6}Z', '', expires)
+ self.assertTrue(trust['expires_at'].startswith(expires_nousec))
+ else:
+ self.assertIsNone(trust['expires_at'])
self.assertEqual(self.trustor_user_id, trust['trustor_user_id'])
self.assertEqual(self.trustee_user_id, trust['trustee_user_id'])
self.assertIn('v3/OS-TRUST/trusts', trust['links']['self'])
@@ -212,6 +223,24 @@
self.delete_trust()
@attr(type='smoke')
+ def test_trust_expire(self):
+ # Test case to check we can create, get and delete a trust
+ # with an expiry specified
+ expires_at = timeutils.utcnow() + datetime.timedelta(hours=1)
+ expires_str = timeutils.isotime(at=expires_at, subsecond=True)
+
+ trust = self.create_trust(expires=expires_str)
+ self.validate_trust(trust, expires=expires_str)
+
+ trust_get = self.get_trust()
+
+ self.validate_trust(trust_get, expires=expires_str)
+
+ self.check_trust_roles()
+
+ self.delete_trust()
+
+ @attr(type='smoke')
def test_trust_expire_invalid(self):
# Test case to check we can check an invlaid expiry time
# is rejected with the correct error
@@ -220,3 +249,22 @@
self.assertRaises(exceptions.BadRequest,
self.create_trust,
expires=expires_str)
+
+ @attr(type='smoke')
+ def test_get_trusts_query(self):
+ self.create_trust()
+ resp, trusts_get = self.trustor_v3_client.get_trusts(
+ trustor_user_id=self.trustor_user_id)
+ self.assertEqual('200', resp['status'])
+ self.assertEqual(1, len(trusts_get))
+ self.validate_trust(trusts_get[0], summary=True)
+
+ @attr(type='smoke')
+ def test_get_trusts_all(self):
+ self.create_trust()
+ resp, trusts_get = self.v3_client.get_trusts()
+ self.assertEqual('200', resp['status'])
+ trusts = [t for t in trusts_get
+ if t['id'] == self.trust_id]
+ self.assertEqual(1, len(trusts))
+ self.validate_trust(trusts[0], summary=True)
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 318d891..dcad101 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -66,6 +66,7 @@
cls.health_monitors = []
cls.vpnservices = []
cls.ikepolicies = []
+ cls.floating_ips = []
@classmethod
def tearDownClass(cls):
@@ -75,6 +76,9 @@
# Clean up vpn services
for vpnservice in cls.vpnservices:
cls.client.delete_vpnservice(vpnservice['id'])
+ # Clean up floating IPs
+ for floating_ip in cls.floating_ips:
+ cls.client.delete_floating_ip(floating_ip['id'])
# Clean up routers
for router in cls.routers:
resp, body = cls.client.list_router_interfaces(router['id'])
@@ -167,6 +171,16 @@
return router
@classmethod
+ def create_floating_ip(cls, external_network_id, **kwargs):
+ """Wrapper utility that returns a test floating IP."""
+ resp, body = cls.client.create_floating_ip(
+ external_network_id,
+ **kwargs)
+ fip = body['floatingip']
+ cls.floating_ips.append(fip)
+ return fip
+
+ @classmethod
def create_pool(cls, name, lb_method, protocol, subnet):
"""Wrapper utility that returns a test pool."""
resp, body = cls.client.create_pool(
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index 7ce8ca6..6f3fa4b 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -32,6 +32,9 @@
Delete a Floating IP
List all Floating IPs
Show Floating IP details
+ Associate a Floating IP with a port and then delete that port
+ Associate a Floating IP with a port and then with a port on another
+ router
v2.0 of the Neutron API is assumed. It is also assumed that the following
options are defined in the [network] section of etc/tempest.conf:
@@ -55,31 +58,17 @@
for i in range(2):
cls.create_port(cls.network)
- def _delete_floating_ip(self, floating_ip_id):
- # Deletes a floating IP and verifies if it is deleted or not
- resp, _ = self.client.delete_floatingip(floating_ip_id)
- self.assertEqual(204, resp.status)
- # Asserting that the floating_ip is not found in list after deletion
- resp, floating_ips = self.client.list_floatingips()
- floatingip_id_list = list()
- for f in floating_ips['floatingips']:
- floatingip_id_list.append(f['id'])
- self.assertNotIn(floating_ip_id, floatingip_id_list)
-
@attr(type='smoke')
def test_create_list_show_update_delete_floating_ip(self):
# Creates a floating IP
- resp, floating_ip = self.client.create_floating_ip(
+ created_floating_ip = self.create_floating_ip(
self.ext_net_id, port_id=self.ports[0]['id'])
- self.assertEqual('201', resp['status'])
- created_floating_ip = floating_ip['floatingip']
self.assertIsNotNone(created_floating_ip['id'])
self.assertIsNotNone(created_floating_ip['tenant_id'])
self.assertIsNotNone(created_floating_ip['floating_ip_address'])
self.assertEqual(created_floating_ip['port_id'], self.ports[0]['id'])
self.assertEqual(created_floating_ip['floating_network_id'],
self.ext_net_id)
- self.addCleanup(self._delete_floating_ip, created_floating_ip['id'])
# Verifies the details of a floating_ip
resp, floating_ip = self.client.show_floating_ip(
created_floating_ip['id'])
@@ -120,6 +109,51 @@
self.assertIsNone(updated_floating_ip['fixed_ip_address'])
self.assertIsNone(updated_floating_ip['router_id'])
+ @attr(type='smoke')
+ def test_floating_ip_delete_port(self):
+ # Create a floating IP
+ created_floating_ip = self.create_floating_ip(self.ext_net_id)
+ # Create a port
+ resp, port = self.client.create_port(self.network['id'])
+ created_port = port['port']
+ resp, floating_ip = self.client.update_floating_ip(
+ created_floating_ip['id'], port_id=created_port['id'])
+ self.assertEqual('200', resp['status'])
+ # Delete port
+ self.client.delete_port(created_port['id'])
+ # Verifies the details of the floating_ip
+ resp, floating_ip = self.client.show_floating_ip(
+ created_floating_ip['id'])
+ self.assertEqual('200', resp['status'])
+ shown_floating_ip = floating_ip['floatingip']
+ # Confirm the fields are back to None
+ self.assertEqual(shown_floating_ip['id'], created_floating_ip['id'])
+ self.assertIsNone(shown_floating_ip['port_id'])
+ self.assertIsNone(shown_floating_ip['fixed_ip_address'])
+ self.assertIsNone(shown_floating_ip['router_id'])
+
+ @attr(type='smoke')
+ def test_floating_ip_update_different_router(self):
+ # Associate a floating IP to a port on a router
+ created_floating_ip = self.create_floating_ip(
+ self.ext_net_id, port_id=self.ports[1]['id'])
+ self.assertEqual(created_floating_ip['router_id'], self.router['id'])
+ network2 = self.create_network()
+ subnet2 = self.create_subnet(network2)
+ router2 = self.create_router(data_utils.rand_name('router-'),
+ external_network_id=self.ext_net_id)
+ 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
+ resp, floating_ip = self.client.update_floating_ip(
+ created_floating_ip['id'], port_id=port_other_router['id'])
+ self.assertEqual('200', resp['status'])
+ updated_floating_ip = floating_ip['floatingip']
+ self.assertEqual(updated_floating_ip['router_id'], router2['id'])
+ self.assertEqual(updated_floating_ip['port_id'],
+ port_other_router['id'])
+ self.assertIsNotNone(updated_floating_ip['fixed_ip_address'])
+
class FloatingIPTestXML(FloatingIPTestJSON):
_interface = 'xml'
diff --git a/tempest/api/object_storage/test_object_temp_url.py b/tempest/api/object_storage/test_object_temp_url.py
index 9d5a1c0..d0e5353 100644
--- a/tempest/api/object_storage/test_object_temp_url.py
+++ b/tempest/api/object_storage/test_object_temp_url.py
@@ -39,27 +39,36 @@
def setUpClass(cls):
super(ObjectTempUrlTest, cls).setUpClass()
- # skip this test if CORS isn't enabled in the conf file.
+ # skip this test if TempUrl isn't enabled in the conf file.
if not cls.tempurl_available:
skip_msg = ("%s skipped as TempUrl middleware not available"
% cls.__name__)
raise cls.skipException(skip_msg)
+ # create a container
cls.container_name = data_utils.rand_name(name='TestContainer')
cls.container_client.create_container(cls.container_name)
cls.containers = [cls.container_name]
# update account metadata
cls.key = 'Meta'
+ cls.metadatas = []
cls.metadata = {'Temp-URL-Key': cls.key}
+ cls.metadatas.append(cls.metadata)
cls.account_client.create_account_metadata(metadata=cls.metadata)
- cls.account_client_metadata, _ = \
- cls.account_client.list_account_metadata()
+
+ # create an object
+ cls.object_name = data_utils.rand_name(name='ObjectTemp')
+ cls.content = data_utils.arbitrary_string(size=len(cls.object_name),
+ base_text=cls.object_name)
+ cls.object_client.create_object(cls.container_name,
+ cls.object_name, cls.content)
@classmethod
def tearDownClass(cls):
- resp, _ = cls.account_client.delete_account_metadata(
- metadata=cls.metadata)
+ for metadata in cls.metadata:
+ cls.account_client.delete_account_metadata(
+ metadata=metadata)
cls.delete_containers(cls.containers)
@@ -69,21 +78,16 @@
def setUp(self):
super(ObjectTempUrlTest, self).setUp()
+
# make sure the metadata has been set
+ account_client_metadata, _ = \
+ self.account_client.list_account_metadata()
self.assertIn('x-account-meta-temp-url-key',
- self.account_client_metadata)
-
+ account_client_metadata)
self.assertEqual(
- self.account_client_metadata['x-account-meta-temp-url-key'],
+ account_client_metadata['x-account-meta-temp-url-key'],
self.key)
- # create object
- self.object_name = data_utils.rand_name(name='ObjectTemp')
- self.data = data_utils.arbitrary_string(size=len(self.object_name),
- base_text=self.object_name)
- self.object_client.create_object(self.container_name,
- self.object_name, self.data)
-
def _get_expiry_date(self, expiration_time=1000):
return int(time.time() + expiration_time)
@@ -114,10 +118,10 @@
expires, self.key)
# trying to get object using temp url within expiry time
- resp, body = self.object_client.get_object_using_temp_url(url)
+ resp, body = self.object_client.get(url)
self.assertIn(int(resp['status']), HTTP_SUCCESS)
self.assertHeaders(resp, 'Object', 'GET')
- self.assertEqual(body, self.data)
+ self.assertEqual(body, self.content)
# Testing a HEAD on this Temp URL
resp, body = self.object_client.head(url)
@@ -129,23 +133,27 @@
key2 = 'Meta2-'
metadata = {'Temp-URL-Key-2': key2}
self.account_client.create_account_metadata(metadata=metadata)
+ self.metadatas.append(metadata)
- self.account_client_metadata, _ = \
+ # make sure the metadata has been set
+ account_client_metadata, _ = \
self.account_client.list_account_metadata()
self.assertIn('x-account-meta-temp-url-key-2',
- self.account_client_metadata)
+ account_client_metadata)
+ self.assertEqual(
+ account_client_metadata['x-account-meta-temp-url-key-2'],
+ key2)
expires = self._get_expiry_date()
url = self._get_temp_url(self.container_name,
self.object_name, "GET",
expires, key2)
- resp, body = self.object_client.get_object_using_temp_url(url)
+ resp, body = self.object_client.get(url)
self.assertIn(int(resp['status']), HTTP_SUCCESS)
- self.assertEqual(body, self.data)
+ self.assertEqual(body, self.content)
@attr(type='gate')
def test_put_object_using_temp_url(self):
- # make sure the metadata has been set
new_data = data_utils.arbitrary_string(
size=len(self.object_name),
base_text=data_utils.rand_name(name="random"))
@@ -156,9 +164,7 @@
expires, self.key)
# trying to put random data in the object using temp url
- resp, body = self.object_client.put_object_using_temp_url(
- url, new_data)
-
+ resp, body = self.object_client.put(url, new_data, None)
self.assertIn(int(resp['status']), HTTP_SUCCESS)
self.assertHeaders(resp, 'Object', 'PUT')
@@ -172,9 +178,23 @@
self.object_name, "GET",
expires, self.key)
- _, body = self.object_client.get_object_using_temp_url(url)
+ _, body = self.object_client.get(url)
self.assertEqual(body, new_data)
+ @attr(type='gate')
+ def test_head_object_using_temp_url(self):
+ expires = self._get_expiry_date()
+
+ # get a temp URL for the created object
+ url = self._get_temp_url(self.container_name,
+ self.object_name, "HEAD",
+ expires, self.key)
+
+ # Testing a HEAD on this Temp URL
+ resp, body = self.object_client.head(url)
+ self.assertIn(int(resp['status']), HTTP_SUCCESS)
+ self.assertHeaders(resp, 'Object', 'HEAD')
+
@attr(type=['gate', 'negative'])
def test_get_object_after_expiration_time(self):
@@ -188,5 +208,4 @@
time.sleep(2)
self.assertRaises(exceptions.Unauthorized,
- self.object_client.get_object_using_temp_url,
- url)
+ self.object_client.get, url)
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index f3ef99f..b6c03e0 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -12,8 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import time
-
from tempest import clients
from tempest.common.utils import data_utils
from tempest.openstack.common import log as logging
@@ -118,21 +116,6 @@
cls.clear_keypairs()
super(BaseOrchestrationTest, cls).tearDownClass()
- def wait_for(self, condition):
- """Repeatedly calls condition() until a timeout."""
- start_time = int(time.time())
- while True:
- try:
- condition()
- except Exception:
- pass
- else:
- return
- if int(time.time()) - start_time >= self.build_timeout:
- condition()
- return
- time.sleep(self.build_interval)
-
@staticmethod
def stack_output(stack, output_key):
"""Return a stack output value for a give key."""
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index d63fd8b..9c841cc 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -15,9 +15,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import time
-
from tempest import clients
+from tempest.common.utils import data_utils
from tempest.openstack.common import log as logging
import tempest.test
@@ -73,7 +72,10 @@
@classmethod
def create_volume(cls, size=1, **kwargs):
"""Wrapper utility that returns a test volume."""
- resp, volume = cls.volumes_client.create_volume(size, **kwargs)
+ vol_name = data_utils.rand_name('Volume')
+ resp, volume = cls.volumes_client.create_volume(size,
+ display_name=vol_name,
+ **kwargs)
assert 200 == resp.status
cls.volumes.append(volume)
cls.volumes_client.wait_for_volume_status(volume['id'], 'available')
@@ -107,21 +109,6 @@
except Exception:
pass
- def wait_for(self, condition):
- """Repeatedly calls condition() until a timeout."""
- start_time = int(time.time())
- while True:
- try:
- condition()
- except Exception:
- pass
- else:
- return
- if int(time.time()) - start_time >= self.build_timeout:
- condition()
- return
- time.sleep(self.build_interval)
-
class BaseVolumeV1Test(BaseVolumeTest):
@classmethod
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index 71e9f85..34eab00 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -17,7 +17,6 @@
from tempest.api.volume import base
from tempest import clients
-from tempest.common.utils.data_utils import rand_name
from tempest.test import attr
@@ -61,10 +60,7 @@
@attr(type='gate')
def test_create_get_list_accept_volume_transfer(self):
# Create a volume first
- vol_name = rand_name('-Volume-')
- _, volume = self.client.create_volume(size=1, display_name=vol_name)
- self.addCleanup(self.adm_client.delete_volume, volume['id'])
- self.client.wait_for_volume_status(volume['id'], 'available')
+ volume = self.create_volume()
# Create a volume transfer
resp, transfer = self.client.create_volume_transfer(volume['id'])
@@ -93,10 +89,7 @@
def test_create_list_delete_volume_transfer(self):
# Create a volume first
- vol_name = rand_name('-Volume-')
- _, volume = self.client.create_volume(size=1, display_name=vol_name)
- self.addCleanup(self.adm_client.delete_volume, volume['id'])
- self.client.wait_for_volume_status(volume['id'], 'available')
+ volume = self.create_volume()
# Create a volume transfer
resp, body = self.client.create_volume_transfer(volume['id'])
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index 61f1bda..7a7ead6 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -31,24 +31,19 @@
cls.client = cls.volumes_client
cls.image_client = cls.os.image_client
- # Create a test shared instance and volume for attach/detach tests
+ # Create a test shared instance
srv_name = data_utils.rand_name(cls.__name__ + '-Instance-')
- vol_name = data_utils.rand_name(cls.__name__ + '-Volume-')
resp, cls.server = cls.servers_client.create_server(srv_name,
cls.image_ref,
cls.flavor_ref)
cls.servers_client.wait_for_server_status(cls.server['id'], 'ACTIVE')
- resp, cls.volume = cls.client.create_volume(size=1,
- display_name=vol_name)
- cls.client.wait_for_volume_status(cls.volume['id'], 'available')
+ # Create a test shared volume for attach/detach tests
+ cls.volume = cls.create_volume()
@classmethod
def tearDownClass(cls):
- # Delete the test instance and volume
- cls.client.delete_volume(cls.volume['id'])
- cls.client.wait_for_resource_deletion(cls.volume['id'])
-
+ # Delete the test instance
cls.servers_client.delete_server(cls.server['id'])
cls.client.wait_for_resource_deletion(cls.server['id'])
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 6d1c25a..e342563 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -117,17 +117,10 @@
@attr(type='gate')
def test_volume_get_metadata_none(self):
# Create a volume without passing metadata, get details, and delete
- volume = {}
- v_name = data_utils.rand_name('Volume-')
+
# Create a volume without metadata
- resp, volume = self.client.create_volume(size=1,
- display_name=v_name,
- metadata={})
- self.assertEqual(200, resp.status)
- self.assertIn('id', volume)
- self.addCleanup(self._delete_volume, volume['id'])
- self.assertIn('display_name', volume)
- self.client.wait_for_volume_status(volume['id'], 'available')
+ volume = self.create_volume(metadata={})
+
# GET Volume
resp, fetched_volume = self.client.get_volume(volume['id'])
self.assertEqual(200, resp.status)
@@ -145,8 +138,7 @@
@attr(type='gate')
def test_volume_create_get_update_delete_as_clone(self):
- origin = self.create_volume(size=1,
- display_name="Volume Origin")
+ origin = self.create_volume()
self._volume_create_get_update_delete(source_volid=origin['id'])
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index c624a3a..49a2f74 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -66,17 +66,15 @@
cls.volume_id_list = []
cls.metadata = {'Type': 'work'}
for i in range(3):
- v_name = data_utils.rand_name('volume')
try:
- resp, volume = cls.client.create_volume(size=1,
- display_name=v_name,
- metadata=cls.metadata)
- cls.client.wait_for_volume_status(volume['id'], 'available')
+ volume = cls.create_volume(metadata=cls.metadata)
+
resp, volume = cls.client.get_volume(volume['id'])
cls.volume_list.append(volume)
cls.volume_id_list.append(volume['id'])
- except Exception as exc:
- LOG.exception(exc)
+ except Exception:
+ LOG.exception('Failed to create volume. %d volumes were '
+ 'created' % len(cls.volume_id_list))
if cls.volume_list:
# We could not create all the volumes, though we were able
# to create *some* of the volumes. This is typically
@@ -85,7 +83,7 @@
for volid in cls.volume_id_list:
cls.client.delete_volume(volid)
cls.client.wait_for_resource_deletion(volid)
- raise exc
+ raise
@classmethod
def tearDownClass(cls):
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 869aedb..f14cfdc 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -32,10 +32,7 @@
cls.client = cls.volumes_client
# Create a test shared instance and volume for attach/detach tests
- vol_name = data_utils.rand_name('Volume-')
-
- cls.volume = cls.create_volume(size=1, display_name=vol_name)
- cls.client.wait_for_volume_status(cls.volume['id'], 'available')
+ cls.volume = cls.create_volume()
cls.mountpoint = "/dev/vdc"
@attr(type=['negative', 'gate'])
diff --git a/tempest/cli/simple_read_only/test_ceilometer.py b/tempest/cli/simple_read_only/test_ceilometer.py
index 7f2864f..8bdd633 100644
--- a/tempest/cli/simple_read_only/test_ceilometer.py
+++ b/tempest/cli/simple_read_only/test_ceilometer.py
@@ -49,3 +49,6 @@
def test_ceilometermeter_alarm_list(self):
self.ceilometer('alarm-list')
+
+ def test_ceilometer_version(self):
+ self.ceilometer('', flags='--version')
diff --git a/tempest/clients.py b/tempest/clients.py
index f4548d5..83b72c6 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -66,6 +66,8 @@
InterfacesV3ClientJSON
from tempest.services.compute.v3.json.keypairs_client import \
KeyPairsV3ClientJSON
+from tempest.services.compute.v3.json.quotas_client import \
+ QuotasV3ClientJSON
from tempest.services.compute.v3.json.servers_client import \
ServersV3ClientJSON
from tempest.services.compute.v3.json.services_client import \
@@ -87,6 +89,8 @@
from tempest.services.compute.v3.xml.interfaces_client import \
InterfacesV3ClientXML
from tempest.services.compute.v3.xml.keypairs_client import KeyPairsV3ClientXML
+from tempest.services.compute.v3.xml.quotas_client import \
+ QuotasV3ClientXML
from tempest.services.compute.v3.xml.servers_client import ServersV3ClientXML
from tempest.services.compute.v3.xml.services_client import \
ServicesV3ClientXML
@@ -234,7 +238,9 @@
self.images_client = ImagesClientXML(*client_args)
self.keypairs_v3_client = KeyPairsV3ClientXML(*client_args)
self.keypairs_client = KeyPairsClientXML(*client_args)
+ self.keypairs_v3_client = KeyPairsV3ClientXML(*client_args)
self.quotas_client = QuotasClientXML(*client_args)
+ self.quotas_v3_client = QuotasV3ClientXML(*client_args)
self.flavors_client = FlavorsClientXML(*client_args)
self.flavors_v3_client = FlavorsV3ClientXML(*client_args)
self.extensions_v3_client = ExtensionsV3ClientXML(*client_args)
@@ -294,7 +300,9 @@
self.images_client = ImagesClientJSON(*client_args)
self.keypairs_v3_client = KeyPairsV3ClientJSON(*client_args)
self.keypairs_client = KeyPairsClientJSON(*client_args)
+ self.keypairs_v3_client = KeyPairsV3ClientJSON(*client_args)
self.quotas_client = QuotasClientJSON(*client_args)
+ self.quotas_v3_client = QuotasV3ClientJSON(*client_args)
self.flavors_client = FlavorsClientJSON(*client_args)
self.flavors_v3_client = FlavorsV3ClientJSON(*client_args)
self.extensions_v3_client = ExtensionsV3ClientJSON(*client_args)
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 33dd6c0..3618a14 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -227,10 +227,10 @@
for ip_address in ip_addresses:
self._check_vm_connectivity(ip_address, ssh_login,
key.private_key)
- except Exception as exc:
- LOG.exception(exc)
+ except Exception:
+ LOG.exception('Tenant connectivity check failed')
debug.log_ip_ns()
- raise exc
+ raise
def _wait_for_floating_ip_association(self):
ip_tracker = FloatingIPCheckTracker(self.compute_client,
@@ -263,10 +263,10 @@
ssh_login,
private_key,
should_connect=should_connect)
- except Exception as exc:
- LOG.exception(exc)
+ except Exception:
+ LOG.exception('Public network connectivity check failed')
debug.log_ip_ns()
- raise exc
+ raise
def _disassociate_floating_ips(self):
for floating_ip, server in self.floating_ips.iteritems():
diff --git a/tempest/services/compute/v3/json/quotas_client.py b/tempest/services/compute/v3/json/quotas_client.py
index a910dec..cae2332 100644
--- a/tempest/services/compute/v3/json/quotas_client.py
+++ b/tempest/services/compute/v3/json/quotas_client.py
@@ -20,12 +20,12 @@
from tempest.common.rest_client import RestClient
-class QuotasClientJSON(RestClient):
+class QuotasV3ClientJSON(RestClient):
def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(QuotasClientJSON, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_type
+ super(QuotasV3ClientJSON, self).__init__(config, username, password,
+ auth_url, tenant_name)
+ self.service = self.config.compute.catalog_v3_type
def get_quota_set(self, tenant_id):
"""List the quota set for a tenant."""
@@ -44,11 +44,9 @@
return resp, body['quota_set']
def update_quota_set(self, tenant_id, force=None,
- injected_file_content_bytes=None,
metadata_items=None, ram=None, floating_ips=None,
fixed_ips=None, key_pairs=None, instances=None,
- security_group_rules=None, injected_files=None,
- cores=None, injected_file_path_bytes=None,
+ security_group_rules=None, cores=None,
security_groups=None):
"""
Updates the tenant's quota limits for one or more resources
@@ -58,10 +56,6 @@
if force is not None:
post_body['force'] = force
- if injected_file_content_bytes is not None:
- post_body['injected_file_content_bytes'] = \
- injected_file_content_bytes
-
if metadata_items is not None:
post_body['metadata_items'] = metadata_items
@@ -83,15 +77,9 @@
if security_group_rules is not None:
post_body['security_group_rules'] = security_group_rules
- if injected_files is not None:
- post_body['injected_files'] = injected_files
-
if cores is not None:
post_body['cores'] = cores
- if injected_file_path_bytes is not None:
- post_body['injected_file_path_bytes'] = injected_file_path_bytes
-
if security_groups is not None:
post_body['security_groups'] = security_groups
diff --git a/tempest/services/compute/v3/json/servers_client.py b/tempest/services/compute/v3/json/servers_client.py
index a486801..da31036 100644
--- a/tempest/services/compute/v3/json/servers_client.py
+++ b/tempest/services/compute/v3/json/servers_client.py
@@ -93,8 +93,8 @@
body = json.loads(body)
# NOTE(maurosr): this deals with the case of multiple server create
# with return reservation id set True
- if 'reservation_id' in body:
- return resp, body
+ if 'servers_reservation' in body:
+ return resp, body['servers_reservation']
return resp, body['server']
def update_server(self, server_id, name=None, meta=None, access_ip_v4=None,
@@ -117,10 +117,10 @@
post_body['name'] = name
if access_ip_v4 is not None:
- post_body['access_ip_v4'] = access_ip_v4
+ post_body['os-access-ips:access_ip_v4'] = access_ip_v4
if access_ip_v6 is not None:
- post_body['access_ip_v6'] = access_ip_v6
+ post_body['os-access-ips:access_ip_v6'] = access_ip_v6
if disk_config is not None:
post_body['os-disk-config:disk_config'] = disk_config
diff --git a/tempest/services/compute/v3/xml/quotas_client.py b/tempest/services/compute/v3/xml/quotas_client.py
index ef5362c..7ef2274 100644
--- a/tempest/services/compute/v3/xml/quotas_client.py
+++ b/tempest/services/compute/v3/xml/quotas_client.py
@@ -21,15 +21,15 @@
from tempest.services.compute.xml.common import Document
from tempest.services.compute.xml.common import Element
from tempest.services.compute.xml.common import xml_to_json
-from tempest.services.compute.xml.common import XMLNS_11
+from tempest.services.compute.xml.common import XMLNS_V3
-class QuotasClientXML(RestClientXML):
+class QuotasV3ClientXML(RestClientXML):
def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(QuotasClientXML, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_type
+ super(QuotasV3ClientXML, self).__init__(config, username, password,
+ auth_url, tenant_name)
+ self.service = self.config.compute.catalog_v3_type
def _format_quota(self, q):
quota = {}
@@ -65,25 +65,19 @@
return resp, body
def update_quota_set(self, tenant_id, force=None,
- injected_file_content_bytes=None,
metadata_items=None, ram=None, floating_ips=None,
fixed_ips=None, key_pairs=None, instances=None,
- security_group_rules=None, injected_files=None,
- cores=None, injected_file_path_bytes=None,
+ security_group_rules=None, cores=None,
security_groups=None):
"""
Updates the tenant's quota limits for one or more resources
"""
post_body = Element("quota_set",
- xmlns=XMLNS_11)
+ xmlns=XMLNS_V3)
if force is not None:
post_body.add_attr('force', force)
- if injected_file_content_bytes is not None:
- post_body.add_attr('injected_file_content_bytes',
- injected_file_content_bytes)
-
if metadata_items is not None:
post_body.add_attr('metadata_items', metadata_items)
@@ -105,16 +99,9 @@
if security_group_rules is not None:
post_body.add_attr('security_group_rules', security_group_rules)
- if injected_files is not None:
- post_body.add_attr('injected_files', injected_files)
-
if cores is not None:
post_body.add_attr('cores', cores)
- if injected_file_path_bytes is not None:
- post_body.add_attr('injected_file_path_bytes',
- injected_file_path_bytes)
-
if security_groups is not None:
post_body.add_attr('security_groups', security_groups)
diff --git a/tempest/services/compute/v3/xml/servers_client.py b/tempest/services/compute/v3/xml/servers_client.py
index c3381a3..a5cc291 100644
--- a/tempest/services/compute/v3/xml/servers_client.py
+++ b/tempest/services/compute/v3/xml/servers_client.py
@@ -114,6 +114,10 @@
'/compute/ext/extended_status/api/v3}vm_state')
task_state = ('{http://docs.openstack.org'
'/compute/ext/extended_status/api/v3}task_state')
+ access_ip_v4 = ('{http://docs.openstack.org/compute/ext/'
+ 'os-access-ips/api/v3}access_ip_v4')
+ access_ip_v6 = ('{http://docs.openstack.org/compute/ext/'
+ 'os-access-ips/api/v3}access_ip_v6')
if disk_config in json:
json['os-disk-config:disk_config'] = json.pop(disk_config)
if terminated_at in json:
@@ -129,6 +133,10 @@
json['os-extended-status:vm_state'] = json.pop(vm_state)
if task_state in json:
json['os-extended-status:task_state'] = json.pop(task_state)
+ if access_ip_v4 in json:
+ json['os-access-ips:access_ip_v4'] = json.pop(access_ip_v4)
+ if access_ip_v6 in json:
+ json['os-access-ips:access_ip_v6'] = json.pop(access_ip_v6)
return json
@@ -258,10 +266,14 @@
if name is not None:
server.add_attr("name", name)
+ if access_ip_v4 or access_ip_v6:
+ server.add_attr('xmlns:os-access-ips',
+ "http://docs.openstack.org/compute/ext/"
+ "os-access-ips/api/v3")
if access_ip_v4 is not None:
- server.add_attr("access_ip_v4", access_ip_v4)
+ server.add_attr("os-access-ips:access_ip_v4", access_ip_v4)
if access_ip_v6 is not None:
- server.add_attr("access_ip_v6", access_ip_v6)
+ server.add_attr("os-access-ips:access_ip_v6", access_ip_v6)
if disk_config is not None:
server.add_attr('xmlns:os-disk-config', "http://docs.openstack.org"
"/compute/ext/disk_config/api/v3")
@@ -302,7 +314,6 @@
return_reservation_id: Enable/Disable the return of reservation id.
"""
server = Element("server",
- imageRef=image_ref,
xmlns=XMLNS_V3,
flavor_ref=flavor_ref,
image_ref=image_ref,
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index 9e0adff..5c86d1f 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -134,14 +134,6 @@
resp, body = self.put(url, data, self.headers)
return resp, body
- def get_object_using_temp_url(self, url):
- """Retrieve object's data using temp URL."""
- return self.get(url)
-
- def put_object_using_temp_url(self, url, data):
- """Put data in an object using temp URL."""
- return self.put(url, data, None)
-
class ObjectClientCustomizedHeader(RestClient):
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index 2f7a650..2ce5cce 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -245,20 +245,20 @@
@classmethod
def tearDownClass(cls):
"""Calls the callables added by addResourceCleanUp,
- when you overwire this function dont't forget to call this too.
+ when you overwrite this function don't forget to call this too.
"""
fail_count = 0
trash_keys = sorted(cls._resource_trash_bin, reverse=True)
for key in trash_keys:
(function, pos_args, kw_args) = cls._resource_trash_bin[key]
try:
- LOG.debug("Cleaning up: %s" %
- friendly_function_call_str(function, *pos_args,
- **kw_args))
+ func_name = friendly_function_call_str(function, *pos_args,
+ **kw_args)
+ LOG.debug("Cleaning up: %s" % func_name)
function(*pos_args, **kw_args)
- except BaseException as exc:
+ except BaseException:
fail_count += 1
- LOG.exception(exc)
+ LOG.exception("Cleanup failed %s" % func_name)
finally:
del cls._resource_trash_bin[key]
super(BotoTestCase, cls).tearDownClass()
@@ -428,12 +428,12 @@
try:
bucket.delete_key(obj.key)
obj.close()
- except BaseException as exc:
- LOG.exception(exc)
+ except BaseException:
+ LOG.exception("Failed to delete key %s " % obj.key)
exc_num += 1
conn.delete_bucket(bucket)
- except BaseException as exc:
- LOG.exception(exc)
+ except BaseException:
+ LOG.exception("Failed to destroy bucket %s " % bucket)
exc_num += 1
if exc_num:
raise exceptions.TearDownException(num=exc_num)
@@ -463,8 +463,8 @@
try:
instance.terminate()
re_search_wait(_instance_state, "_GONE")
- except BaseException as exc:
- LOG.exception(exc)
+ except BaseException:
+ LOG.exception("Failed to terminate instance %s " % instance)
exc_num += 1
if exc_num:
raise exceptions.TearDownException(num=exc_num)
@@ -497,8 +497,8 @@
try:
if volume.status != "available":
volume.detach(force=True)
- except BaseException as exc:
- LOG.exception(exc)
+ except BaseException:
+ LOG.exception("Failed to detach volume %s" % volume)
# exc_num += 1 "nonlocal" not in python2
return volume.status
@@ -506,8 +506,8 @@
re_search_wait(_volume_state, "available") # not validates status
LOG.info(_volume_state())
volume.delete()
- except BaseException as exc:
- LOG.exception(exc)
+ except BaseException:
+ LOG.exception("Failed to delete volume %s" % volume)
exc_num += 1
if exc_num:
raise exceptions.TearDownException(num=exc_num)