Merge "Nova V3 API test for resetNetwork/injectNetworkInfo"
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index 4818aa6..6797005 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -26,7 +26,6 @@
"""
_host_key = 'OS-EXT-SRV-ATTR:host'
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/admin/test_aggregates_negative.py b/tempest/api/compute/admin/test_aggregates_negative.py
index 7d92532..3d34d47 100644
--- a/tempest/api/compute/admin/test_aggregates_negative.py
+++ b/tempest/api/compute/admin/test_aggregates_negative.py
@@ -26,8 +26,6 @@
Tests Aggregates API that require admin privileges
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(AggregatesAdminNegativeTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_availability_zone.py b/tempest/api/compute/admin/test_availability_zone.py
index 283a45a..1387261 100644
--- a/tempest/api/compute/admin/test_availability_zone.py
+++ b/tempest/api/compute/admin/test_availability_zone.py
@@ -23,8 +23,6 @@
Tests Availability Zone API List
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(AZAdminTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_availability_zone_negative.py b/tempest/api/compute/admin/test_availability_zone_negative.py
index d13618c..8cc8bce 100644
--- a/tempest/api/compute/admin/test_availability_zone_negative.py
+++ b/tempest/api/compute/admin/test_availability_zone_negative.py
@@ -23,8 +23,6 @@
Tests Availability Zone API List
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(AZAdminNegativeTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_fixed_ips.py b/tempest/api/compute/admin/test_fixed_ips.py
index cfb2f0e..00bb9c3 100644
--- a/tempest/api/compute/admin/test_fixed_ips.py
+++ b/tempest/api/compute/admin/test_fixed_ips.py
@@ -21,7 +21,6 @@
class FixedIPsTestJson(base.BaseV2ComputeAdminTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/admin/test_fixed_ips_negative.py b/tempest/api/compute/admin/test_fixed_ips_negative.py
index def9810..0faedb2 100644
--- a/tempest/api/compute/admin/test_fixed_ips_negative.py
+++ b/tempest/api/compute/admin/test_fixed_ips_negative.py
@@ -21,7 +21,6 @@
class FixedIPsNegativeTestJson(base.BaseV2ComputeAdminTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 3e13bf8..05b763a 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -27,8 +27,6 @@
Tests Flavors API Create and Delete that require admin privileges
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(FlavorsAdminTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_flavors_access.py b/tempest/api/compute/admin/test_flavors_access.py
index da11ab5..4804ce4 100644
--- a/tempest/api/compute/admin/test_flavors_access.py
+++ b/tempest/api/compute/admin/test_flavors_access.py
@@ -25,8 +25,6 @@
Add and remove Flavor Access require admin privileges.
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(FlavorsAccessTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
index c4d54b6..8fe3331 100644
--- a/tempest/api/compute/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -28,8 +28,6 @@
Add and remove Flavor Access require admin privileges.
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(FlavorsAccessNegativeTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index 1afa693..91145ec 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -26,8 +26,6 @@
GET Flavor Extra specs can be performed even by without admin privileges.
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(FlavorsExtraSpecsTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
index cdf97cc..a139c2f 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -27,8 +27,6 @@
SET, UNSET, UPDATE Flavor Extra specs require admin privileges.
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(FlavorsExtraSpecsNegativeTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_flavors_negative.py b/tempest/api/compute/admin/test_flavors_negative.py
index ad4ceeb..49d49ef 100644
--- a/tempest/api/compute/admin/test_flavors_negative.py
+++ b/tempest/api/compute/admin/test_flavors_negative.py
@@ -27,8 +27,6 @@
Tests Flavors API Create and Delete that require admin privileges
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(FlavorsAdminNegativeTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_hosts.py b/tempest/api/compute/admin/test_hosts.py
index a3b4b47..b4b3139 100644
--- a/tempest/api/compute/admin/test_hosts.py
+++ b/tempest/api/compute/admin/test_hosts.py
@@ -23,8 +23,6 @@
Tests hosts API using admin privileges.
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(HostsAdminTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_hosts_negative.py b/tempest/api/compute/admin/test_hosts_negative.py
index cb034c9..0f26e84 100644
--- a/tempest/api/compute/admin/test_hosts_negative.py
+++ b/tempest/api/compute/admin/test_hosts_negative.py
@@ -24,8 +24,6 @@
Tests hosts API using admin privileges.
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(HostsAdminNegativeTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_hypervisor.py b/tempest/api/compute/admin/test_hypervisor.py
index 989c0d8..4e1b289 100644
--- a/tempest/api/compute/admin/test_hypervisor.py
+++ b/tempest/api/compute/admin/test_hypervisor.py
@@ -23,8 +23,6 @@
Tests Hypervisors API that require admin privileges
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(HypervisorAdminTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_hypervisor_negative.py b/tempest/api/compute/admin/test_hypervisor_negative.py
index e41bd18..be0153b 100644
--- a/tempest/api/compute/admin/test_hypervisor_negative.py
+++ b/tempest/api/compute/admin/test_hypervisor_negative.py
@@ -27,8 +27,6 @@
Tests Hypervisors API that require admin privileges
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(HypervisorAdminNegativeTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log.py b/tempest/api/compute/admin/test_instance_usage_audit_log.py
index c617178..13f504f 100644
--- a/tempest/api/compute/admin/test_instance_usage_audit_log.py
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log.py
@@ -22,8 +22,6 @@
class InstanceUsageAuditLogTestJSON(base.BaseV2ComputeAdminTest):
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(InstanceUsageAuditLogTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
index 10bb1aa..e128d0c 100644
--- a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
@@ -23,8 +23,6 @@
class InstanceUsageAuditLogNegativeTestJSON(base.BaseV2ComputeAdminTest):
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(InstanceUsageAuditLogNegativeTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index 81b0328..5af091e 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -19,7 +19,6 @@
class QuotasAdminTestJSON(base.BaseV2ComputeAdminTest):
- _interface = 'json'
force_tenant_isolation = True
@classmethod
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index 4c4acd4..5b2b5fd 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -22,7 +22,6 @@
class QuotasAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
- _interface = 'json'
force_tenant_isolation = True
@classmethod
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index 0cfa344..69ba2c2 100644
--- a/tempest/api/compute/admin/test_security_groups.py
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -24,7 +24,6 @@
class SecurityGroupsTestAdminJSON(base.BaseV2ComputeAdminTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index 8a5f1a5..40a4df7 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -25,7 +25,6 @@
"""
_host_key = 'OS-EXT-SRV-ATTR:host'
- _interface = 'json'
@classmethod
def setUpClass(cls):
@@ -175,6 +174,16 @@
rebuilt_image_id = server['image']['id']
self.assertEqual(self.image_ref_alt, rebuilt_image_id)
+ @test.attr(type='gate')
+ def test_reset_network_inject_network_info(self):
+ # Reset Network of a Server
+ resp, server = self.create_test_server(wait_until='ACTIVE')
+ resp, server_body = self.client.reset_network(server['id'])
+ self.assertEqual(202, resp.status)
+ # Inject the Network Info into Server
+ resp, server_body = self.client.inject_network_info(server['id'])
+ self.assertEqual(202, resp.status)
+
class ServersAdminTestXML(ServersAdminTestJSON):
_host_key = (
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index 9580a06..dff4aaa 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -26,8 +26,6 @@
Tests Servers API using admin privileges
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(ServersAdminNegativeTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_services.py b/tempest/api/compute/admin/test_services.py
index ac800fb..3e45d65 100644
--- a/tempest/api/compute/admin/test_services.py
+++ b/tempest/api/compute/admin/test_services.py
@@ -24,8 +24,6 @@
Tests Services API. List and Enable/Disable require admin privileges.
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(ServicesAdminTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_services_negative.py b/tempest/api/compute/admin/test_services_negative.py
index a1809c4..a4bf754 100644
--- a/tempest/api/compute/admin/test_services_negative.py
+++ b/tempest/api/compute/admin/test_services_negative.py
@@ -23,8 +23,6 @@
Tests Services API. List and Enable/Disable require admin privileges.
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(ServicesAdminNegativeTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage.py b/tempest/api/compute/admin/test_simple_tenant_usage.py
index dcb9aed..2f1391b 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage.py
@@ -22,8 +22,6 @@
class TenantUsagesTestJSON(base.BaseV2ComputeAdminTest):
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(TenantUsagesTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
index 2a30348..4ad3e1a 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
@@ -22,8 +22,6 @@
class TenantUsagesNegativeTestJSON(base.BaseV2ComputeAdminTest):
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(TenantUsagesNegativeTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 9162926..28d50c9 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -206,6 +206,8 @@
class BaseV2ComputeTest(BaseComputeTest):
+ _interface = "json"
+
@classmethod
def setUpClass(cls):
# By default compute tests do not create network resources
diff --git a/tempest/api/compute/certificates/test_certificates.py b/tempest/api/compute/certificates/test_certificates.py
index 79619bc..01fdc7c 100644
--- a/tempest/api/compute/certificates/test_certificates.py
+++ b/tempest/api/compute/certificates/test_certificates.py
@@ -18,7 +18,6 @@
class CertificatesTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@attr(type='gate')
def test_create_and_get_root_certificate(self):
diff --git a/tempest/api/compute/flavors/test_flavors.py b/tempest/api/compute/flavors/test_flavors.py
index b0a7fed..98a8e29 100644
--- a/tempest/api/compute/flavors/test_flavors.py
+++ b/tempest/api/compute/flavors/test_flavors.py
@@ -18,7 +18,6 @@
class FlavorsTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/flavors/test_flavors_negative.py b/tempest/api/compute/flavors/test_flavors_negative.py
index 8ac6182..4ba5023 100644
--- a/tempest/api/compute/flavors/test_flavors_negative.py
+++ b/tempest/api/compute/flavors/test_flavors_negative.py
@@ -24,7 +24,6 @@
class FlavorsListNegativeTestJSON(base.BaseV2ComputeTest,
test.NegativeAutoTest):
- _interface = 'json'
_service = 'compute'
_schema_file = 'compute/flavors/flavors_list.json'
@@ -37,7 +36,6 @@
class FlavorDetailsNegativeTestJSON(base.BaseV2ComputeTest,
test.NegativeAutoTest):
- _interface = 'json'
_service = 'compute'
_schema_file = 'compute/flavors/flavor_details.json'
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 ea785b3..c0f7af0 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -20,7 +20,6 @@
class FloatingIPsTestJSON(base.BaseFloatingIPsTest):
- _interface = 'json'
server_id = None
floating_ip = None
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
index f24343b..0c3663e 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
@@ -25,7 +25,6 @@
class FloatingIPsNegativeTestJSON(base.BaseFloatingIPsTest):
- _interface = 'json'
server_id = None
@classmethod
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 fa2d558..d69e33c 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -18,7 +18,6 @@
class FloatingIPDetailsTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
index 8d60e7d..5701be8 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
@@ -25,7 +25,6 @@
class FloatingIPDetailsNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index 4115d65..ad211ce 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -22,7 +22,6 @@
class ImagesMetadataTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/images/test_image_metadata_negative.py b/tempest/api/compute/images/test_image_metadata_negative.py
index 4878936..7776c57 100644
--- a/tempest/api/compute/images/test_image_metadata_negative.py
+++ b/tempest/api/compute/images/test_image_metadata_negative.py
@@ -20,7 +20,6 @@
class ImagesMetadataTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index 8964dcf..ed316ef 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -22,7 +22,6 @@
class ImagesTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 7d5593d..b152c3c 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -26,7 +26,6 @@
class ImagesOneServerTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
def setUp(self):
# NOTE(afazekas): Normally we use the same server with all test cases,
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
index 82955d8..41a0590 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -27,7 +27,6 @@
class ImagesOneServerNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
def tearDown(self):
"""Terminate test instances created after a test is executed."""
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index 9cff3a8..86ee4a4 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -24,7 +24,6 @@
class ListImageFiltersTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/images/test_list_image_filters_negative.py b/tempest/api/compute/images/test_list_image_filters_negative.py
index 3b19d3c..80d59a7 100644
--- a/tempest/api/compute/images/test_list_image_filters_negative.py
+++ b/tempest/api/compute/images/test_list_image_filters_negative.py
@@ -22,7 +22,6 @@
class ListImageFiltersNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/images/test_list_images.py b/tempest/api/compute/images/test_list_images.py
index ed38442..4074a7a 100644
--- a/tempest/api/compute/images/test_list_images.py
+++ b/tempest/api/compute/images/test_list_images.py
@@ -21,7 +21,6 @@
class ListImagesTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/keypairs/test_keypairs.py b/tempest/api/compute/keypairs/test_keypairs.py
index d4554bc..67fafed 100644
--- a/tempest/api/compute/keypairs/test_keypairs.py
+++ b/tempest/api/compute/keypairs/test_keypairs.py
@@ -19,7 +19,6 @@
class KeyPairsTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/keypairs/test_keypairs_negative.py b/tempest/api/compute/keypairs/test_keypairs_negative.py
index 93b0692..a91a9c2 100644
--- a/tempest/api/compute/keypairs/test_keypairs_negative.py
+++ b/tempest/api/compute/keypairs/test_keypairs_negative.py
@@ -21,7 +21,6 @@
class KeyPairsNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/limits/test_absolute_limits.py b/tempest/api/compute/limits/test_absolute_limits.py
index 0e234fb..d64fd57 100644
--- a/tempest/api/compute/limits/test_absolute_limits.py
+++ b/tempest/api/compute/limits/test_absolute_limits.py
@@ -18,7 +18,6 @@
class AbsoluteLimitsTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/limits/test_absolute_limits_negative.py b/tempest/api/compute/limits/test_absolute_limits_negative.py
index ac8af3b..f88699b 100644
--- a/tempest/api/compute/limits/test_absolute_limits_negative.py
+++ b/tempest/api/compute/limits/test_absolute_limits_negative.py
@@ -19,7 +19,6 @@
class AbsoluteLimitsNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/security_groups/test_security_group_rules.py b/tempest/api/compute/security_groups/test_security_group_rules.py
index 17bb489..b04ab8a 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -21,7 +21,6 @@
class SecurityGroupRulesTestJSON(base.BaseSecurityGroupsTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/security_groups/test_security_group_rules_negative.py b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
index 9c9e72c..0b53037 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules_negative.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
@@ -30,7 +30,6 @@
class SecurityGroupRulesNegativeTestJSON(base.BaseSecurityGroupsTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index b376edc..c063a4e 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -20,7 +20,6 @@
class SecurityGroupsTestJSON(base.BaseSecurityGroupsTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/security_groups/test_security_groups_negative.py b/tempest/api/compute/security_groups/test_security_groups_negative.py
index edf38e9..735c7ce 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -25,7 +25,6 @@
class SecurityGroupsNegativeTestJSON(base.BaseSecurityGroupsTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 9cdac55..a21c411 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -24,7 +24,6 @@
class AttachInterfacesTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
@@ -48,6 +47,7 @@
def _create_server_get_interfaces(self):
resp, server = self.create_test_server(wait_until='ACTIVE')
resp, ifs = self.client.list_interfaces(server['id'])
+ self.assertEqual(200, resp.status)
resp, body = self.client.wait_for_interface_status(
server['id'], ifs[0]['port_id'], 'ACTIVE')
ifs[0]['port_state'] = body['port_state']
@@ -55,6 +55,7 @@
def _test_create_interface(self, server):
resp, iface = self.client.create_interface(server['id'])
+ self.assertEqual(200, resp.status)
resp, iface = self.client.wait_for_interface_status(
server['id'], iface['port_id'], 'ACTIVE')
self._check_interface(iface)
@@ -64,6 +65,7 @@
network_id = ifs[0]['net_id']
resp, iface = self.client.create_interface(server['id'],
network_id=network_id)
+ self.assertEqual(200, resp.status)
resp, iface = self.client.wait_for_interface_status(
server['id'], iface['port_id'], 'ACTIVE')
self._check_interface(iface, network_id=network_id)
@@ -73,12 +75,14 @@
iface = ifs[0]
resp, _iface = self.client.show_interface(server['id'],
iface['port_id'])
+ self.assertEqual(200, resp.status)
self.assertEqual(iface, _iface)
def _test_delete_interface(self, server, ifs):
# NOTE(danms): delete not the first or last, but one in the middle
iface = ifs[1]
- self.client.delete_interface(server['id'], iface['port_id'])
+ resp, _ = self.client.delete_interface(server['id'], iface['port_id'])
+ self.assertEqual(202, resp.status)
_ifs = self.client.list_interfaces(server['id'])[1]
start = int(time.time())
@@ -123,6 +127,33 @@
_ifs = self._test_delete_interface(server, ifs)
self.assertEqual(len(ifs) - 1, len(_ifs))
+ @attr(type='gate')
+ def test_add_remove_fixed_ip(self):
+ # Add and Remove the fixed IP to server.
+ server, ifs = self._create_server_get_interfaces()
+ interface_count = len(ifs)
+ self.assertTrue(interface_count > 0)
+ self._check_interface(ifs[0])
+ network_id = ifs[0]['net_id']
+ resp, body = self.client.add_fixed_ip(server['id'],
+ network_id)
+ self.assertEqual(202, resp.status)
+ # Remove the fixed IP from server.
+ server_resp, server_detail = self.os.servers_client.get_server(
+ server['id'])
+ # Get the Fixed IP from server.
+ fixed_ip = None
+ for ip_set in server_detail['addresses']:
+ for ip in server_detail['addresses'][ip_set]:
+ if ip['OS-EXT-IPS:type'] == 'fixed':
+ fixed_ip = ip['addr']
+ break
+ if fixed_ip is not None:
+ break
+ resp, body = self.client.remove_fixed_ip(server['id'],
+ fixed_ip)
+ self.assertEqual(202, resp.status)
+
class AttachInterfacesTestXML(AttachInterfacesTestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/servers/test_availability_zone.py b/tempest/api/compute/servers/test_availability_zone.py
index 748ba41..7b12555 100644
--- a/tempest/api/compute/servers/test_availability_zone.py
+++ b/tempest/api/compute/servers/test_availability_zone.py
@@ -23,8 +23,6 @@
Tests Availability Zone API List
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(AZTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index f705308..ddf37ce 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -28,7 +28,6 @@
class ServersTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
run_ssh = CONF.compute.run_ssh
disk_config = 'AUTO'
@@ -110,7 +109,6 @@
class ServersWithSpecificFlavorTestJSON(base.BaseV2ComputeAdminTest):
- _interface = 'json'
run_ssh = CONF.compute.run_ssh
disk_config = 'AUTO'
diff --git a/tempest/api/compute/servers/test_delete_server.py b/tempest/api/compute/servers/test_delete_server.py
index 6c0e37c..5e011dd 100644
--- a/tempest/api/compute/servers/test_delete_server.py
+++ b/tempest/api/compute/servers/test_delete_server.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import testtools
+
from tempest.api.compute import base
from tempest import config
from tempest import test
@@ -23,7 +25,6 @@
class DeleteServersTestJSON(base.BaseV2ComputeTest):
# NOTE: Server creations of each test class should be under 10
# for preventing "Quota exceeded for instances"
- _interface = 'json'
@classmethod
def setUpClass(cls):
@@ -85,11 +86,23 @@
self.assertEqual('204', resp['status'])
self.client.wait_for_server_termination(server['id'])
+ @testtools.skipIf(not CONF.compute_feature_enabled.resize,
+ 'Resize not available.')
+ @test.attr(type='gate')
+ def test_delete_server_while_in_verify_resize_state(self):
+ # Delete a server while it's VM state is VERIFY_RESIZE
+ resp, server = self.create_test_server(wait_until='ACTIVE')
+ resp, body = self.client.resize(server['id'], self.flavor_ref_alt)
+ self.assertEqual(202, resp.status)
+ self.client.wait_for_server_status(server['id'], 'VERIFY_RESIZE')
+ resp, _ = self.client.delete_server(server['id'])
+ self.assertEqual('204', resp['status'])
+ self.client.wait_for_server_termination(server['id'])
+
class DeleteServersAdminTestJSON(base.BaseV2ComputeAdminTest):
# NOTE: Server creations of each test class should be under 10
# for preventing "Quota exceeded for instances".
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_disk_config.py b/tempest/api/compute/servers/test_disk_config.py
index 0d79161..75a1234 100644
--- a/tempest/api/compute/servers/test_disk_config.py
+++ b/tempest/api/compute/servers/test_disk_config.py
@@ -23,7 +23,6 @@
class ServerDiskConfigTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_instance_actions.py b/tempest/api/compute/servers/test_instance_actions.py
index 667b84f..dd31165 100644
--- a/tempest/api/compute/servers/test_instance_actions.py
+++ b/tempest/api/compute/servers/test_instance_actions.py
@@ -18,7 +18,6 @@
class InstanceActionsTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_instance_actions_negative.py b/tempest/api/compute/servers/test_instance_actions_negative.py
index 2503eb2..e67b69d 100644
--- a/tempest/api/compute/servers/test_instance_actions_negative.py
+++ b/tempest/api/compute/servers/test_instance_actions_negative.py
@@ -20,7 +20,6 @@
class InstanceActionsNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index fc0bb9f..837114c 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -24,7 +24,6 @@
class ListServerFiltersTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index a0aefd8..26c5887 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -15,13 +15,14 @@
import datetime
+from six import moves
+
from tempest.api.compute import base
from tempest import exceptions
from tempest.test import attr
class ListServersNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
force_tenant_isolation = True
@classmethod
@@ -36,7 +37,7 @@
cls.existing_fixtures = []
cls.deleted_fixtures = []
cls.start_time = datetime.datetime.utcnow()
- for x in xrange(2):
+ for x in moves.xrange(2):
resp, srv = cls.create_test_server()
cls.existing_fixtures.append(srv)
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index cf4d646..40b9c16 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -19,7 +19,6 @@
class MultipleCreateTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
_name = 'multiple-create-test'
def _generate_name(self):
diff --git a/tempest/api/compute/servers/test_multiple_create_negative.py b/tempest/api/compute/servers/test_multiple_create_negative.py
index e289717..3dea521 100644
--- a/tempest/api/compute/servers/test_multiple_create_negative.py
+++ b/tempest/api/compute/servers/test_multiple_create_negative.py
@@ -20,7 +20,6 @@
class MultipleCreateNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
_name = 'multiple-create-test'
def _generate_name(self):
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index adf522b..bde0f57 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -29,7 +29,6 @@
class ServerActionsTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
resize_available = CONF.compute_feature_enabled.resize
run_ssh = CONF.compute.run_ssh
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index d5528c4..0c14dc2 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -21,7 +21,6 @@
class ServerAddressesTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_server_addresses_negative.py b/tempest/api/compute/servers/test_server_addresses_negative.py
index c69c5eb..d37f7fa 100644
--- a/tempest/api/compute/servers/test_server_addresses_negative.py
+++ b/tempest/api/compute/servers/test_server_addresses_negative.py
@@ -19,7 +19,6 @@
class ServerAddressesNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_server_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index ad4931c..448b8ff 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -18,7 +18,6 @@
class ServerMetadataTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_server_metadata_negative.py b/tempest/api/compute/servers/test_server_metadata_negative.py
index e52ea4a..8b69c78 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.py
@@ -20,7 +20,6 @@
class ServerMetadataNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_server_password.py b/tempest/api/compute/servers/test_server_password.py
index 06697a5..ad78f65 100644
--- a/tempest/api/compute/servers/test_server_password.py
+++ b/tempest/api/compute/servers/test_server_password.py
@@ -19,7 +19,6 @@
class ServerPasswordTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_server_personality.py b/tempest/api/compute/servers/test_server_personality.py
index bb14a4c..b581faf 100644
--- a/tempest/api/compute/servers/test_server_personality.py
+++ b/tempest/api/compute/servers/test_server_personality.py
@@ -21,7 +21,6 @@
class ServerPersonalityTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 826317d..48f2e14 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -19,7 +19,6 @@
class ServerRescueTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index ffd79fa..277f28f 100644
--- a/tempest/api/compute/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/servers/test_server_rescue_negative.py
@@ -20,7 +20,6 @@
class ServerRescueNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index 7167a8b..9674463 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -19,7 +19,6 @@
class ServersTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index e0181b9..4cccbd6 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -27,7 +27,6 @@
class ServersNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
def setUp(self):
super(ServersNegativeTestJSON, self).setUp()
diff --git a/tempest/api/compute/servers/test_servers_negative_new.py b/tempest/api/compute/servers/test_servers_negative_new.py
index 2b2fcf1..42ace76 100644
--- a/tempest/api/compute/servers/test_servers_negative_new.py
+++ b/tempest/api/compute/servers/test_servers_negative_new.py
@@ -24,7 +24,6 @@
class GetConsoleOutputNegativeTestJSON(base.BaseV2ComputeTest,
test.NegativeAutoTest):
- _interface = 'json'
_service = 'compute'
_schema_file = 'compute/servers/get_console_output.json'
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index 95703d4..6354996 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -23,7 +23,6 @@
class VirtualInterfacesTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/servers/test_virtual_interfaces_negative.py b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
index f73218c..87289d8 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces_negative.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
@@ -21,7 +21,6 @@
class VirtualInterfacesNegativeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index ed72061..fd73cc5 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -27,7 +27,6 @@
class AuthorizationTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/test_extensions.py b/tempest/api/compute/test_extensions.py
index 55146e5..674ca9a 100644
--- a/tempest/api/compute/test_extensions.py
+++ b/tempest/api/compute/test_extensions.py
@@ -26,7 +26,6 @@
class ExtensionsTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@test.attr(type='gate')
def test_list_extensions(self):
diff --git a/tempest/api/compute/test_live_block_migration.py b/tempest/api/compute/test_live_block_migration.py
index 1df4159..1319f68 100644
--- a/tempest/api/compute/test_live_block_migration.py
+++ b/tempest/api/compute/test_live_block_migration.py
@@ -25,7 +25,6 @@
class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest):
_host_key = 'OS-EXT-SRV-ATTR:host'
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/test_live_block_migration_negative.py b/tempest/api/compute/test_live_block_migration_negative.py
index e1a264e..c10818e 100644
--- a/tempest/api/compute/test_live_block_migration_negative.py
+++ b/tempest/api/compute/test_live_block_migration_negative.py
@@ -25,7 +25,6 @@
class LiveBlockMigrationNegativeTestJSON(base.BaseV2ComputeAdminTest):
_host_key = 'OS-EXT-SRV-ATTR:host'
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/test_quotas.py b/tempest/api/compute/test_quotas.py
index 112e4fb..b97ab2c 100644
--- a/tempest/api/compute/test_quotas.py
+++ b/tempest/api/compute/test_quotas.py
@@ -18,7 +18,6 @@
class QuotasTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/v3/admin/test_quotas_negative.py b/tempest/api/compute/v3/admin/test_quotas_negative.py
index c9f14f8..d138e80 100644
--- a/tempest/api/compute/v3/admin/test_quotas_negative.py
+++ b/tempest/api/compute/v3/admin/test_quotas_negative.py
@@ -20,7 +20,6 @@
class QuotasAdminNegativeV3Test(base.BaseV3ComputeAdminTest):
- _interface = 'json'
force_tenant_isolation = True
@classmethod
diff --git a/tempest/api/compute/v3/images/test_images.py b/tempest/api/compute/v3/images/test_images.py
index 656f7ba..bb81626 100644
--- a/tempest/api/compute/v3/images/test_images.py
+++ b/tempest/api/compute/v3/images/test_images.py
@@ -15,7 +15,6 @@
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -30,42 +29,8 @@
skip_msg = ("%s skipped as glance is not available" % cls.__name__)
raise cls.skipException(skip_msg)
cls.client = cls.images_client
- cls.servers_client = cls.servers_client
- def __create_image__(self, server_id, name, meta=None):
- resp, body = self.servers_client.create_image(server_id, name, meta)
- image_id = data_utils.parse_image_id(resp['location'])
- self.addCleanup(self.client.delete_image, image_id)
- self.client.wait_for_image_status(image_id, 'ACTIVE')
- return resp, body
-
- @test.attr(type=['negative', 'gate'])
- def test_create_image_from_deleted_server(self):
- # An image should not be created if the server instance is removed
- resp, server = self.create_test_server(wait_until='ACTIVE')
-
- # Delete server before trying to create server
- self.servers_client.delete_server(server['id'])
- self.servers_client.wait_for_server_termination(server['id'])
- # Create a new image after server is deleted
- name = data_utils.rand_name('image')
- meta = {'image_type': 'test'}
- self.assertRaises(exceptions.NotFound,
- self.__create_image__,
- server['id'], name, meta)
-
- @test.attr(type=['negative', 'gate'])
- def test_create_image_from_invalid_server(self):
- # An image should not be created with invalid server id
- # Create a new image with invalid server id
- name = data_utils.rand_name('image')
- meta = {'image_type': 'test'}
- resp = {}
- resp['status'] = None
- self.assertRaises(exceptions.NotFound, self.__create_image__,
- '!@#$%^&*()', name, meta)
-
- @test.attr(type=['negative', 'gate'])
+ @test.attr(type='gate')
def test_create_image_from_stopped_server(self):
resp, server = self.create_test_server(wait_until='ACTIVE')
self.servers_client.stop(server['id'])
@@ -89,21 +54,3 @@
wait_until='queued')
resp, body = self.client.delete_image(image['id'])
self.assertEqual('200', resp['status'])
-
- @test.attr(type=['negative', 'gate'])
- def test_create_image_specify_uuid_35_characters_or_less(self):
- # Return an error if Image ID passed is 35 characters or less
- snapshot_name = data_utils.rand_name('test-snap-')
- test_uuid = ('a' * 35)
- self.assertRaises(exceptions.NotFound,
- self.servers_client.create_image,
- test_uuid, snapshot_name)
-
- @test.attr(type=['negative', 'gate'])
- def test_create_image_specify_uuid_37_characters_or_more(self):
- # Return an error if Image ID passed is 37 characters or more
- snapshot_name = data_utils.rand_name('test-snap-')
- test_uuid = ('a' * 37)
- self.assertRaises(exceptions.NotFound,
- self.servers_client.create_image,
- test_uuid, snapshot_name)
diff --git a/tempest/api/compute/v3/images/test_images_negative.py b/tempest/api/compute/v3/images/test_images_negative.py
new file mode 100644
index 0000000..c38373f
--- /dev/null
+++ b/tempest/api/compute/v3/images/test_images_negative.py
@@ -0,0 +1,82 @@
+# Copyright 2014 NEC Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import config
+from tempest import exceptions
+from tempest import test
+
+CONF = config.CONF
+
+
+class ImagesNegativeV3Test(base.BaseV3ComputeTest):
+
+ @classmethod
+ def setUpClass(cls):
+ super(ImagesNegativeV3Test, cls).setUpClass()
+ if not CONF.service_available.glance:
+ skip_msg = ("%s skipped as glance is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+ cls.client = cls.images_client
+
+ def __create_image__(self, server_id, name, meta=None):
+ resp, body = self.servers_client.create_image(server_id, name, meta)
+ image_id = data_utils.parse_image_id(resp['location'])
+ self.addCleanup(self.client.delete_image, image_id)
+ self.client.wait_for_image_status(image_id, 'ACTIVE')
+ return resp, body
+
+ @test.attr(type=['negative', 'gate'])
+ def test_create_image_from_deleted_server(self):
+ # An image should not be created if the server instance is removed
+ resp, server = self.create_test_server(wait_until='ACTIVE')
+
+ # Delete server before trying to create server
+ self.servers_client.delete_server(server['id'])
+ self.servers_client.wait_for_server_termination(server['id'])
+ # Create a new image after server is deleted
+ name = data_utils.rand_name('image')
+ meta = {'image_type': 'test'}
+ self.assertRaises(exceptions.NotFound,
+ self.__create_image__,
+ server['id'], name, meta)
+
+ @test.attr(type=['negative', 'gate'])
+ def test_create_image_from_nonexistent_server(self):
+ # An image should not be created with invalid server id
+ # Create a new image with invalid server id
+ nonexistent_server_id = data_utils.rand_uuid()
+ name = data_utils.rand_name('image')
+ meta = {'image_type': 'test'}
+ self.assertRaises(exceptions.NotFound, self.__create_image__,
+ nonexistent_server_id, name, meta)
+
+ @test.attr(type=['negative', 'gate'])
+ def test_create_image_specify_uuid_35_characters_or_less(self):
+ # Return an error if Image ID passed is 35 characters or less
+ snapshot_name = data_utils.rand_name('test-snap-')
+ test_uuid = ('a' * 35)
+ self.assertRaises(exceptions.NotFound,
+ self.servers_client.create_image,
+ test_uuid, snapshot_name)
+
+ @test.attr(type=['negative', 'gate'])
+ def test_create_image_specify_uuid_37_characters_or_more(self):
+ # Return an error if Image ID passed is 37 characters or more
+ snapshot_name = data_utils.rand_name('test-snap-')
+ test_uuid = ('a' * 37)
+ self.assertRaises(exceptions.NotFound,
+ self.servers_client.create_image,
+ test_uuid, snapshot_name)
diff --git a/tempest/api/compute/v3/servers/test_attach_interfaces.py b/tempest/api/compute/v3/servers/test_attach_interfaces.py
index a3046c7..e1c69d9 100644
--- a/tempest/api/compute/v3/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/v3/servers/test_attach_interfaces.py
@@ -47,6 +47,7 @@
def _create_server_get_interfaces(self):
resp, server = self.create_test_server(wait_until='ACTIVE')
resp, ifs = self.client.list_interfaces(server['id'])
+ self.assertEqual(200, resp.status)
resp, body = self.client.wait_for_interface_status(
server['id'], ifs[0]['port_id'], 'ACTIVE')
ifs[0]['port_state'] = body['port_state']
@@ -54,6 +55,7 @@
def _test_create_interface(self, server):
resp, iface = self.client.create_interface(server['id'])
+ self.assertEqual(200, resp.status)
resp, iface = self.client.wait_for_interface_status(
server['id'], iface['port_id'], 'ACTIVE')
self._check_interface(iface)
@@ -63,6 +65,7 @@
network_id = ifs[0]['net_id']
resp, iface = self.client.create_interface(server['id'],
network_id=network_id)
+ self.assertEqual(200, resp.status)
resp, iface = self.client.wait_for_interface_status(
server['id'], iface['port_id'], 'ACTIVE')
self._check_interface(iface, network_id=network_id)
@@ -72,12 +75,14 @@
iface = ifs[0]
resp, _iface = self.client.show_interface(server['id'],
iface['port_id'])
+ self.assertEqual(200, resp.status)
self.assertEqual(iface, _iface)
def _test_delete_interface(self, server, ifs):
# NOTE(danms): delete not the first or last, but one in the middle
iface = ifs[1]
- self.client.delete_interface(server['id'], iface['port_id'])
+ resp, _ = self.client.delete_interface(server['id'], iface['port_id'])
+ self.assertEqual(202, resp.status)
_ifs = self.client.list_interfaces(server['id'])[1]
start = int(time.time())
@@ -121,3 +126,30 @@
_ifs = self._test_delete_interface(server, ifs)
self.assertEqual(len(ifs) - 1, len(_ifs))
+
+ @attr(type='gate')
+ def test_add_remove_fixed_ip(self):
+ # Add and Remove the fixed IP to server.
+ server, ifs = self._create_server_get_interfaces()
+ interface_count = len(ifs)
+ self.assertGreater(interface_count, 0)
+ self._check_interface(ifs[0])
+ network_id = ifs[0]['net_id']
+ resp, body = self.client.add_fixed_ip(server['id'],
+ network_id)
+ self.assertEqual(202, resp.status)
+ server_resp, server_detail = self.servers_client.get_server(
+ server['id'])
+ # Get the Fixed IP from server.
+ fixed_ip = None
+ for ip_set in server_detail['addresses']:
+ for ip in server_detail['addresses'][ip_set]:
+ if ip['type'] == 'fixed':
+ fixed_ip = ip['addr']
+ break
+ if fixed_ip is not None:
+ break
+ # Remove the fixed IP from server.
+ resp, body = self.client.remove_fixed_ip(server['id'],
+ fixed_ip)
+ self.assertEqual(202, resp.status)
diff --git a/tempest/api/compute/v3/servers/test_availability_zone.py b/tempest/api/compute/v3/servers/test_availability_zone.py
index feac9a1..5a1e07e 100644
--- a/tempest/api/compute/v3/servers/test_availability_zone.py
+++ b/tempest/api/compute/v3/servers/test_availability_zone.py
@@ -23,8 +23,6 @@
Tests Availability Zone API List
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(AZV3Test, cls).setUpClass()
diff --git a/tempest/api/compute/v3/servers/test_delete_server.py b/tempest/api/compute/v3/servers/test_delete_server.py
index 0dfe60e..d694a33 100644
--- a/tempest/api/compute/v3/servers/test_delete_server.py
+++ b/tempest/api/compute/v3/servers/test_delete_server.py
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import testtools
+
from tempest.api.compute import base
from tempest import config
from tempest import test
@@ -22,7 +24,6 @@
class DeleteServersV3Test(base.BaseV3ComputeTest):
# NOTE: Server creations of each test class should be under 10
# for preventing "Quota exceeded for instances".
- _interface = 'json'
@classmethod
def setUpClass(cls):
@@ -85,11 +86,23 @@
self.assertEqual('204', resp['status'])
self.client.wait_for_server_termination(server['id'])
+ @testtools.skipIf(not CONF.compute_feature_enabled.resize,
+ 'Resize not available.')
+ @test.attr(type='gate')
+ def test_delete_server_while_in_verify_resize_state(self):
+ # Delete a server while it's VM state is VERIFY_RESIZE
+ resp, server = self.create_test_server(wait_until='ACTIVE')
+ resp, body = self.client.resize(server['id'], self.flavor_ref_alt)
+ self.assertEqual(202, resp.status)
+ self.client.wait_for_server_status(server['id'], 'VERIFY_RESIZE')
+ resp, _ = self.client.delete_server(server['id'])
+ self.assertEqual('204', resp['status'])
+ self.client.wait_for_server_termination(server['id'])
+
class DeleteServersAdminV3Test(base.BaseV3ComputeAdminTest):
# NOTE: Server creations of each test class should be under 10
# for preventing "Quota exceeded for instances".
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/v3/servers/test_instance_actions_negative.py b/tempest/api/compute/v3/servers/test_instance_actions_negative.py
index bd741e0..b0a7050 100644
--- a/tempest/api/compute/v3/servers/test_instance_actions_negative.py
+++ b/tempest/api/compute/v3/servers/test_instance_actions_negative.py
@@ -20,7 +20,6 @@
class InstanceActionsNegativeV3Test(base.BaseV3ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/compute/v3/servers/test_list_servers_negative.py b/tempest/api/compute/v3/servers/test_list_servers_negative.py
index 9a46193..92f44fe 100644
--- a/tempest/api/compute/v3/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/v3/servers/test_list_servers_negative.py
@@ -15,6 +15,8 @@
import datetime
+from six import moves
+
from tempest.api.compute import base
from tempest import exceptions
from tempest.test import attr
@@ -35,7 +37,7 @@
cls.existing_fixtures = []
cls.deleted_fixtures = []
cls.start_time = datetime.datetime.utcnow()
- for x in xrange(2):
+ for x in moves.xrange(2):
resp, srv = cls.create_test_server()
cls.existing_fixtures.append(srv)
diff --git a/tempest/api/compute/v3/servers/test_multiple_create_negative.py b/tempest/api/compute/v3/servers/test_multiple_create_negative.py
index 57bb807..f208bc0 100644
--- a/tempest/api/compute/v3/servers/test_multiple_create_negative.py
+++ b/tempest/api/compute/v3/servers/test_multiple_create_negative.py
@@ -20,7 +20,6 @@
class MultipleCreateV3NegativeTest(base.BaseV3ComputeTest):
- _interface = 'json'
_name = 'multiple-create-negative-test'
def _generate_name(self):
diff --git a/tempest/api/compute/v3/servers/test_server_addresses.py b/tempest/api/compute/v3/servers/test_server_addresses.py
index 335bd3d..efd7500 100644
--- a/tempest/api/compute/v3/servers/test_server_addresses.py
+++ b/tempest/api/compute/v3/servers/test_server_addresses.py
@@ -15,7 +15,6 @@
from tempest.api.compute import base
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -32,19 +31,6 @@
resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
- @test.attr(type=['negative', 'gate'])
- def test_list_server_addresses_invalid_server_id(self):
- # List addresses request should fail if server id not in system
- self.assertRaises(exceptions.NotFound, self.client.list_addresses,
- '999')
-
- @test.attr(type=['negative', 'gate'])
- def test_list_server_addresses_by_network_neg(self):
- # List addresses by network should fail if network name not valid
- self.assertRaises(exceptions.NotFound,
- self.client.list_addresses_by_network,
- self.server['id'], 'invalid')
-
@test.skip_because(bug="1210483",
condition=CONF.service_available.neutron)
@test.attr(type='smoke')
diff --git a/tempest/api/compute/v3/servers/test_server_addresses_negative.py b/tempest/api/compute/v3/servers/test_server_addresses_negative.py
new file mode 100644
index 0000000..8a9877b
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_server_addresses_negative.py
@@ -0,0 +1,46 @@
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest import test
+
+
+class ServerAddressesV3NegativeTest(base.BaseV3ComputeTest):
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ # This test module might use a network and a subnet
+ cls.set_network_resources(network=True, subnet=True)
+ super(ServerAddressesV3NegativeTest, cls).setUpClass()
+ cls.client = cls.servers_client
+
+ resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
+
+ @test.attr(type=['negative', 'gate'])
+ def test_list_server_addresses_nonexistent_server_id(self):
+ # List addresses request should fail if server id not in system
+ non_existent_server_id = data_utils.rand_uuid()
+ self.assertRaises(exceptions.NotFound, self.client.list_addresses,
+ non_existent_server_id)
+
+ @test.attr(type=['negative', 'gate'])
+ def test_list_server_addresses_by_network_neg(self):
+ # List addresses by network should fail if network name not valid
+ self.assertRaises(exceptions.NotFound,
+ self.client.list_addresses_by_network,
+ self.server['id'], 'invalid')
diff --git a/tempest/api/compute/v3/servers/test_server_rescue.py b/tempest/api/compute/v3/servers/test_server_rescue.py
index 5d7f91d..b3dcb51 100644
--- a/tempest/api/compute/v3/servers/test_server_rescue.py
+++ b/tempest/api/compute/v3/servers/test_server_rescue.py
@@ -14,9 +14,7 @@
# 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 import test
class ServerRescueV3Test(base.BaseV3ComputeTest):
@@ -24,56 +22,14 @@
@classmethod
def setUpClass(cls):
super(ServerRescueV3Test, cls).setUpClass()
- cls.device = 'vdf'
-
- # Create a volume and wait for it to become ready for attach
- resp, cls.volume = cls.volumes_client.create_volume(
- 1, display_name=data_utils.rand_name(cls.__name__ + '_volume'))
- cls.volumes_client.wait_for_volume_status(
- cls.volume['id'], 'available')
# Server for positive tests
resp, server = cls.create_test_server(wait_until='BUILD')
- resp, resc_server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
cls.password = server['admin_password']
cls.servers_client.wait_for_server_status(cls.server_id, 'ACTIVE')
- # Server for negative tests
- cls.rescue_id = resc_server['id']
- cls.rescue_password = resc_server['admin_password']
-
- cls.servers_client.rescue_server(
- cls.rescue_id, admin_password=cls.rescue_password)
- cls.servers_client.wait_for_server_status(cls.rescue_id, 'RESCUE')
-
- def setUp(self):
- super(ServerRescueV3Test, self).setUp()
-
- @classmethod
- def tearDownClass(cls):
- cls.delete_volume(cls.volume['id'])
- super(ServerRescueV3Test, cls).tearDownClass()
-
- def tearDown(self):
- super(ServerRescueV3Test, self).tearDown()
-
- def _detach(self, server_id, volume_id):
- self.servers_client.detach_volume(server_id, volume_id)
- self.volumes_client.wait_for_volume_status(volume_id,
- 'available')
-
- def _unrescue(self, server_id):
- resp, body = self.servers_client.unrescue_server(server_id)
- self.assertEqual(202, resp.status)
- self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
-
- def _unpause(self, server_id):
- resp, body = self.servers_client.unpause_server(server_id)
- self.assertEqual(202, resp.status)
- self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
-
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_rescue_unrescue_instance(self):
resp, body = self.servers_client.rescue_server(
self.server_id, admin_password=self.password)
@@ -82,71 +38,3 @@
resp, body = self.servers_client.unrescue_server(self.server_id)
self.assertEqual(202, resp.status)
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
-
- @attr(type=['negative', 'gate'])
- def test_rescue_paused_instance(self):
- # Rescue a paused server
- resp, body = self.servers_client.pause_server(
- self.server_id)
- self.addCleanup(self._unpause, self.server_id)
- self.assertEqual(202, resp.status)
- self.servers_client.wait_for_server_status(self.server_id, 'PAUSED')
- self.assertRaises(exceptions.Conflict,
- self.servers_client.rescue_server,
- self.server_id)
-
- @attr(type=['negative', 'gate'])
- def test_rescued_vm_reboot(self):
- self.assertRaises(exceptions.Conflict, self.servers_client.reboot,
- self.rescue_id, 'HARD')
-
- @attr(type=['negative', 'gate'])
- def test_rescue_non_existent_server(self):
- # Rescue a non-existing server
- self.assertRaises(exceptions.NotFound,
- self.servers_client.rescue_server,
- '999erra43')
-
- @attr(type=['negative', 'gate'])
- def test_rescued_vm_rebuild(self):
- self.assertRaises(exceptions.Conflict,
- self.servers_client.rebuild,
- self.rescue_id,
- self.image_ref_alt)
-
- @attr(type=['negative', 'gate'])
- def test_rescued_vm_attach_volume(self):
- # Rescue the server
- self.servers_client.rescue_server(self.server_id,
- admin_password=self.password)
- self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
- self.addCleanup(self._unrescue, self.server_id)
-
- # Attach the volume to the server
- self.assertRaises(exceptions.Conflict,
- self.servers_client.attach_volume,
- self.server_id,
- self.volume['id'],
- device='/dev/%s' % self.device)
-
- @attr(type=['negative', 'gate'])
- def test_rescued_vm_detach_volume(self):
- # Attach the volume to the server
- self.servers_client.attach_volume(self.server_id,
- self.volume['id'],
- device='/dev/%s' % self.device)
- self.volumes_client.wait_for_volume_status(self.volume['id'], 'in-use')
-
- # Rescue the server
- self.servers_client.rescue_server(self.server_id,
- admin_password=self.password)
- self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
- # addCleanup is a LIFO queue
- self.addCleanup(self._detach, self.server_id, self.volume['id'])
- self.addCleanup(self._unrescue, self.server_id)
-
- # Detach the volume from the server expecting failure
- self.assertRaises(exceptions.Conflict,
- self.servers_client.detach_volume,
- self.server_id,
- self.volume['id'])
diff --git a/tempest/api/compute/v3/servers/test_server_rescue_negative.py b/tempest/api/compute/v3/servers/test_server_rescue_negative.py
new file mode 100644
index 0000000..6e09376
--- /dev/null
+++ b/tempest/api/compute/v3/servers/test_server_rescue_negative.py
@@ -0,0 +1,133 @@
+# Copyright 2013 Hewlett-Packard Development Company, L.P.
+# Copyright 2014 NEC Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest import test
+
+
+class ServerRescueNegativeV3Test(base.BaseV3ComputeTest):
+
+ @classmethod
+ def setUpClass(cls):
+ super(ServerRescueNegativeV3Test, cls).setUpClass()
+ cls.device = 'vdf'
+
+ # Create a volume and wait for it to become ready for attach
+ resp, cls.volume = cls.volumes_client.create_volume(
+ 1, display_name=data_utils.rand_name(cls.__name__ + '_volume'))
+ cls.volumes_client.wait_for_volume_status(
+ cls.volume['id'], 'available')
+
+ # Server for negative tests
+ resp, server = cls.create_test_server(wait_until='BUILD')
+ resp, resc_server = cls.create_test_server(wait_until='ACTIVE')
+ cls.server_id = server['id']
+ cls.password = server['admin_password']
+ cls.rescue_id = resc_server['id']
+ cls.rescue_password = resc_server['admin_password']
+
+ cls.servers_client.rescue_server(
+ cls.rescue_id, admin_password=cls.rescue_password)
+ cls.servers_client.wait_for_server_status(cls.rescue_id, 'RESCUE')
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.delete_volume(cls.volume['id'])
+ super(ServerRescueNegativeV3Test, cls).tearDownClass()
+
+ def _detach(self, server_id, volume_id):
+ self.servers_client.detach_volume(server_id, volume_id)
+ self.volumes_client.wait_for_volume_status(volume_id,
+ 'available')
+
+ def _unrescue(self, server_id):
+ resp, body = self.servers_client.unrescue_server(server_id)
+ self.assertEqual(202, resp.status)
+ self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
+
+ def _unpause(self, server_id):
+ resp, body = self.servers_client.unpause_server(server_id)
+ self.assertEqual(202, resp.status)
+ self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
+
+ @test.attr(type=['negative', 'gate'])
+ def test_rescue_paused_instance(self):
+ # Rescue a paused server
+ resp, body = self.servers_client.pause_server(
+ self.server_id)
+ self.addCleanup(self._unpause, self.server_id)
+ self.assertEqual(202, resp.status)
+ self.servers_client.wait_for_server_status(self.server_id, 'PAUSED')
+ self.assertRaises(exceptions.Conflict,
+ self.servers_client.rescue_server,
+ self.server_id)
+
+ @test.attr(type=['negative', 'gate'])
+ def test_rescued_vm_reboot(self):
+ self.assertRaises(exceptions.Conflict, self.servers_client.reboot,
+ self.rescue_id, 'HARD')
+
+ @test.attr(type=['negative', 'gate'])
+ def test_rescue_non_existent_server(self):
+ # Rescue a non-existing server
+ self.assertRaises(exceptions.NotFound,
+ self.servers_client.rescue_server,
+ data_utils.rand_uuid())
+
+ @test.attr(type=['negative', 'gate'])
+ def test_rescued_vm_rebuild(self):
+ self.assertRaises(exceptions.Conflict,
+ self.servers_client.rebuild,
+ self.rescue_id,
+ self.image_ref_alt)
+
+ @test.attr(type=['negative', 'gate'])
+ def test_rescued_vm_attach_volume(self):
+ # Rescue the server
+ self.servers_client.rescue_server(self.server_id,
+ admin_password=self.password)
+ self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
+ self.addCleanup(self._unrescue, self.server_id)
+
+ # Attach the volume to the server
+ self.assertRaises(exceptions.Conflict,
+ self.servers_client.attach_volume,
+ self.server_id,
+ self.volume['id'],
+ device='/dev/%s' % self.device)
+
+ @test.attr(type=['negative', 'gate'])
+ def test_rescued_vm_detach_volume(self):
+ # Attach the volume to the server
+ self.servers_client.attach_volume(self.server_id,
+ self.volume['id'],
+ device='/dev/%s' % self.device)
+ self.volumes_client.wait_for_volume_status(self.volume['id'], 'in-use')
+
+ # Rescue the server
+ self.servers_client.rescue_server(self.server_id,
+ admin_password=self.password)
+ self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
+ # addCleanup is a LIFO queue
+ self.addCleanup(self._detach, self.server_id, self.volume['id'])
+ self.addCleanup(self._unrescue, self.server_id)
+
+ # Detach the volume from the server expecting failure
+ self.assertRaises(exceptions.Conflict,
+ self.servers_client.detach_volume,
+ self.server_id,
+ self.volume['id'])
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 7a60196..3c5feed 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -24,7 +24,6 @@
class AttachVolumeTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
run_ssh = CONF.compute.run_ssh
def __init__(self, *args, **kwargs):
diff --git a/tempest/api/compute/volumes/test_volumes_get.py b/tempest/api/compute/volumes/test_volumes_get.py
index 73e3b3a..c3d6ba6 100644
--- a/tempest/api/compute/volumes/test_volumes_get.py
+++ b/tempest/api/compute/volumes/test_volumes_get.py
@@ -24,8 +24,6 @@
class VolumesGetTestJSON(base.BaseV2ComputeTest):
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(VolumesGetTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/volumes/test_volumes_list.py b/tempest/api/compute/volumes/test_volumes_list.py
index 48b1b7e..9867c64 100644
--- a/tempest/api/compute/volumes/test_volumes_list.py
+++ b/tempest/api/compute/volumes/test_volumes_list.py
@@ -31,8 +31,6 @@
VOLUME_BACKING_FILE_SIZE is atleast 4G in your localrc
"""
- _interface = 'json'
-
@classmethod
def setUpClass(cls):
super(VolumesTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/volumes/test_volumes_negative.py b/tempest/api/compute/volumes/test_volumes_negative.py
index 85b30e2..cecaf62 100644
--- a/tempest/api/compute/volumes/test_volumes_negative.py
+++ b/tempest/api/compute/volumes/test_volumes_negative.py
@@ -25,7 +25,6 @@
class VolumesNegativeTest(base.BaseV2ComputeTest):
- _interface = 'json'
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/identity/admin/test_roles.py b/tempest/api/identity/admin/test_roles.py
index aa64969..5e78cce 100644
--- a/tempest/api/identity/admin/test_roles.py
+++ b/tempest/api/identity/admin/test_roles.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from six import moves
+
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest.test import attr
@@ -24,7 +26,7 @@
@classmethod
def setUpClass(cls):
super(RolesTestJSON, cls).setUpClass()
- for _ in xrange(5):
+ for _ in moves.xrange(5):
role_name = data_utils.rand_name(name='role-')
resp, role = cls.client.create_role(role_name)
cls.data.roles.append(role)
diff --git a/tempest/api/identity/admin/test_services.py b/tempest/api/identity/admin/test_services.py
index cbf6b58..459c44c 100644
--- a/tempest/api/identity/admin/test_services.py
+++ b/tempest/api/identity/admin/test_services.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from six import moves
from tempest.api.identity import base
from tempest.common.utils import data_utils
@@ -69,7 +70,7 @@
def test_list_services(self):
# Create, List, Verify and Delete Services
services = []
- for _ in xrange(3):
+ for _ in moves.xrange(3):
name = data_utils.rand_name('service-')
type = data_utils.rand_name('type--')
description = data_utils.rand_name('description-')
diff --git a/tempest/api/identity/admin/test_tenants.py b/tempest/api/identity/admin/test_tenants.py
index c7cacb4..257a6d7 100644
--- a/tempest/api/identity/admin/test_tenants.py
+++ b/tempest/api/identity/admin/test_tenants.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from six import moves
+
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest.test import attr
@@ -25,7 +27,7 @@
def test_tenant_list_delete(self):
# Create several tenants and delete them
tenants = []
- for _ in xrange(3):
+ for _ in moves.xrange(3):
tenant_name = data_utils.rand_name(name='tenant-new')
resp, tenant = self.client.create_tenant(tenant_name)
self.assertEqual(200, resp.status)
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 78ecf93..05b704f 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -125,7 +125,7 @@
self.assertEqual(interface2, endpoint['interface'])
self.assertEqual(url2, endpoint['url'])
self.assertEqual(region2, endpoint['region'])
- self.assertEqual('False', str(endpoint['enabled']))
+ self.assertEqual('false', str(endpoint['enabled']).lower())
self.addCleanup(self.client.delete_endpoint, endpoint_for_update['id'])
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index be03a03..31a0ddd 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from six import moves
+
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest import exceptions
@@ -31,7 +33,7 @@
@test.attr(type='gate')
def test_project_list_delete(self):
# Create several projects and delete them
- for _ in xrange(3):
+ for _ in moves.xrange(3):
resp, project = self.client.create_project(
data_utils.rand_name('project-new'))
self.addCleanup(self._delete_project, project['id'])
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 759c4a9..d448c01 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -249,3 +249,19 @@
self.assertEqual(len(images_list), params['limit'],
"Failed to get images by limit")
+
+ @attr(type='gate')
+ def test_get_image_schema(self):
+ # Test to get image schema
+ schema = "image"
+ resp, body = self.client.get_schema(schema)
+ self.assertEqual(200, resp.status)
+ self.assertEqual("image", body['name'])
+
+ @attr(type='gate')
+ def test_get_images_schema(self):
+ # Test to get images schema
+ schema = "images"
+ resp, body = self.client.get_schema(schema)
+ self.assertEqual(200, resp.status)
+ self.assertEqual("images", body['name'])
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index dd888a6..8720985 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -53,8 +53,6 @@
# Default to ipv4.
_ip_version = 4
- _tenant_network_cidr = CONF.network.tenant_network_cidr
- _tenant_network_mask_bits = CONF.network.tenant_network_mask_bits
@classmethod
def setUpClass(cls):
@@ -147,8 +145,12 @@
def create_subnet(cls, network):
"""Wrapper utility that returns a test subnet."""
# The cidr and mask_bits depend on the ip version.
- cidr = netaddr.IPNetwork(cls._tenant_network_cidr)
- mask_bits = cls._tenant_network_mask_bits
+ if cls._ip_version == 4:
+ cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
+ mask_bits = CONF.network.tenant_network_mask_bits
+ elif cls._ip_version == 6:
+ cidr = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
+ mask_bits = CONF.network.tenant_network_v6_mask_bits
# Find a cidr that is not in use yet and create a subnet with it
body = None
failure = None
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index aba2c8e..654552d 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -85,8 +85,12 @@
updated_net = body['network']
self.assertEqual(updated_net['name'], new_name)
# Find a cidr that is not in use yet and create a subnet with it
- cidr = netaddr.IPNetwork(self._tenant_network_cidr)
- mask_bits = self._tenant_network_mask_bits
+ if self._ip_version == 4:
+ cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
+ mask_bits = CONF.network.tenant_network_mask_bits
+ elif self._ip_version == 6:
+ cidr = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
+ mask_bits = CONF.network.tenant_network_v6_mask_bits
for subnet_cidr in cidr.subnet(mask_bits):
try:
resp, body = self.client.create_subnet(
@@ -464,8 +468,6 @@
class NetworksIpV6TestJSON(NetworksTestJSON):
_ip_version = 6
- _tenant_network_cidr = CONF.network.tenant_network_v6_cidr
- _tenant_network_mask_bits = CONF.network.tenant_network_v6_mask_bits
@classmethod
def setUpClass(cls):
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 5456768..7542ea1 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -15,6 +15,8 @@
import random
+from six import moves
+
from tempest.api.object_storage import base
from tempest.common import custom_matchers
from tempest.common.utils import data_utils
@@ -26,7 +28,7 @@
def setUpClass(cls):
super(AccountTest, cls).setUpClass()
cls.containers = []
- for i in xrange(ord('a'), ord('f') + 1):
+ for i in moves.xrange(ord('a'), ord('f') + 1):
name = data_utils.rand_name(name='%s-' % chr(i))
cls.container_client.create_container(name)
cls.containers.append(name)
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 33f3299..91df292 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -14,6 +14,7 @@
# under the License.
import hashlib
+from six import moves
from tempest.api.object_storage import base
from tempest.common import custom_matchers
@@ -242,9 +243,9 @@
object_name = data_utils.rand_name(name='LObject')
data = data_utils.arbitrary_string()
segments = 10
- data_segments = [data + str(i) for i in xrange(segments)]
+ data_segments = [data + str(i) for i in moves.xrange(segments)]
# uploading segments
- for i in xrange(segments):
+ for i in moves.xrange(segments):
resp, _ = self.object_client.create_object_segments(
self.container_name, object_name, i, data_segments[i])
self.assertEqual(resp['status'], '201')
diff --git a/tempest/common/generate_sample_tempest.py b/tempest/common/generate_sample_tempest.py
index e1213db..ceb3394 100644
--- a/tempest/common/generate_sample_tempest.py
+++ b/tempest/common/generate_sample_tempest.py
@@ -31,5 +31,5 @@
if __name__ == "__main__":
- CONF = tempest.config.TempestConfigPrivate(False)
+ tempest.config.register_opts()
generator.generate(sys.argv[1:])
diff --git a/tempest/common/glance_http.py b/tempest/common/glance_http.py
index 4503f13..b4ba933 100644
--- a/tempest/common/glance_http.py
+++ b/tempest/common/glance_http.py
@@ -21,6 +21,7 @@
import json
import posixpath
import re
+from six import moves
import socket
import StringIO
import struct
@@ -264,7 +265,7 @@
# Also try Subject Alternative Names for a match
san_list = None
- for i in xrange(x509.get_extension_count()):
+ for i in moves.xrange(x509.get_extension_count()):
ext = x509.get_extension(i)
if ext.get_short_name() == 'subjectAltName':
san_list = str(ext)
diff --git a/tempest/common/ssh.py b/tempest/common/ssh.py
index b6fa0a0..531887c 100644
--- a/tempest/common/ssh.py
+++ b/tempest/common/ssh.py
@@ -16,6 +16,7 @@
import cStringIO
import select
+import six
import socket
import time
import warnings
@@ -39,7 +40,7 @@
self.host = host
self.username = username
self.password = password
- if isinstance(pkey, basestring):
+ if isinstance(pkey, six.string_types):
pkey = paramiko.RSAKey.from_private_key(
cStringIO.StringIO(str(pkey)))
self.pkey = pkey
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 94fc23c..8420ad0 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -11,6 +11,7 @@
# under the License.
import re
+import six
import time
from tempest.common import ssh
@@ -28,7 +29,7 @@
network = CONF.compute.network_for_ssh
ip_version = CONF.compute.ip_version_for_ssh
ssh_channel_timeout = CONF.compute.ssh_channel_timeout
- if isinstance(server, basestring):
+ if isinstance(server, six.string_types):
ip_address = server
else:
addresses = server['addresses'][network]
@@ -93,3 +94,18 @@
def get_mac_address(self):
cmd = "/sbin/ifconfig | awk '/HWaddr/ {print $5}'"
return self.ssh_client.exec_command(cmd)
+
+ def get_ip_list(self):
+ cmd = "/bin/ip address"
+ return self.ssh_client.exec_command(cmd)
+
+ def assign_static_ip(self, nic, addr):
+ cmd = "sudo /bin/ip addr add {ip}/{mask} dev {nic}".format(
+ ip=addr, mask=CONF.network.tenant_network_mask_bits,
+ nic=nic
+ )
+ return self.ssh_client.exec_command(cmd)
+
+ def turn_nic_on(self, nic):
+ cmd = "sudo /bin/ip link set {nic} up".format(nic=nic)
+ return self.ssh_client.exec_command(cmd)
diff --git a/tempest/config.py b/tempest/config.py
index 887bac3..0f5e23c 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -807,6 +807,41 @@
]
+def register_opts():
+ register_opt_group(cfg.CONF, compute_group, ComputeGroup)
+ register_opt_group(cfg.CONF, compute_features_group,
+ ComputeFeaturesGroup)
+ register_opt_group(cfg.CONF, identity_group, IdentityGroup)
+ register_opt_group(cfg.CONF, identity_feature_group,
+ IdentityFeatureGroup)
+ register_opt_group(cfg.CONF, image_group, ImageGroup)
+ register_opt_group(cfg.CONF, image_feature_group, ImageFeaturesGroup)
+ register_opt_group(cfg.CONF, network_group, NetworkGroup)
+ register_opt_group(cfg.CONF, network_feature_group,
+ NetworkFeaturesGroup)
+ register_opt_group(cfg.CONF, volume_group, VolumeGroup)
+ register_opt_group(cfg.CONF, volume_feature_group,
+ VolumeFeaturesGroup)
+ register_opt_group(cfg.CONF, object_storage_group, ObjectStoreGroup)
+ register_opt_group(cfg.CONF, object_storage_feature_group,
+ ObjectStoreFeaturesGroup)
+ register_opt_group(cfg.CONF, orchestration_group, OrchestrationGroup)
+ register_opt_group(cfg.CONF, telemetry_group, TelemetryGroup)
+ register_opt_group(cfg.CONF, dashboard_group, DashboardGroup)
+ register_opt_group(cfg.CONF, data_processing_group,
+ DataProcessingGroup)
+ register_opt_group(cfg.CONF, boto_group, BotoGroup)
+ register_opt_group(cfg.CONF, compute_admin_group, ComputeAdminGroup)
+ register_opt_group(cfg.CONF, stress_group, StressGroup)
+ register_opt_group(cfg.CONF, scenario_group, ScenarioGroup)
+ register_opt_group(cfg.CONF, service_available_group,
+ ServiceAvailableGroup)
+ register_opt_group(cfg.CONF, debug_group, DebugGroup)
+ register_opt_group(cfg.CONF, baremetal_group, BaremetalGroup)
+ register_opt_group(cfg.CONF, input_scenario_group, InputScenarioGroup)
+ register_opt_group(cfg.CONF, cli_group, CLIGroup)
+
+
# this should never be called outside of this class
class TempestConfigPrivate(object):
"""Provides OpenStack configuration information."""
@@ -817,64 +852,7 @@
DEFAULT_CONFIG_FILE = "tempest.conf"
- def __init__(self, parse_conf=True):
- """Initialize a configuration from a conf directory and conf file."""
- super(TempestConfigPrivate, self).__init__()
- config_files = []
- failsafe_path = "/etc/tempest/" + self.DEFAULT_CONFIG_FILE
-
- # Environment variables override defaults...
- conf_dir = os.environ.get('TEMPEST_CONFIG_DIR',
- self.DEFAULT_CONFIG_DIR)
- conf_file = os.environ.get('TEMPEST_CONFIG', self.DEFAULT_CONFIG_FILE)
-
- path = os.path.join(conf_dir, conf_file)
-
- if not os.path.isfile(path):
- path = failsafe_path
-
- # only parse the config file if we expect one to exist. This is needed
- # to remove an issue with the config file up to date checker.
- if parse_conf:
- config_files.append(path)
-
- cfg.CONF([], project='tempest', default_config_files=config_files)
- logging.setup('tempest')
- LOG = logging.getLogger('tempest')
- LOG.info("Using tempest config file %s" % path)
-
- register_opt_group(cfg.CONF, compute_group, ComputeGroup)
- register_opt_group(cfg.CONF, compute_features_group,
- ComputeFeaturesGroup)
- register_opt_group(cfg.CONF, identity_group, IdentityGroup)
- register_opt_group(cfg.CONF, identity_feature_group,
- IdentityFeatureGroup)
- register_opt_group(cfg.CONF, image_group, ImageGroup)
- register_opt_group(cfg.CONF, image_feature_group, ImageFeaturesGroup)
- register_opt_group(cfg.CONF, network_group, NetworkGroup)
- register_opt_group(cfg.CONF, network_feature_group,
- NetworkFeaturesGroup)
- register_opt_group(cfg.CONF, volume_group, VolumeGroup)
- register_opt_group(cfg.CONF, volume_feature_group,
- VolumeFeaturesGroup)
- register_opt_group(cfg.CONF, object_storage_group, ObjectStoreGroup)
- register_opt_group(cfg.CONF, object_storage_feature_group,
- ObjectStoreFeaturesGroup)
- register_opt_group(cfg.CONF, orchestration_group, OrchestrationGroup)
- register_opt_group(cfg.CONF, telemetry_group, TelemetryGroup)
- register_opt_group(cfg.CONF, dashboard_group, DashboardGroup)
- register_opt_group(cfg.CONF, data_processing_group,
- DataProcessingGroup)
- register_opt_group(cfg.CONF, boto_group, BotoGroup)
- register_opt_group(cfg.CONF, compute_admin_group, ComputeAdminGroup)
- register_opt_group(cfg.CONF, stress_group, StressGroup)
- register_opt_group(cfg.CONF, scenario_group, ScenarioGroup)
- register_opt_group(cfg.CONF, service_available_group,
- ServiceAvailableGroup)
- register_opt_group(cfg.CONF, debug_group, DebugGroup)
- register_opt_group(cfg.CONF, baremetal_group, BaremetalGroup)
- register_opt_group(cfg.CONF, input_scenario_group, InputScenarioGroup)
- register_opt_group(cfg.CONF, cli_group, CLIGroup)
+ def _set_attrs(self):
self.compute = cfg.CONF.compute
self.compute_feature_enabled = cfg.CONF['compute-feature-enabled']
self.identity = cfg.CONF.identity
@@ -906,6 +884,33 @@
self.compute_admin.password = self.identity.admin_password
self.compute_admin.tenant_name = self.identity.admin_tenant_name
+ def __init__(self, parse_conf=True):
+ """Initialize a configuration from a conf directory and conf file."""
+ super(TempestConfigPrivate, self).__init__()
+ config_files = []
+ failsafe_path = "/etc/tempest/" + self.DEFAULT_CONFIG_FILE
+
+ # Environment variables override defaults...
+ conf_dir = os.environ.get('TEMPEST_CONFIG_DIR',
+ self.DEFAULT_CONFIG_DIR)
+ conf_file = os.environ.get('TEMPEST_CONFIG', self.DEFAULT_CONFIG_FILE)
+
+ path = os.path.join(conf_dir, conf_file)
+
+ if not os.path.isfile(path):
+ path = failsafe_path
+
+ # only parse the config file if we expect one to exist. This is needed
+ # to remove an issue with the config file up to date checker.
+ if parse_conf:
+ config_files.append(path)
+
+ cfg.CONF([], project='tempest', default_config_files=config_files)
+ logging.setup('tempest')
+ LOG = logging.getLogger('tempest')
+ LOG.info("Using tempest config file %s" % path)
+ register_opts()
+ self._set_attrs()
if parse_conf:
cfg.CONF.log_opt_values(LOG, std_logging.DEBUG)
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
deleted file mode 100644
index ac88faa..0000000
--- a/tempest/exceptions.py
+++ /dev/null
@@ -1,187 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import testtools
-
-
-class TempestException(Exception):
- """
- Base Tempest Exception
-
- To correctly use this class, inherit from it and define
- a 'message' property. That message will get printf'd
- with the keyword arguments provided to the constructor.
- """
- message = "An unknown exception occurred"
-
- def __init__(self, *args, **kwargs):
- super(TempestException, self).__init__()
- try:
- self._error_string = self.message % kwargs
- except Exception:
- # at least get the core message out if something happened
- self._error_string = self.message
- if len(args) > 0:
- # If there is a non-kwarg parameter, assume it's the error
- # message or reason description and tack it on to the end
- # of the exception message
- # Convert all arguments into their string representations...
- args = ["%s" % arg for arg in args]
- self._error_string = (self._error_string +
- "\nDetails: %s" % '\n'.join(args))
-
- def __str__(self):
- return self._error_string
-
-
-class InvalidConfiguration(TempestException):
- message = "Invalid Configuration"
-
-
-class RestClientException(TempestException,
- testtools.TestCase.failureException):
- pass
-
-
-class InvalidHttpSuccessCode(RestClientException):
- message = "The success code is different than the expected one"
-
-
-class NotFound(RestClientException):
- message = "Object not found"
-
-
-class Unauthorized(RestClientException):
- message = 'Unauthorized'
-
-
-class InvalidServiceTag(RestClientException):
- message = "Invalid service tag"
-
-
-class TimeoutException(TempestException):
- message = "Request timed out"
-
-
-class BuildErrorException(TempestException):
- message = "Server %(server_id)s failed to build and is in ERROR status"
-
-
-class ImageKilledException(TempestException):
- message = "Image %(image_id)s 'killed' while waiting for '%(status)s'"
-
-
-class AddImageException(TempestException):
- message = "Image %(image_id)s failed to become ACTIVE in the allotted time"
-
-
-class EC2RegisterImageException(TempestException):
- message = ("Image %(image_id)s failed to become 'available' "
- "in the allotted time")
-
-
-class VolumeBuildErrorException(TempestException):
- message = "Volume %(volume_id)s failed to build and is in ERROR status"
-
-
-class SnapshotBuildErrorException(TempestException):
- message = "Snapshot %(snapshot_id)s failed to build and is in ERROR status"
-
-
-class VolumeBackupException(TempestException):
- message = "Volume backup %(backup_id)s failed and is in ERROR status"
-
-
-class StackBuildErrorException(TempestException):
- message = ("Stack %(stack_identifier)s is in %(stack_status)s status "
- "due to '%(stack_status_reason)s'")
-
-
-class BadRequest(RestClientException):
- message = "Bad request"
-
-
-class UnprocessableEntity(RestClientException):
- message = "Unprocessable entity"
-
-
-class AuthenticationFailure(RestClientException):
- message = ("Authentication with user %(user)s and password "
- "%(password)s failed auth using tenant %(tenant)s.")
-
-
-class EndpointNotFound(TempestException):
- message = "Endpoint not found"
-
-
-class RateLimitExceeded(TempestException):
- message = "Rate limit exceeded"
-
-
-class OverLimit(TempestException):
- message = "Quota exceeded"
-
-
-class ServerFault(TempestException):
- message = "Got server fault"
-
-
-class ImageFault(TempestException):
- message = "Got image fault"
-
-
-class IdentityError(TempestException):
- message = "Got identity error"
-
-
-class Conflict(RestClientException):
- message = "An object with that identifier already exists"
-
-
-class SSHTimeout(TempestException):
- message = ("Connection to the %(host)s via SSH timed out.\n"
- "User: %(user)s, Password: %(password)s")
-
-
-class SSHExecCommandFailed(TempestException):
- """Raised when remotely executed command returns nonzero status."""
- message = ("Command '%(command)s', exit status: %(exit_status)d, "
- "Error:\n%(strerror)s")
-
-
-class ServerUnreachable(TempestException):
- message = "The server is not reachable via the configured network"
-
-
-class TearDownException(TempestException):
- message = "%(num)d cleanUp operation failed"
-
-
-class RFCViolation(RestClientException):
- message = "RFC Violation"
-
-
-class ResponseWithNonEmptyBody(RFCViolation):
- message = ("RFC Violation! Response with %(status)d HTTP Status Code "
- "MUST NOT have a body")
-
-
-class ResponseWithEntity(RFCViolation):
- message = ("RFC Violation! Response with 205 HTTP Status Code "
- "MUST NOT have an entity")
-
-
-class InvalidHTTPResponseBody(RestClientException):
- message = "HTTP response body is invalid json or xml"
diff --git a/tempest/exceptions/README.rst b/tempest/exceptions/README.rst
new file mode 100644
index 0000000..dbe42b2
--- /dev/null
+++ b/tempest/exceptions/README.rst
@@ -0,0 +1,27 @@
+Tempest Field Guide to Exceptions
+=================================
+
+
+What are these exceptions?
+--------------------------
+
+These exceptions are used by Tempest for covering OpenStack specific exceptional
+cases.
+
+How to add new exceptions?
+--------------------------
+
+Each exception-template for inheritance purposes should be added into 'base'
+submodule.
+All other exceptions can be added in two ways:
+- in main module
+- in submodule
+But only in one of the ways. Need to make sure, that new exception is not
+present already.
+
+How to use exceptions?
+----------------------
+
+Any exceptions from this module or its submodules should be used in appropriate
+places to handle exceptional cases.
+Classes from 'base' module should be used only for inheritance.
diff --git a/tempest/exceptions/__init__.py b/tempest/exceptions/__init__.py
new file mode 100644
index 0000000..c95f94f
--- /dev/null
+++ b/tempest/exceptions/__init__.py
@@ -0,0 +1,148 @@
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.exceptions import base
+
+
+class InvalidConfiguration(base.TempestException):
+ message = "Invalid Configuration"
+
+
+class InvalidHttpSuccessCode(base.RestClientException):
+ message = "The success code is different than the expected one"
+
+
+class NotFound(base.RestClientException):
+ message = "Object not found"
+
+
+class Unauthorized(base.RestClientException):
+ message = 'Unauthorized'
+
+
+class InvalidServiceTag(base.RestClientException):
+ message = "Invalid service tag"
+
+
+class TimeoutException(base.TempestException):
+ message = "Request timed out"
+
+
+class BuildErrorException(base.TempestException):
+ message = "Server %(server_id)s failed to build and is in ERROR status"
+
+
+class ImageKilledException(base.TempestException):
+ message = "Image %(image_id)s 'killed' while waiting for '%(status)s'"
+
+
+class AddImageException(base.TempestException):
+ message = "Image %(image_id)s failed to become ACTIVE in the allotted time"
+
+
+class EC2RegisterImageException(base.TempestException):
+ message = ("Image %(image_id)s failed to become 'available' "
+ "in the allotted time")
+
+
+class VolumeBuildErrorException(base.TempestException):
+ message = "Volume %(volume_id)s failed to build and is in ERROR status"
+
+
+class SnapshotBuildErrorException(base.TempestException):
+ message = "Snapshot %(snapshot_id)s failed to build and is in ERROR status"
+
+
+class VolumeBackupException(base.TempestException):
+ message = "Volume backup %(backup_id)s failed and is in ERROR status"
+
+
+class StackBuildErrorException(base.TempestException):
+ message = ("Stack %(stack_identifier)s is in %(stack_status)s status "
+ "due to '%(stack_status_reason)s'")
+
+
+class BadRequest(base.RestClientException):
+ message = "Bad request"
+
+
+class UnprocessableEntity(base.RestClientException):
+ message = "Unprocessable entity"
+
+
+class AuthenticationFailure(base.RestClientException):
+ message = ("Authentication with user %(user)s and password "
+ "%(password)s failed auth using tenant %(tenant)s.")
+
+
+class EndpointNotFound(base.TempestException):
+ message = "Endpoint not found"
+
+
+class RateLimitExceeded(base.TempestException):
+ message = "Rate limit exceeded"
+
+
+class OverLimit(base.TempestException):
+ message = "Quota exceeded"
+
+
+class ServerFault(base.TempestException):
+ message = "Got server fault"
+
+
+class ImageFault(base.TempestException):
+ message = "Got image fault"
+
+
+class IdentityError(base.TempestException):
+ message = "Got identity error"
+
+
+class Conflict(base.RestClientException):
+ message = "An object with that identifier already exists"
+
+
+class SSHTimeout(base.TempestException):
+ message = ("Connection to the %(host)s via SSH timed out.\n"
+ "User: %(user)s, Password: %(password)s")
+
+
+class SSHExecCommandFailed(base.TempestException):
+ """Raised when remotely executed command returns nonzero status."""
+ message = ("Command '%(command)s', exit status: %(exit_status)d, "
+ "Error:\n%(strerror)s")
+
+
+class ServerUnreachable(base.TempestException):
+ message = "The server is not reachable via the configured network"
+
+
+class TearDownException(base.TempestException):
+ message = "%(num)d cleanUp operation failed"
+
+
+class ResponseWithNonEmptyBody(base.RFCViolation):
+ message = ("RFC Violation! Response with %(status)d HTTP Status Code "
+ "MUST NOT have a body")
+
+
+class ResponseWithEntity(base.RFCViolation):
+ message = ("RFC Violation! Response with 205 HTTP Status Code "
+ "MUST NOT have an entity")
+
+
+class InvalidHTTPResponseBody(base.RestClientException):
+ message = "HTTP response body is invalid json or xml"
diff --git a/tempest/exceptions/base.py b/tempest/exceptions/base.py
new file mode 100644
index 0000000..b8e470e
--- /dev/null
+++ b/tempest/exceptions/base.py
@@ -0,0 +1,55 @@
+# 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 testtools
+
+
+class TempestException(Exception):
+ """
+ Base Tempest Exception
+
+ To correctly use this class, inherit from it and define
+ a 'message' property. That message will get printf'd
+ with the keyword arguments provided to the constructor.
+ """
+ message = "An unknown exception occurred"
+
+ def __init__(self, *args, **kwargs):
+ super(TempestException, self).__init__()
+ try:
+ self._error_string = self.message % kwargs
+ except Exception:
+ # at least get the core message out if something happened
+ self._error_string = self.message
+ if len(args) > 0:
+ # If there is a non-kwarg parameter, assume it's the error
+ # message or reason description and tack it on to the end
+ # of the exception message
+ # Convert all arguments into their string representations...
+ args = ["%s" % arg for arg in args]
+ self._error_string = (self._error_string +
+ "\nDetails: %s" % '\n'.join(args))
+
+ def __str__(self):
+ return self._error_string
+
+
+class RestClientException(TempestException,
+ testtools.TestCase.failureException):
+ pass
+
+
+class RFCViolation(RestClientException):
+ message = "RFC Violation"
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 1b1ddab..f06a850 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -16,6 +16,7 @@
import logging
import os
+import six
import subprocess
import netaddr
@@ -371,7 +372,7 @@
return keypair
def get_remote_client(self, server_or_ip, username=None, private_key=None):
- if isinstance(server_or_ip, basestring):
+ if isinstance(server_or_ip, six.string_types):
ip = server_or_ip
else:
network_name_for_ssh = CONF.compute.network_for_ssh
@@ -512,7 +513,7 @@
ports = self._list_ports(tenant_id=tenant_id)
return len(ports)
- def _create_subnet(self, network, namestart='subnet-smoke-'):
+ def _create_subnet(self, network, namestart='subnet-smoke-', **kwargs):
"""
Create a subnet for the given network within the cidr block
configured for tenant networks.
@@ -545,6 +546,7 @@
cidr=str_cidr,
),
)
+ body['subnet'].update(kwargs)
try:
result = self.network_client.create_subnet(body=body)
break
@@ -702,6 +704,28 @@
private_key)
linux_client.validate_authentication()
+ def _check_remote_connectivity(self, source, dest, should_succeed=True):
+ """
+ check ping server via source ssh connection
+
+ :param source: RemoteClient: an ssh connection from which to ping
+ :param dest: and IP to ping against
+ :param should_succeed: boolean should ping succeed or not
+ :returns: boolean -- should_succeed == ping
+ :returns: ping is false if ping failed
+ """
+ def ping_remote():
+ try:
+ source.ping_host(dest)
+ except exceptions.SSHExecCommandFailed:
+ LOG.exception('Failed to ping host via ssh connection')
+ return not should_succeed
+ return should_succeed
+
+ return tempest.test.call_until_true(ping_remote,
+ CONF.compute.ping_timeout,
+ 1)
+
def _create_security_group_nova(self, client=None,
namestart='secgroup-smoke-',
tenant_id=None):
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 998a474..e441415 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -15,6 +15,9 @@
# under the License.
import collections
+import re
+
+from tempest.api.network import common as net_common
from tempest.common import debug
from tempest.common.utils import data_utils
from tempest import config
@@ -36,36 +39,6 @@
boot VM's with Neutron-managed networking, and attempts to
verify network connectivity as follows:
- * For a freshly-booted VM with an IP address ("port") on a given network:
-
- - the Tempest host can ping the IP address. This implies, but
- does not guarantee (see the ssh check that follows), that the
- VM has been assigned the correct IP address and has
- connectivity to the Tempest host.
-
- - the Tempest host can perform key-based authentication to an
- ssh server hosted at the IP address. This check guarantees
- that the IP address is associated with the target VM.
-
- - detach the floating-ip from the VM and verify that it becomes
- unreachable
-
- - associate detached floating ip to a new VM and verify connectivity.
- VMs are created with unique keypair so connectivity also asserts that
- floating IP is associated with the new VM instead of the old one
-
- # TODO(mnewby) - Need to implement the following:
- - the Tempest host can ssh into the VM via the IP address and
- successfully execute the following:
-
- - ping an external IP address, implying external connectivity.
-
- - ping an external hostname, implying that dns is correctly
- configured.
-
- - ping an internal IP address, implying connectivity to another
- VM on the same network.
-
There are presumed to be two types of networks: tenant and
public. A tenant network may or may not be reachable from the
Tempest host. A public network is assumed to be reachable from
@@ -250,9 +223,125 @@
self.floating_ip_tuple = Floating_IP_tuple(
floating_ip, serv_dict['server'])
+ def _create_new_network(self):
+ self.new_net = self._create_network(self.tenant_id)
+ self.addCleanup(self.cleanup_wrapper, self.new_net)
+ self.new_subnet = self._create_subnet(
+ network=self.new_net,
+ gateway_ip=None)
+ self.addCleanup(self.cleanup_wrapper, self.new_subnet)
+
+ def _hotplug_server(self):
+ old_floating_ip, server = self.floating_ip_tuple
+ ip_address = old_floating_ip.floating_ip_address
+ private_key = self.servers[server].private_key
+ ssh_client = self.get_remote_client(ip_address,
+ private_key=private_key)
+ old_nic_list = self._get_server_nics(ssh_client)
+ # get a port from a list of one item
+ port_list = self._list_ports(device_id=server.id)
+ self.assertEqual(1, len(port_list))
+ old_port = port_list[0]
+ self.compute_client.servers.interface_attach(server=server,
+ net_id=self.new_net.id,
+ port_id=None,
+ fixed_ip=None)
+ # move server to the head of the cleanup list
+ self.addCleanup(self.cleanup_wrapper, server)
+
+ def check_ports():
+ port_list = [port for port in
+ self._list_ports(device_id=server.id)
+ if port != old_port]
+ return len(port_list) == 1
+
+ test.call_until_true(check_ports, 60, 1)
+ new_port_list = [p for p in
+ self._list_ports(device_id=server.id)
+ if p != old_port]
+ self.assertEqual(1, len(new_port_list))
+ new_port = new_port_list[0]
+ new_port = net_common.DeletablePort(client=self.network_client,
+ **new_port)
+ new_nic_list = self._get_server_nics(ssh_client)
+ diff_list = [n for n in new_nic_list if n not in old_nic_list]
+ self.assertEqual(1, len(diff_list))
+ num, new_nic = diff_list[0]
+ ssh_client.assign_static_ip(nic=new_nic,
+ addr=new_port.fixed_ips[0]['ip_address'])
+ ssh_client.turn_nic_on(nic=new_nic)
+
+ def _get_server_nics(self, ssh_client):
+ reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
+ ipatxt = ssh_client.get_ip_list()
+ return reg.findall(ipatxt)
+
+ def _check_network_internal_connectivity(self):
+ """
+ via ssh check VM internal connectivity:
+ - ping internal DHCP port, implying in-tenant connectivty
+ """
+ floating_ip, server = self.floating_ip_tuple
+ # get internal ports' ips:
+ # get all network ports in the new network
+ internal_ips = (p['fixed_ips'][0]['ip_address'] for p in
+ self._list_ports(tenant_id=server.tenant_id,
+ network_id=self.new_net.id)
+ if p['device_owner'].startswith('network'))
+
+ ip_address = floating_ip.floating_ip_address
+ private_key = self.servers[server].private_key
+ ssh_source = self._ssh_to_server(ip_address, private_key)
+
+ for remote_ip in internal_ips:
+ try:
+ self.assertTrue(self._check_remote_connectivity(ssh_source,
+ remote_ip),
+ "Timed out waiting for %s to become "
+ "reachable" % remote_ip)
+ except Exception:
+ LOG.exception("Unable to access {dest} via ssh to "
+ "floating-ip {src}".format(dest=remote_ip,
+ src=floating_ip))
+ debug.log_ip_ns()
+ raise
+
@test.attr(type='smoke')
@test.services('compute', 'network')
def test_network_basic_ops(self):
+ """
+ For a freshly-booted VM with an IP address ("port") on a given
+ network:
+
+ - the Tempest host can ping the IP address. This implies, but
+ does not guarantee (see the ssh check that follows), that the
+ VM has been assigned the correct IP address and has
+ connectivity to the Tempest host.
+
+ - the Tempest host can perform key-based authentication to an
+ ssh server hosted at the IP address. This check guarantees
+ that the IP address is associated with the target VM.
+
+ - detach the floating-ip from the VM and verify that it becomes
+ unreachable
+
+ - associate detached floating ip to a new VM and verify connectivity.
+ VMs are created with unique keypair so connectivity also asserts that
+ floating IP is associated with the new VM instead of the old one
+
+ # TODO(mnewby) - Need to implement the following:
+ - the Tempest host can ssh into the VM via the IP address and
+ successfully execute the following:
+
+ - ping an external IP address, implying external connectivity.
+
+ - ping an external hostname, implying that dns is correctly
+ configured.
+
+ - ping an internal IP address, implying connectivity to another
+ VM on the same network.
+
+ """
self._check_public_network_connectivity(should_connect=True)
self._disassociate_floating_ips()
self._check_public_network_connectivity(should_connect=False,
@@ -262,3 +351,20 @@
self._check_public_network_connectivity(should_connect=True,
msg="after re-associate "
"floating ip")
+
+ @test.attr(type='smoke')
+ @test.services('compute', 'network')
+ def test_hotplug_nic(self):
+ """
+ 1. create a new network, with no gateway (to prevent overwriting VM's
+ gateway)
+ 2. connect VM to new network
+ 3. set static ip and bring new nic up
+ 4. check VM can ping new network dhcp port
+
+ """
+
+ self._check_public_network_connectivity(should_connect=True)
+ self._create_new_network()
+ self._hotplug_server()
+ self._check_network_internal_connectivity()
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index a26e0cf..d404dd1 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -17,7 +17,6 @@
from tempest.common import debug
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest.openstack.common import log as logging
from tempest.scenario import manager
from tempest import test
@@ -332,28 +331,6 @@
private_key=private_key)
return access_point_ssh
- def _test_remote_connectivity(self, source, dest, should_succeed=True):
- """
- check ping server via source ssh connection
-
- :param source: RemoteClient: an ssh connection from which to ping
- :param dest: and IP to ping against
- :param should_succeed: boolean should ping succeed or not
- :returns: boolean -- should_succeed == ping
- :returns: ping is false if ping failed
- """
- def ping_remote():
- try:
- source.ping_host(dest)
- except exceptions.SSHExecCommandFailed as ex:
- LOG.debug(ex)
- return not should_succeed
- return should_succeed
-
- return test.call_until_true(ping_remote,
- CONF.compute.ping_timeout,
- 1)
-
def _check_connectivity(self, access_point, ip, should_succeed=True):
if should_succeed:
msg = "Timed out waiting for %s to become reachable" % ip
@@ -362,8 +339,8 @@
return True
msg = "%s is reachable" % ip
try:
- self.assertTrue(self._test_remote_connectivity(access_point, ip,
- should_succeed),
+ self.assertTrue(self._check_remote_connectivity(access_point, ip,
+ should_succeed),
msg)
except Exception:
debug.log_ip_ns()
diff --git a/tempest/services/compute/json/aggregates_client.py b/tempest/services/compute/json/aggregates_client.py
index e26f570..700a29b 100644
--- a/tempest/services/compute/json/aggregates_client.py
+++ b/tempest/services/compute/json/aggregates_client.py
@@ -15,14 +15,14 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
CONF = config.CONF
-class AggregatesClientJSON(RestClient):
+class AggregatesClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(AggregatesClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/availability_zone_client.py b/tempest/services/compute/json/availability_zone_client.py
index ea4e95e..9278d5b 100644
--- a/tempest/services/compute/json/availability_zone_client.py
+++ b/tempest/services/compute/json/availability_zone_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class AvailabilityZoneClientJSON(RestClient):
+class AvailabilityZoneClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(AvailabilityZoneClientJSON, self).__init__(
diff --git a/tempest/services/compute/json/certificates_client.py b/tempest/services/compute/json/certificates_client.py
index de0f1a8..c05e352 100644
--- a/tempest/services/compute/json/certificates_client.py
+++ b/tempest/services/compute/json/certificates_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class CertificatesClientJSON(RestClient):
+class CertificatesClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(CertificatesClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/extensions_client.py b/tempest/services/compute/json/extensions_client.py
index f7e2737..5ad8b98 100644
--- a/tempest/services/compute/json/extensions_client.py
+++ b/tempest/services/compute/json/extensions_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class ExtensionsClientJSON(RestClient):
+class ExtensionsClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(ExtensionsClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/fixed_ips_client.py b/tempest/services/compute/json/fixed_ips_client.py
index af750a3..8b2c6c9 100644
--- a/tempest/services/compute/json/fixed_ips_client.py
+++ b/tempest/services/compute/json/fixed_ips_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class FixedIPsClientJSON(RestClient):
+class FixedIPsClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(FixedIPsClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/flavors_client.py b/tempest/services/compute/json/flavors_client.py
index 289b09e..a8111af 100644
--- a/tempest/services/compute/json/flavors_client.py
+++ b/tempest/services/compute/json/flavors_client.py
@@ -16,13 +16,13 @@
import json
import urllib
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class FlavorsClientJSON(RestClient):
+class FlavorsClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(FlavorsClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/floating_ips_client.py b/tempest/services/compute/json/floating_ips_client.py
index 0385160..42487c3 100644
--- a/tempest/services/compute/json/floating_ips_client.py
+++ b/tempest/services/compute/json/floating_ips_client.py
@@ -16,14 +16,14 @@
import json
import urllib
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
CONF = config.CONF
-class FloatingIPsClientJSON(RestClient):
+class FloatingIPsClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(FloatingIPsClientJSON, self).__init__(auth_provider)
self.service = CONF.compute.catalog_type
diff --git a/tempest/services/compute/json/hosts_client.py b/tempest/services/compute/json/hosts_client.py
index d826a78..fb45997 100644
--- a/tempest/services/compute/json/hosts_client.py
+++ b/tempest/services/compute/json/hosts_client.py
@@ -15,13 +15,13 @@
import json
import urllib
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class HostsClientJSON(RestClient):
+class HostsClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(HostsClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/hypervisor_client.py b/tempest/services/compute/json/hypervisor_client.py
index 74844dc..c6b13b0 100644
--- a/tempest/services/compute/json/hypervisor_client.py
+++ b/tempest/services/compute/json/hypervisor_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class HypervisorClientJSON(RestClient):
+class HypervisorClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(HypervisorClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/images_client.py b/tempest/services/compute/json/images_client.py
index b3d8c35..5a79a29 100644
--- a/tempest/services/compute/json/images_client.py
+++ b/tempest/services/compute/json/images_client.py
@@ -16,7 +16,7 @@
import json
import urllib
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest.common import waiters
from tempest import config
from tempest import exceptions
@@ -24,7 +24,7 @@
CONF = config.CONF
-class ImagesClientJSON(RestClient):
+class ImagesClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(ImagesClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/instance_usage_audit_log_client.py b/tempest/services/compute/json/instance_usage_audit_log_client.py
index 27930f2..1f6e988 100644
--- a/tempest/services/compute/json/instance_usage_audit_log_client.py
+++ b/tempest/services/compute/json/instance_usage_audit_log_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class InstanceUsagesAuditLogClientJSON(RestClient):
+class InstanceUsagesAuditLogClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(InstanceUsagesAuditLogClientJSON, self).__init__(
diff --git a/tempest/services/compute/json/interfaces_client.py b/tempest/services/compute/json/interfaces_client.py
index f4c4c64..9928b94 100644
--- a/tempest/services/compute/json/interfaces_client.py
+++ b/tempest/services/compute/json/interfaces_client.py
@@ -16,14 +16,14 @@
import json
import time
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
CONF = config.CONF
-class InterfacesClientJSON(RestClient):
+class InterfacesClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(InterfacesClientJSON, self).__init__(auth_provider)
@@ -80,3 +80,25 @@
raise exceptions.TimeoutException(message)
return resp, body
+
+ def add_fixed_ip(self, server_id, network_id):
+ """Add a fixed IP to input server instance."""
+ post_body = json.dumps({
+ 'addFixedIp': {
+ 'networkId': network_id
+ }
+ })
+ resp, body = self.post('servers/%s/action' % str(server_id),
+ post_body)
+ return resp, body
+
+ def remove_fixed_ip(self, server_id, ip_address):
+ """Remove input fixed IP from input server instance."""
+ post_body = json.dumps({
+ 'removeFixedIp': {
+ 'address': ip_address
+ }
+ })
+ resp, body = self.post('servers/%s/action' % str(server_id),
+ post_body)
+ return resp, body
diff --git a/tempest/services/compute/json/keypairs_client.py b/tempest/services/compute/json/keypairs_client.py
index 356c2e6..28f3c31 100644
--- a/tempest/services/compute/json/keypairs_client.py
+++ b/tempest/services/compute/json/keypairs_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class KeyPairsClientJSON(RestClient):
+class KeyPairsClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(KeyPairsClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/limits_client.py b/tempest/services/compute/json/limits_client.py
index 765ba79..1493718 100644
--- a/tempest/services/compute/json/limits_client.py
+++ b/tempest/services/compute/json/limits_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class LimitsClientJSON(RestClient):
+class LimitsClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(LimitsClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/quotas_client.py b/tempest/services/compute/json/quotas_client.py
index 7607cc0..459ab6d 100644
--- a/tempest/services/compute/json/quotas_client.py
+++ b/tempest/services/compute/json/quotas_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class QuotasClientJSON(RestClient):
+class QuotasClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(QuotasClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/security_groups_client.py b/tempest/services/compute/json/security_groups_client.py
index 2cd2d2e..899d4ef 100644
--- a/tempest/services/compute/json/security_groups_client.py
+++ b/tempest/services/compute/json/security_groups_client.py
@@ -16,14 +16,14 @@
import json
import urllib
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
CONF = config.CONF
-class SecurityGroupsClientJSON(RestClient):
+class SecurityGroupsClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(SecurityGroupsClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 025c4e5..623bf42 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -18,7 +18,7 @@
import time
import urllib
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest.common import waiters
from tempest import config
from tempest import exceptions
@@ -26,7 +26,7 @@
CONF = config.CONF
-class ServersClientJSON(RestClient):
+class ServersClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(ServersClientJSON, self).__init__(auth_provider)
@@ -428,3 +428,11 @@
def restore_soft_deleted_server(self, server_id, **kwargs):
"""Restore a soft-deleted server."""
return self.action(server_id, 'restore', None, **kwargs)
+
+ def reset_network(self, server_id, **kwargs):
+ """Resets the Network of a server"""
+ return self.action(server_id, 'resetNetwork', None, **kwargs)
+
+ def inject_network_info(self, server_id, **kwargs):
+ """Inject the Network Info into server"""
+ return self.action(server_id, 'injectNetworkInfo', None, **kwargs)
diff --git a/tempest/services/compute/json/services_client.py b/tempest/services/compute/json/services_client.py
index 8380dc2..1ab25ec 100644
--- a/tempest/services/compute/json/services_client.py
+++ b/tempest/services/compute/json/services_client.py
@@ -17,13 +17,13 @@
import json
import urllib
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class ServicesClientJSON(RestClient):
+class ServicesClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(ServicesClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/tenant_usages_client.py b/tempest/services/compute/json/tenant_usages_client.py
index b14fa9b..f3a67dd 100644
--- a/tempest/services/compute/json/tenant_usages_client.py
+++ b/tempest/services/compute/json/tenant_usages_client.py
@@ -16,13 +16,13 @@
import json
import urllib
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class TenantUsagesClientJSON(RestClient):
+class TenantUsagesClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(TenantUsagesClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/compute/json/volumes_extensions_client.py b/tempest/services/compute/json/volumes_extensions_client.py
index 4b9dc0b..5ef11ed 100644
--- a/tempest/services/compute/json/volumes_extensions_client.py
+++ b/tempest/services/compute/json/volumes_extensions_client.py
@@ -17,14 +17,14 @@
import time
import urllib
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
CONF = config.CONF
-class VolumesExtensionsClientJSON(RestClient):
+class VolumesExtensionsClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(VolumesExtensionsClientJSON, self).__init__(
diff --git a/tempest/services/compute/v3/json/interfaces_client.py b/tempest/services/compute/v3/json/interfaces_client.py
index c167520..f8b9d09 100644
--- a/tempest/services/compute/v3/json/interfaces_client.py
+++ b/tempest/services/compute/v3/json/interfaces_client.py
@@ -81,3 +81,25 @@
raise exceptions.TimeoutException(message)
return resp, body
+
+ def add_fixed_ip(self, server_id, network_id):
+ """Add a fixed IP to input server instance."""
+ post_body = json.dumps({
+ 'add_fixed_ip': {
+ 'network_id': network_id
+ }
+ })
+ resp, body = self.post('servers/%s/action' % str(server_id),
+ post_body)
+ return resp, body
+
+ def remove_fixed_ip(self, server_id, ip_address):
+ """Remove input fixed IP from input server instance."""
+ post_body = json.dumps({
+ 'remove_fixed_ip': {
+ 'address': ip_address
+ }
+ })
+ resp, body = self.post('servers/%s/action' % str(server_id),
+ post_body)
+ return resp, body
diff --git a/tempest/services/compute/xml/common.py b/tempest/services/compute/xml/common.py
index 4def19f..b29b932 100644
--- a/tempest/services/compute/xml/common.py
+++ b/tempest/services/compute/xml/common.py
@@ -18,6 +18,11 @@
XMLNS_11 = "http://docs.openstack.org/compute/api/v1.1"
XMLNS_V3 = "http://docs.openstack.org/compute/api/v1.1"
+NEUTRON_NAMESPACES = {
+ 'router': "http://docs.openstack.org/ext/neutron/router/api/v1.0",
+ 'provider': 'http://docs.openstack.org/ext/provider/api/v1.0',
+}
+
# NOTE(danms): This is just a silly implementation to help make generating
# XML faster for prototyping. Could be replaced with proper etree gorp
@@ -137,6 +142,9 @@
tag = child.tag
if tag.startswith("{"):
ns, tag = tag.split("}", 1)
+ for key, uri in NEUTRON_NAMESPACES.iteritems():
+ if uri == ns[1:]:
+ tag = key + ":" + tag
if plurals is not None and tag in plurals:
json[tag] = parse_array(child, plurals)
else:
diff --git a/tempest/services/compute/xml/interfaces_client.py b/tempest/services/compute/xml/interfaces_client.py
index 5df6187..8d4bfcc 100644
--- a/tempest/services/compute/xml/interfaces_client.py
+++ b/tempest/services/compute/xml/interfaces_client.py
@@ -24,6 +24,7 @@
from tempest.services.compute.xml.common import Element
from tempest.services.compute.xml.common import Text
from tempest.services.compute.xml.common import xml_to_json
+from tempest.services.compute.xml.common import XMLNS_11
CONF = config.CONF
@@ -104,3 +105,21 @@
(port_id, status, self.build_timeout))
raise exceptions.TimeoutException(message)
return resp, body
+
+ def add_fixed_ip(self, server_id, network_id):
+ """Add a fixed IP to input server instance."""
+ post_body = Element("addFixedIp",
+ xmlns=XMLNS_11,
+ networkId=network_id)
+ resp, body = self.post('servers/%s/action' % str(server_id),
+ str(Document(post_body)))
+ return resp, body
+
+ def remove_fixed_ip(self, server_id, ip_address):
+ """Remove input fixed IP from input server instance."""
+ post_body = Element("removeFixedIp",
+ xmlns=XMLNS_11,
+ address=ip_address)
+ resp, body = self.post('servers/%s/action' % str(server_id),
+ str(Document(post_body)))
+ return resp, body
diff --git a/tempest/services/compute/xml/servers_client.py b/tempest/services/compute/xml/servers_client.py
index da01b83..cd2cb06 100644
--- a/tempest/services/compute/xml/servers_client.py
+++ b/tempest/services/compute/xml/servers_client.py
@@ -633,3 +633,11 @@
def restore_soft_deleted_server(self, server_id, **kwargs):
"""Restore a soft-deleted server."""
return self.action(server_id, 'restore', None, **kwargs)
+
+ def reset_network(self, server_id, **kwargs):
+ """Resets the Network of a server"""
+ return self.action(server_id, 'resetNetwork', None, **kwargs)
+
+ def inject_network_info(self, server_id, **kwargs):
+ """Inject the Network Info into server"""
+ return self.action(server_id, 'injectNetworkInfo', None, **kwargs)
diff --git a/tempest/services/identity/v3/json/credentials_client.py b/tempest/services/identity/v3/json/credentials_client.py
index 5d6632a..f795c7b 100644
--- a/tempest/services/identity/v3/json/credentials_client.py
+++ b/tempest/services/identity/v3/json/credentials_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class CredentialsClientJSON(RestClient):
+class CredentialsClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(CredentialsClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/identity/v3/json/endpoints_client.py b/tempest/services/identity/v3/json/endpoints_client.py
index 652c345..c3c1e15 100644
--- a/tempest/services/identity/v3/json/endpoints_client.py
+++ b/tempest/services/identity/v3/json/endpoints_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class EndPointClientJSON(RestClient):
+class EndPointClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(EndPointClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index b044e4d..65f3355 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -15,14 +15,14 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
CONF = config.CONF
-class IdentityV3ClientJSON(RestClient):
+class IdentityV3ClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(IdentityV3ClientJSON, self).__init__(auth_provider)
@@ -439,7 +439,7 @@
return resp, body
-class V3TokenClientJSON(RestClient):
+class V3TokenClientJSON(rest_client.RestClient):
def __init__(self):
super(V3TokenClientJSON, self).__init__(None)
diff --git a/tempest/services/identity/v3/json/policy_client.py b/tempest/services/identity/v3/json/policy_client.py
index 5a3f891..3c90fa1 100644
--- a/tempest/services/identity/v3/json/policy_client.py
+++ b/tempest/services/identity/v3/json/policy_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class PolicyClientJSON(RestClient):
+class PolicyClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(PolicyClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/identity/v3/json/service_client.py b/tempest/services/identity/v3/json/service_client.py
index c1faebb..b66fb4a 100644
--- a/tempest/services/identity/v3/json/service_client.py
+++ b/tempest/services/identity/v3/json/service_client.py
@@ -15,13 +15,13 @@
import json
-from tempest.common.rest_client import RestClient
+from tempest.common import rest_client
from tempest import config
CONF = config.CONF
-class ServiceClientJSON(RestClient):
+class ServiceClientJSON(rest_client.RestClient):
def __init__(self, auth_provider):
super(ServiceClientJSON, self).__init__(auth_provider)
diff --git a/tempest/services/identity/v3/xml/credentials_client.py b/tempest/services/identity/v3/xml/credentials_client.py
index 22ed44d..70f85a1 100644
--- a/tempest/services/identity/v3/xml/credentials_client.py
+++ b/tempest/services/identity/v3/xml/credentials_client.py
@@ -19,10 +19,7 @@
from tempest.common import rest_client
from tempest import config
-from tempest.services.compute.xml.common import Document
-from tempest.services.compute.xml.common import Element
-from tempest.services.compute.xml.common import Text
-from tempest.services.compute.xml.common import xml_to_json
+from tempest.services.compute.xml import common
CONF = config.CONF
@@ -39,7 +36,7 @@
self.api_version = "v3"
def _parse_body(self, body):
- data = xml_to_json(body)
+ data = common.xml_to_json(body)
return data
def _parse_creds(self, node):
@@ -47,7 +44,7 @@
for child in node.getchildren():
tag_list = child.tag.split('}', 1)
if tag_list[1] == "credential":
- array.append(xml_to_json(child))
+ array.append(common.xml_to_json(child))
return array
def create_credential(self, access_key, secret_key, user_id, project_id):
@@ -55,14 +52,14 @@
cred_type = 'ec2'
access = ""access": "%s"" % access_key
secret = ""secret": "%s"" % secret_key
- blob = Element('blob',
- xmlns=XMLNS)
- blob.append(Text("{%s , %s}"
- % (access, secret)))
- credential = Element('credential', project_id=project_id,
- type=cred_type, user_id=user_id)
+ blob = common.Element('blob',
+ xmlns=XMLNS)
+ blob.append(common.Text("{%s , %s}"
+ % (access, secret)))
+ credential = common.Element('credential', project_id=project_id,
+ type=cred_type, user_id=user_id)
credential.append(blob)
- resp, body = self.post('credentials', str(Document(credential)))
+ resp, body = self.post('credentials', str(common.Document(credential)))
body = self._parse_body(etree.fromstring(body))
body['blob'] = json.loads(body['blob'])
return resp, body
@@ -77,15 +74,15 @@
user_id = kwargs.get('user_id', body['user_id'])
access = ""access": "%s"" % access_key
secret = ""secret": "%s"" % secret_key
- blob = Element('blob',
- xmlns=XMLNS)
- blob.append(Text("{%s , %s}"
- % (access, secret)))
- credential = Element('credential', project_id=project_id,
- type=cred_type, user_id=user_id)
+ blob = common.Element('blob',
+ xmlns=XMLNS)
+ blob.append(common.Text("{%s , %s}"
+ % (access, secret)))
+ credential = common.Element('credential', project_id=project_id,
+ type=cred_type, user_id=user_id)
credential.append(blob)
resp, body = self.patch('credentials/%s' % credential_id,
- str(Document(credential)))
+ str(common.Document(credential)))
body = self._parse_body(etree.fromstring(body))
body['blob'] = json.loads(body['blob'])
return resp, body
diff --git a/tempest/services/identity/v3/xml/endpoints_client.py b/tempest/services/identity/v3/xml/endpoints_client.py
index a32eede..cc9aa65 100644
--- a/tempest/services/identity/v3/xml/endpoints_client.py
+++ b/tempest/services/identity/v3/xml/endpoints_client.py
@@ -18,9 +18,7 @@
from tempest.common import http
from tempest.common import rest_client
from tempest import config
-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 import common
CONF = config.CONF
@@ -41,11 +39,11 @@
for child in node.getchildren():
tag_list = child.tag.split('}', 1)
if tag_list[1] == "endpoint":
- array.append(xml_to_json(child))
+ array.append(common.xml_to_json(child))
return array
def _parse_body(self, body):
- json = xml_to_json(body)
+ json = common.xml_to_json(body)
return json
def request(self, method, url, headers=None, body=None, wait=None):
@@ -67,21 +65,24 @@
"""Create endpoint."""
region = kwargs.get('region', None)
enabled = kwargs.get('enabled', None)
- create_endpoint = Element("endpoint",
- xmlns=XMLNS,
- service_id=service_id,
- interface=interface,
- url=url, region=region,
- enabled=enabled)
- resp, body = self.post('endpoints', str(Document(create_endpoint)))
+ if enabled is not None:
+ enabled = str(enabled).lower()
+ create_endpoint = common.Element("endpoint",
+ xmlns=XMLNS,
+ service_id=service_id,
+ interface=interface,
+ url=url, region=region,
+ enabled=enabled)
+ resp, body = self.post('endpoints',
+ str(common.Document(create_endpoint)))
body = self._parse_body(etree.fromstring(body))
return resp, body
def update_endpoint(self, endpoint_id, service_id=None, interface=None,
url=None, region=None, enabled=None):
"""Updates an endpoint with given parameters."""
- doc = Document()
- endpoint = Element("endpoint")
+ doc = common.Document()
+ endpoint = common.Element("endpoint")
doc.append(endpoint)
if service_id:
@@ -93,7 +94,7 @@
if region:
endpoint.add_attr("region", region)
if enabled is not None:
- endpoint.add_attr("enabled", enabled)
+ endpoint.add_attr("enabled", str(enabled).lower())
resp, body = self.patch('endpoints/%s' % str(endpoint_id), str(doc))
body = self._parse_body(etree.fromstring(body))
return resp, body
diff --git a/tempest/services/identity/v3/xml/identity_client.py b/tempest/services/identity/v3/xml/identity_client.py
index e8e70d8..6ff6d56 100644
--- a/tempest/services/identity/v3/xml/identity_client.py
+++ b/tempest/services/identity/v3/xml/identity_client.py
@@ -20,10 +20,7 @@
from tempest.common import rest_client
from tempest import config
from tempest import exceptions
-from tempest.services.compute.xml.common import Document
-from tempest.services.compute.xml.common import Element
-from tempest.services.compute.xml.common import Text
-from tempest.services.compute.xml.common import xml_to_json
+from tempest.services.compute.xml import common
CONF = config.CONF
@@ -44,7 +41,7 @@
for child in node.getchildren():
tag_list = child.tag.split('}', 1)
if tag_list[1] == "project":
- array.append(xml_to_json(child))
+ array.append(common.xml_to_json(child))
return array
def _parse_domains(self, node):
@@ -52,7 +49,7 @@
for child in node.getchildren():
tag_list = child.tag.split('}', 1)
if tag_list[1] == "domain":
- array.append(xml_to_json(child))
+ array.append(common.xml_to_json(child))
return array
def _parse_group_users(self, node):
@@ -60,7 +57,7 @@
for child in node.getchildren():
tag_list = child.tag.split('}', 1)
if tag_list[1] == "user":
- array.append(xml_to_json(child))
+ array.append(common.xml_to_json(child))
return array
def _parse_roles(self, node):
@@ -68,17 +65,17 @@
for child in node.getchildren():
tag_list = child.tag.split('}', 1)
if tag_list[1] == "role":
- array.append(xml_to_json(child))
+ array.append(common.xml_to_json(child))
return array
def _parse_array(self, node):
array = []
for child in node.getchildren():
- array.append(xml_to_json(child))
+ array.append(common.xml_to_json(child))
return array
def _parse_body(self, body):
- _json = xml_to_json(body)
+ _json = common.xml_to_json(body)
return _json
def create_user(self, user_name, **kwargs):
@@ -89,16 +86,16 @@
project_id = kwargs.get('project_id', None)
description = kwargs.get('description', None)
domain_id = kwargs.get('domain_id', 'default')
- post_body = Element("user",
- xmlns=XMLNS,
- name=user_name,
- password=password,
- description=description,
- email=email,
- enabled=str(en).lower(),
- project_id=project_id,
- domain_id=domain_id)
- resp, body = self.post('users', str(Document(post_body)))
+ post_body = common.Element("user",
+ xmlns=XMLNS,
+ name=user_name,
+ password=password,
+ description=description,
+ email=email,
+ enabled=str(en).lower(),
+ project_id=project_id,
+ domain_id=domain_id)
+ resp, body = self.post('users', str(common.Document(post_body)))
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -110,16 +107,16 @@
project_id = kwargs.get('project_id', body['project_id'])
description = kwargs.get('description', body['description'])
domain_id = kwargs.get('domain_id', body['domain_id'])
- update_user = Element("user",
- xmlns=XMLNS,
- name=name,
- email=email,
- project_id=project_id,
- domain_id=domain_id,
- description=description,
- enabled=str(en).lower())
+ update_user = common.Element("user",
+ xmlns=XMLNS,
+ name=name,
+ email=email,
+ project_id=project_id,
+ domain_id=domain_id,
+ description=description,
+ enabled=str(en).lower())
resp, body = self.patch('users/%s' % user_id,
- str(Document(update_user)))
+ str(common.Document(update_user)))
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -151,14 +148,14 @@
description = kwargs.get('description', None)
en = kwargs.get('enabled', 'true')
domain_id = kwargs.get('domain_id', 'default')
- post_body = Element("project",
- xmlns=XMLNS,
- description=description,
- domain_id=domain_id,
- enabled=str(en).lower(),
- name=name)
+ post_body = common.Element("project",
+ xmlns=XMLNS,
+ description=description,
+ domain_id=domain_id,
+ enabled=str(en).lower(),
+ name=name)
resp, body = self.post('projects',
- str(Document(post_body)))
+ str(common.Document(post_body)))
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -175,14 +172,14 @@
desc = kwargs.get('description', body['description'])
en = kwargs.get('enabled', body['enabled'])
domain_id = kwargs.get('domain_id', body['domain_id'])
- post_body = Element("project",
- xmlns=XMLNS,
- name=name,
- description=desc,
- enabled=str(en).lower(),
- domain_id=domain_id)
+ post_body = common.Element("project",
+ xmlns=XMLNS,
+ name=name,
+ description=desc,
+ enabled=str(en).lower(),
+ domain_id=domain_id)
resp, body = self.patch('projects/%s' % project_id,
- str(Document(post_body)))
+ str(common.Document(post_body)))
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -199,10 +196,10 @@
def create_role(self, name):
"""Create a Role."""
- post_body = Element("role",
- xmlns=XMLNS,
- name=name)
- resp, body = self.post('roles', str(Document(post_body)))
+ post_body = common.Element("role",
+ xmlns=XMLNS,
+ name=name)
+ resp, body = self.post('roles', str(common.Document(post_body)))
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -214,11 +211,11 @@
def update_role(self, name, role_id):
"""Updates a Role."""
- post_body = Element("role",
- xmlns=XMLNS,
- name=name)
+ post_body = common.Element("role",
+ xmlns=XMLNS,
+ name=name)
resp, body = self.patch('roles/%s' % str(role_id),
- str(Document(post_body)))
+ str(common.Document(post_body)))
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -237,12 +234,12 @@
"""Creates a domain."""
description = kwargs.get('description', None)
en = kwargs.get('enabled', True)
- post_body = Element("domain",
- xmlns=XMLNS,
- name=name,
- description=description,
- enabled=str(en).lower())
- resp, body = self.post('domains', str(Document(post_body)))
+ post_body = common.Element("domain",
+ xmlns=XMLNS,
+ name=name,
+ description=description,
+ enabled=str(en).lower())
+ resp, body = self.post('domains', str(common.Document(post_body)))
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -263,13 +260,13 @@
description = kwargs.get('description', body['description'])
en = kwargs.get('enabled', body['enabled'])
name = kwargs.get('name', body['name'])
- post_body = Element("domain",
- xmlns=XMLNS,
- name=name,
- description=description,
- enabled=str(en).lower())
+ post_body = common.Element("domain",
+ xmlns=XMLNS,
+ name=name,
+ description=description,
+ enabled=str(en).lower())
resp, body = self.patch('domains/%s' % domain_id,
- str(Document(post_body)))
+ str(common.Document(post_body)))
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -299,13 +296,13 @@
description = kwargs.get('description', None)
domain_id = kwargs.get('domain_id', 'default')
project_id = kwargs.get('project_id', None)
- post_body = Element("group",
- xmlns=XMLNS,
- name=name,
- description=description,
- domain_id=domain_id,
- project_id=project_id)
- resp, body = self.post('groups', str(Document(post_body)))
+ post_body = common.Element("group",
+ xmlns=XMLNS,
+ name=name,
+ description=description,
+ domain_id=domain_id,
+ project_id=project_id)
+ resp, body = self.post('groups', str(common.Document(post_body)))
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -320,12 +317,12 @@
resp, body = self.get_group(group_id)
name = kwargs.get('name', body['name'])
description = kwargs.get('description', body['description'])
- post_body = Element("group",
- xmlns=XMLNS,
- name=name,
- description=description)
+ post_body = common.Element("group",
+ xmlns=XMLNS,
+ name=name,
+ description=description)
resp, body = self.patch('groups/%s' % group_id,
- str(Document(post_body)))
+ str(common.Document(post_body)))
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -456,35 +453,35 @@
Validation is left to the server side.
"""
if user_type == 'id':
- _user = Element('user', id=user, password=password)
+ _user = common.Element('user', id=user, password=password)
else:
- _user = Element('user', name=user, password=password)
+ _user = common.Element('user', name=user, password=password)
if domain is not None:
- _domain = Element('domain', name=domain)
+ _domain = common.Element('domain', name=domain)
_user.append(_domain)
- password = Element('password')
+ password = common.Element('password')
password.append(_user)
- method = Element('method')
- method.append(Text('password'))
- methods = Element('methods')
+ method = common.Element('method')
+ method.append(common.Text('password'))
+ methods = common.Element('methods')
methods.append(method)
- identity = Element('identity')
+ identity = common.Element('identity')
identity.append(methods)
identity.append(password)
- auth = Element('auth')
+ auth = common.Element('auth')
auth.append(identity)
if tenant is not None:
- project = Element('project', name=tenant)
+ project = common.Element('project', name=tenant)
project.append(_domain)
- scope = Element('scope')
+ scope = common.Element('scope')
scope.append(project)
auth.append(scope)
- resp, body = self.post(self.auth_url, body=str(Document(auth)))
+ resp, body = self.post(self.auth_url, body=str(common.Document(auth)))
return resp, body
def request(self, method, url, headers=None, body=None):
diff --git a/tempest/services/identity/v3/xml/policy_client.py b/tempest/services/identity/v3/xml/policy_client.py
index c12018a..bf4cce7 100644
--- a/tempest/services/identity/v3/xml/policy_client.py
+++ b/tempest/services/identity/v3/xml/policy_client.py
@@ -18,9 +18,7 @@
from tempest.common import http
from tempest.common import rest_client
from tempest import config
-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 import common
CONF = config.CONF
@@ -41,11 +39,11 @@
for child in node.getchildren():
tag_list = child.tag.split('}', 1)
if tag_list[1] == "policy":
- array.append(xml_to_json(child))
+ array.append(common.xml_to_json(child))
return array
def _parse_body(self, body):
- json = xml_to_json(body)
+ json = common.xml_to_json(body)
return json
def request(self, method, url, headers=None, body=None, wait=None):
@@ -59,8 +57,9 @@
def create_policy(self, blob, type):
"""Creates a Policy."""
- create_policy = Element("policy", xmlns=XMLNS, blob=blob, type=type)
- resp, body = self.post('policies', str(Document(create_policy)))
+ create_policy = common.Element("policy", xmlns=XMLNS,
+ blob=blob, type=type)
+ resp, body = self.post('policies', str(common.Document(create_policy)))
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -81,9 +80,9 @@
"""Updates a policy."""
resp, body = self.get_policy(policy_id)
type = kwargs.get('type')
- update_policy = Element("policy", xmlns=XMLNS, type=type)
+ update_policy = common.Element("policy", xmlns=XMLNS, type=type)
url = 'policies/%s' % policy_id
- resp, body = self.patch(url, str(Document(update_policy)))
+ resp, body = self.patch(url, str(common.Document(update_policy)))
body = self._parse_body(etree.fromstring(body))
return resp, body
diff --git a/tempest/services/identity/v3/xml/service_client.py b/tempest/services/identity/v3/xml/service_client.py
index d4a5877..966d7f7 100644
--- a/tempest/services/identity/v3/xml/service_client.py
+++ b/tempest/services/identity/v3/xml/service_client.py
@@ -17,9 +17,7 @@
from tempest.common import rest_client
from tempest import config
-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 import common
CONF = config.CONF
@@ -36,7 +34,7 @@
self.api_version = "v3"
def _parse_body(self, body):
- data = xml_to_json(body)
+ data = common.xml_to_json(body)
return data
def update_service(self, service_id, **kwargs):
@@ -45,14 +43,14 @@
name = kwargs.get('name', body['name'])
description = kwargs.get('description', body['description'])
type = kwargs.get('type', body['type'])
- update_service = Element("service",
- xmlns=XMLNS,
- id=service_id,
- name=name,
- description=description,
- type=type)
+ update_service = common.Element("service",
+ xmlns=XMLNS,
+ id=service_id,
+ name=name,
+ description=description,
+ type=type)
resp, body = self.patch('services/%s' % service_id,
- str(Document(update_service)))
+ str(common.Document(update_service)))
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -64,12 +62,12 @@
return resp, body
def create_service(self, serv_type, name=None, description=None):
- post_body = Element("service",
- xmlns=XMLNS,
- name=name,
- description=description,
- type=serv_type)
- resp, body = self.post("services", str(Document(post_body)))
+ post_body = common.Element("service",
+ xmlns=XMLNS,
+ name=name,
+ description=description,
+ type=serv_type)
+ resp, body = self.post("services", str(common.Document(post_body)))
body = self._parse_body(etree.fromstring(body))
return resp, body
diff --git a/tempest/services/image/v2/json/image_client.py b/tempest/services/image/v2/json/image_client.py
index 30c6ffc..b3014fc 100644
--- a/tempest/services/image/v2/json/image_client.py
+++ b/tempest/services/image/v2/json/image_client.py
@@ -39,23 +39,9 @@
filters=self.filters,
insecure=dscv)
- def get_images_schema(self):
- url = 'v2/schemas/images'
- resp, body = self.get(url)
- body = json.loads(body)
- return resp, body
-
- def get_image_schema(self):
- url = 'v2/schemas/image'
- resp, body = self.get(url)
- body = json.loads(body)
- return resp, body
-
def _validate_schema(self, body, type='image'):
- if type == 'image':
- resp, schema = self.get_image_schema()
- elif type == 'images':
- resp, schema = self.get_images_schema()
+ if type in ['image', 'images']:
+ resp, schema = self.get_schema(type)
else:
raise ValueError("%s is not a valid schema type" % type)
@@ -184,3 +170,9 @@
resp, _ = self.delete(url)
self.expected_success(204, resp)
return resp
+
+ def get_schema(self, schema):
+ url = 'v2/schemas/%s' % schema
+ resp, body = self.get(url)
+ body = json.loads(body)
+ return resp, body
diff --git a/tempest/services/network/xml/network_client.py b/tempest/services/network/xml/network_client.py
index c520018..8152d71 100644
--- a/tempest/services/network/xml/network_client.py
+++ b/tempest/services/network/xml/network_client.py
@@ -43,9 +43,14 @@
post_body = common.Element(root)
post_body.add_attr('xmlns:xsi',
'http://www.w3.org/2001/XMLSchema-instance')
+ elements = set()
for name, attr in body[root].items():
elt = self._get_element(name, attr)
post_body.append(elt)
+ if ":" in name:
+ elements.add(name.split(":")[0])
+ if elements:
+ self._add_namespaces(post_body, elements)
return str(common.Document(post_body))
def serialize_list(self, body, root_name=None, item_name=None):
@@ -82,6 +87,11 @@
else:
return common.Element(name, value)
+ def _add_namespaces(self, root, elements):
+ for element in elements:
+ root.add_attr('xmlns:%s' % element,
+ common.NEUTRON_NAMESPACES[element])
+
def create_member(self, address, protocol_port, pool_id):
uri = '%s/lb/members' % (self.uri_prefix)
post_body = common.Element("member")
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index 3715636..9660081 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -17,6 +17,8 @@
import signal
import time
+from six import moves
+
from tempest import clients
from tempest.common import ssh
from tempest.common.utils import data_utils
@@ -128,7 +130,7 @@
manager = admin_manager
else:
manager = clients.Manager()
- for p_number in xrange(test.get('threads', default_thread_num)):
+ for p_number in moves.xrange(test.get('threads', default_thread_num)):
if test.get('use_isolated_tenants', False):
username = data_utils.rand_name("stress_user")
tenant_name = data_utils.rand_name("stress_tenant")
diff --git a/tempest/tests/fake_identity.py b/tempest/tests/fake_identity.py
index ea2bd44..058c9c2 100644
--- a/tempest/tests/fake_identity.py
+++ b/tempest/tests/fake_identity.py
@@ -25,16 +25,16 @@
COMPUTE_ENDPOINTS_V2 = {
"endpoints": [
{
- "adminURL": "http://fake_url/api/admin",
+ "adminURL": "http://fake_url/v2/first_endpoint/admin",
"region": "NoMatchRegion",
- "internalURL": "http://fake_url/api/internal",
- "publicURL": "http://fake_url/api/public"
+ "internalURL": "http://fake_url/v2/first_endpoint/internal",
+ "publicURL": "http://fake_url/v2/first_endpoint/public"
},
{
- "adminURL": "http://fake_url/api/admin",
+ "adminURL": "http://fake_url/v2/second_endpoint/admin",
"region": "FakeRegion",
- "internalURL": "http://fake_url/api/internal",
- "publicURL": "http://fake_url/api/public"
+ "internalURL": "http://fake_url/v2/second_endpoint/internal",
+ "publicURL": "http://fake_url/v2/second_endpoint/public"
},
],
"type": "compute",
@@ -79,17 +79,24 @@
COMPUTE_ENDPOINTS_V3 = {
"endpoints": [
{
- "id": "fake_service",
+ "id": "first_compute_fake_service",
"interface": "public",
"region": "NoMatchRegion",
- "url": "http://fake_url/v3"
+ "url": "http://fake_url/v3/first_endpoint/api"
},
{
- "id": "another_fake_service",
+ "id": "second_fake_service",
"interface": "public",
"region": "FakeRegion",
- "url": "http://fake_url/v3"
+ "url": "http://fake_url/v3/second_endpoint/api"
+ },
+ {
+ "id": "third_fake_service",
+ "interface": "admin",
+ "region": "MiddleEarthRegion",
+ "url": "http://fake_url/v3/third_endpoint/api"
}
+
],
"type": "compute",
"id": "fake_compute_endpoint"
diff --git a/tempest/tests/test_auth.py b/tempest/tests/test_auth.py
index 5346052..df04d65 100644
--- a/tempest/tests/test_auth.py
+++ b/tempest/tests/test_auth.py
@@ -100,6 +100,7 @@
class TestKeystoneV2AuthProvider(BaseAuthTestsSetUp):
+ _endpoints = fake_identity.IDENTITY_V2_RESPONSE['access']['serviceCatalog']
_auth_provider_class = auth.KeystoneV2AuthProvider
def setUp(self):
@@ -111,41 +112,71 @@
def _get_fake_alt_identity(self):
return fake_identity.ALT_IDENTITY_V2_RESPONSE['access']
- def _get_result_url_from_fake_identity(self):
- return fake_identity.COMPUTE_ENDPOINTS_V2['endpoints'][1]['publicURL']
+ def _get_result_url_from_endpoint(self, ep, endpoint_type='publicURL',
+ replacement=None):
+ if replacement:
+ return ep[endpoint_type].replace('v2', replacement)
+ return ep[endpoint_type]
def _get_token_from_fake_identity(self):
return fake_identity.TOKEN
- def _test_request_helper(self):
+ def _test_request_helper(self, filters, expected):
+ url, headers, body = self.auth_provider.auth_request('GET',
+ self.target_url,
+ filters=filters)
+
+ self.assertEqual(expected['url'], url)
+ self.assertEqual(expected['token'], headers['X-Auth-Token'])
+ self.assertEqual(expected['body'], body)
+
+ def test_request(self):
+ filters = {
+ 'service': 'compute',
+ 'endpoint_type': 'publicURL',
+ 'region': 'FakeRegion'
+ }
+
+ url = self._get_result_url_from_endpoint(
+ self._endpoints[0]['endpoints'][1]) + '/' + self.target_url
+
+ expected = {
+ 'body': None,
+ 'url': url,
+ 'token': self._get_token_from_fake_identity(),
+ }
+ self._test_request_helper(filters, expected)
+
+ def test_request_with_alt_auth_cleans_alt(self):
+ self.auth_provider.set_alt_auth_data(
+ 'body',
+ (fake_identity.ALT_TOKEN, self._get_fake_alt_identity()))
+ self.test_request()
+ # Assert alt auth data is clear after it
+ self.assertIsNone(self.auth_provider.alt_part)
+ self.assertIsNone(self.auth_provider.alt_auth_data)
+
+ def test_request_with_alt_part_without_alt_data(self):
+ """
+ Assert that when alt_part is defined, the corresponding original
+ request element is kept the same.
+ """
filters = {
'service': 'compute',
'endpoint_type': 'publicURL',
'region': 'fakeRegion'
}
+ self.auth_provider.set_alt_auth_data('url', None)
url, headers, body = self.auth_provider.auth_request('GET',
self.target_url,
filters=filters)
- result_url = self._get_result_url_from_fake_identity()
- self.assertEqual(url, result_url + '/' + self.target_url)
+ self.assertEqual(url, self.target_url)
self.assertEqual(self._get_token_from_fake_identity(),
headers['X-Auth-Token'])
self.assertEqual(body, None)
- def test_request(self):
- self._test_request_helper()
-
- def test_request_with_alt_auth(self):
- self.auth_provider.set_alt_auth_data(
- 'body',
- (fake_identity.ALT_TOKEN, self._get_fake_alt_identity()))
- self._test_request_helper()
- # Assert alt auth data is clear after it
- self.assertIsNone(self.auth_provider.alt_part)
- self.assertIsNone(self.auth_provider.alt_auth_data)
-
def test_request_with_bad_service(self):
filters = {
'service': 'BAD_SERVICE',
@@ -154,7 +185,7 @@
}
self.assertRaises(exceptions.EndpointNotFound,
self.auth_provider.auth_request, 'GET',
- 'http://fakeurl.com/fake_api', filters=filters)
+ self.target_url, filters=filters)
def test_request_without_service(self):
filters = {
@@ -164,7 +195,7 @@
}
self.assertRaises(exceptions.EndpointNotFound,
self.auth_provider.auth_request, 'GET',
- 'http://fakeurl.com/fake_api', filters=filters)
+ self.target_url, filters=filters)
def test_check_credentials_missing_attribute(self):
for attr in ['username', 'password']:
@@ -183,8 +214,86 @@
del cred['tenant_name']
self.assertFalse(self.auth_provider.check_credentials(cred))
+ def _test_base_url_helper(self, expected_url, filters,
+ auth_data=None):
+
+ url = self.auth_provider.base_url(filters, auth_data)
+ self.assertEqual(url, expected_url)
+
+ def test_base_url(self):
+ self.filters = {
+ 'service': 'compute',
+ 'endpoint_type': 'publicURL',
+ 'region': 'FakeRegion'
+ }
+ expected = self._get_result_url_from_endpoint(
+ self._endpoints[0]['endpoints'][1])
+ self._test_base_url_helper(expected, self.filters)
+
+ def test_base_url_to_get_admin_endpoint(self):
+ self.filters = {
+ 'service': 'compute',
+ 'endpoint_type': 'adminURL',
+ 'region': 'FakeRegion'
+ }
+ expected = self._get_result_url_from_endpoint(
+ self._endpoints[0]['endpoints'][1], endpoint_type='adminURL')
+ self._test_base_url_helper(expected, self.filters)
+
+ def test_base_url_unknown_region(self):
+ """
+ Assure that if the region is unknow the first endpoint is returned.
+ """
+ self.filters = {
+ 'service': 'compute',
+ 'endpoint_type': 'publicURL',
+ 'region': 'AintNoBodyKnowThisRegion'
+ }
+ expected = self._get_result_url_from_endpoint(
+ self._endpoints[0]['endpoints'][0])
+ self._test_base_url_helper(expected, self.filters)
+
+ def test_base_url_with_non_existent_service(self):
+ self.filters = {
+ 'service': 'BAD_SERVICE',
+ 'endpoint_type': 'publicURL',
+ 'region': 'FakeRegion'
+ }
+ self.assertRaises(exceptions.EndpointNotFound,
+ self._test_base_url_helper, None, self.filters)
+
+ def test_base_url_without_service(self):
+ self.filters = {
+ 'endpoint_type': 'publicURL',
+ 'region': 'FakeRegion'
+ }
+ self.assertRaises(exceptions.EndpointNotFound,
+ self._test_base_url_helper, None, self.filters)
+
+ def test_base_url_with_api_version_filter(self):
+ self.filters = {
+ 'service': 'compute',
+ 'endpoint_type': 'publicURL',
+ 'region': 'FakeRegion',
+ 'api_version': 'v12'
+ }
+ expected = self._get_result_url_from_endpoint(
+ self._endpoints[0]['endpoints'][1], replacement='v12')
+ self._test_base_url_helper(expected, self.filters)
+
+ def test_base_url_with_skip_path_filter(self):
+ self.filters = {
+ 'service': 'compute',
+ 'endpoint_type': 'publicURL',
+ 'region': 'FakeRegion',
+ 'skip_path': True
+ }
+ expected = 'http://fake_url/'
+ self._test_base_url_helper(expected, self.filters)
+
class TestKeystoneV3AuthProvider(TestKeystoneV2AuthProvider):
+ _endpoints = fake_identity.IDENTITY_V3_RESPONSE['token']['catalog']
_auth_provider_class = auth.KeystoneV3AuthProvider
credentials = {
'username': 'fake_user',
@@ -201,10 +310,23 @@
def _get_fake_alt_identity(self):
return fake_identity.ALT_IDENTITY_V3['token']
- def _get_result_url_from_fake_identity(self):
- return fake_identity.COMPUTE_ENDPOINTS_V3['endpoints'][1]['url']
+ def _get_result_url_from_endpoint(self, ep, replacement=None):
+ if replacement:
+ return ep['url'].replace('v3', replacement)
+ return ep['url']
def test_check_credentials_missing_tenant_name(self):
cred = copy.copy(self.credentials)
del cred['domain_name']
self.assertFalse(self.auth_provider.check_credentials(cred))
+
+ # Overwrites v2 test
+ def test_base_url_to_get_admin_endpoint(self):
+ self.filters = {
+ 'service': 'compute',
+ 'endpoint_type': 'admin',
+ 'region': 'MiddleEarthRegion'
+ }
+ expected = self._get_result_url_from_endpoint(
+ self._endpoints[0]['endpoints'][2])
+ self._test_base_url_helper(expected, self.filters)
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index 6a9836b..10d421e 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -17,6 +17,7 @@
import logging as orig_logging
import os
import re
+import six
import urlparse
import boto
@@ -134,7 +135,7 @@
The not leaf elements does wildcard match
"""
# in error_code just literal and '.' characters expected
- if not isinstance(error_data, basestring):
+ if not isinstance(error_data, six.string_types):
(error_code, status_code) = map(str, error_data)
else:
status_code = None
@@ -144,7 +145,7 @@
num_parts = len(parts)
max_index = num_parts - 1
add_cls = error_cls
- for i_part in xrange(num_parts):
+ for i_part in six.moves.xrange(num_parts):
part = parts[i_part]
leaf = i_part == max_index
if not leaf:
diff --git a/tools/check_logs.py b/tools/check_logs.py
index 15988a6..98e079a 100755
--- a/tools/check_logs.py
+++ b/tools/check_logs.py
@@ -32,7 +32,7 @@
def process_files(file_specs, url_specs, whitelists):
- regexp = re.compile(r"^.* (ERROR|CRITICAL) .*\[.*\-.*\]")
+ regexp = re.compile(r"^.* (ERROR|CRITICAL|TRACE) .*\[.*\-.*\]")
had_errors = False
for (name, filename) in file_specs:
whitelist = whitelists.get(name, [])