Merge "Remove interface json and set skip_test method"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 441e17c..b396503 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -750,7 +750,7 @@
# Catalog type of the Neutron service. (string value)
#catalog_type = network
-# List of dns servers whichs hould be used for subnet creation (list
+# List of dns servers which should be used for subnet creation (list
# value)
#dns_servers = 8.8.8.8,8.8.4.4
diff --git a/tempest/api/compute/servers/test_server_personality.py b/tempest/api/compute/servers/test_server_personality.py
index de5b6c1..c6d48bc 100644
--- a/tempest/api/compute/servers/test_server_personality.py
+++ b/tempest/api/compute/servers/test_server_personality.py
@@ -36,6 +36,8 @@
personality = []
max_file_limit = \
self.user_client.get_specific_absolute_limit("maxPersonality")
+ if max_file_limit == -1:
+ raise self.skipException("No limit for personality files")
for i in range(0, int(max_file_limit) + 1):
path = 'etc/test' + str(i) + '.txt'
personality.append({'path': path,
@@ -52,6 +54,8 @@
file_contents = 'This is a test file.'
max_file_limit = \
self.user_client.get_specific_absolute_limit("maxPersonality")
+ if max_file_limit == -1:
+ raise self.skipException("No limit for personality files")
person = []
for i in range(0, int(max_file_limit)):
path = 'etc/test' + str(i) + '.txt'
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index 5e786a0..6ce1216 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -373,7 +373,6 @@
for ra_mode, add_mode in (
('dhcpv6-stateful', 'dhcpv6-stateful'),
('dhcpv6-stateful', None),
- (None, 'dhcpv6-stateful'),
):
kwargs = {'ipv6_ra_mode': ra_mode,
'ipv6_address_mode': add_mode}
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index f36ef56..28f0aa8 100755
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -19,18 +19,18 @@
Runtime Arguments
-----------------
---init-saved-state: Before you can execute cleanup you must initialize
-the saved state by running it with the --init-saved-state flag
+**--init-saved-state**: Before you can execute cleanup you must initialize
+the saved state by running it with the **--init-saved-state** flag
(creating ./saved_state.json), which protects your deployment from
cleanup deleting objects you want to keep. Typically you would run
-cleanup with --init-saved-state prior to a tempest run. If this is not
+cleanup with **--init-saved-state** prior to a tempest run. If this is not
the case saved_state.json must be edited, removing objects you want
cleanup to delete.
---dry-run: Creates a report (dry_run.json) of the tenants that will be
+**--dry-run**: Creates a report (dry_run.json) of the tenants that will be
cleaned up (in the "_tenants_to_clean" array), and the global objects
that will be removed (tenants, users, flavors and images). Once
-cleanup is executed in normal mode, running it again with --dry-run
+cleanup is executed in normal mode, running it again with **--dry-run**
should yield an empty report.
**NOTE**: The _tenants_to_clean array in dry-run.json lists the
@@ -38,17 +38,17 @@
delete the tenant itself. This may differ from the tenants array as you
can clean the tempest and alternate tempest tenants but by default,
cleanup deletes the objects in the tempest and alternate tempest tenants
-but does not delete those tenants unless the --delete-tempest-conf-objects
+but does not delete those tenants unless the **--delete-tempest-conf-objects**
flag is used to force their deletion.
**Normal mode**: running with no arguments, will query your deployment and
build a list of objects to delete after filtering out the objects found in
-saved_state.json and based on the --delete-tempest-conf-objects flag.
+saved_state.json and based on the **--delete-tempest-conf-objects** flag.
By default the tempest and alternate tempest users and tenants are not
deleted and the admin user specified in tempest.conf is never deleted.
-Please run with --help to see full list of options.
+Please run with **--help** to see full list of options.
"""
import argparse
import json
diff --git a/tempest/common/custom_matchers.py b/tempest/common/custom_matchers.py
index 39e3a67..298a94e 100644
--- a/tempest/common/custom_matchers.py
+++ b/tempest/common/custom_matchers.py
@@ -122,33 +122,21 @@
def match(self, actual):
for key, value in actual.iteritems():
- if key == 'content-length' and not value.isdigit():
+ if key in ('content-length', 'x-account-bytes-used',
+ 'x-account-container-count', 'x-account-object-count',
+ 'x-container-bytes-used', 'x-container-object-count')\
+ and not value.isdigit():
+ return InvalidFormat(key, value)
+ elif key in ('content-type', 'date', 'last-modified',
+ 'x-copied-from-last-modified') and not value:
return InvalidFormat(key, value)
elif key == 'x-timestamp' and not re.match("^\d+\.?\d*\Z", value):
return InvalidFormat(key, value)
- elif key == 'x-account-bytes-used' and not value.isdigit():
- return InvalidFormat(key, value)
- elif key == 'x-account-container-count' and not value.isdigit():
- return InvalidFormat(key, value)
- elif key == 'x-account-object-count' and not value.isdigit():
- return InvalidFormat(key, value)
- elif key == 'x-container-bytes-used' and not value.isdigit():
- return InvalidFormat(key, value)
- elif key == 'x-container-object-count' and not value.isdigit():
- return InvalidFormat(key, value)
- elif key == 'content-type' and not value:
- return InvalidFormat(key, value)
elif key == 'x-copied-from' and not re.match("\S+/\S+", value):
return InvalidFormat(key, value)
- elif key == 'x-copied-from-last-modified' and not value:
- return InvalidFormat(key, value)
elif key == 'x-trans-id' and \
not re.match("^tx[0-9a-f]{21}-[0-9a-f]{10}.*", value):
return InvalidFormat(key, value)
- elif key == 'date' and not value:
- return InvalidFormat(key, value)
- elif key == 'last-modified' and not value:
- return InvalidFormat(key, value)
elif key == 'accept-ranges' and not value == 'bytes':
return InvalidFormat(key, value)
elif key == 'etag' and not value.isalnum():
diff --git a/tempest/config.py b/tempest/config.py
index dbe9bc2..bbfe70b 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -469,7 +469,7 @@
"checks."),
cfg.ListOpt('dns_servers',
default=["8.8.8.8", "8.8.4.4"],
- help="List of dns servers whichs hould be used"
+ help="List of dns servers which should be used"
" for subnet creation")
]
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 61a7d2e..20b95e4 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -556,7 +556,7 @@
if not client:
client = self.network_client
if not tenant_id:
- tenant_id = client.rest_client.tenant_id
+ tenant_id = client.tenant_id
name = data_utils.rand_name(namestart)
result = client.create_network(name=name, tenant_id=tenant_id)
network = net_resources.DeletableNetwork(client=client,
@@ -791,7 +791,7 @@
if client is None:
client = self.network_client
if tenant_id is None:
- tenant_id = client.rest_client.tenant_id
+ tenant_id = client.tenant_id
secgroup = self._create_empty_security_group(namestart=namestart,
client=client,
tenant_id=tenant_id)
@@ -817,7 +817,7 @@
if client is None:
client = self.network_client
if not tenant_id:
- tenant_id = client.rest_client.tenant_id
+ tenant_id = client.tenant_id
sg_name = data_utils.rand_name(namestart)
sg_desc = sg_name + " description"
sg_dict = dict(name=sg_name,
@@ -842,7 +842,7 @@
if client is None:
client = self.network_client
if not tenant_id:
- tenant_id = client.rest_client.tenant_id
+ tenant_id = client.tenant_id
sgs = [
sg for sg in client.list_security_groups().values()[0]
if sg['tenant_id'] == tenant_id and sg['name'] == 'default'
@@ -874,7 +874,7 @@
if client is None:
client = self.network_client
if not tenant_id:
- tenant_id = client.rest_client.tenant_id
+ tenant_id = client.tenant_id
if secgroup is None:
secgroup = self._default_security_group(client=client,
tenant_id=tenant_id)
@@ -986,7 +986,7 @@
if not client:
client = self.network_client
if not tenant_id:
- tenant_id = client.rest_client.tenant_id
+ tenant_id = client.tenant_id
router_id = CONF.network.public_router_id
network_id = CONF.network.public_network_id
if router_id:
@@ -1005,7 +1005,7 @@
if not client:
client = self.network_client
if not tenant_id:
- tenant_id = client.rest_client.tenant_id
+ tenant_id = client.tenant_id
name = data_utils.rand_name(namestart)
result = client.create_router(name=name,
admin_state_up=True,
diff --git a/tempest/services/compute/json/agents_client.py b/tempest/services/compute/json/agents_client.py
index 5b76a56..eacd367 100644
--- a/tempest/services/compute/json/agents_client.py
+++ b/tempest/services/compute/json/agents_client.py
@@ -17,21 +17,14 @@
from tempest.api_schema.response.compute import agents as common_schema
from tempest.api_schema.response.compute.v2 import agents as schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class AgentsClientJSON(rest_client.RestClient):
+class AgentsClientJSON(base.ComputeClient):
"""
Tests Agents API
"""
- def __init__(self, auth_provider):
- super(AgentsClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
-
def list_agents(self, params=None):
"""List all agent builds."""
url = 'os-agents'
diff --git a/tempest/services/compute/json/aggregates_client.py b/tempest/services/compute/json/aggregates_client.py
index 09927d3..1539259 100644
--- a/tempest/services/compute/json/aggregates_client.py
+++ b/tempest/services/compute/json/aggregates_client.py
@@ -17,18 +17,11 @@
from tempest.api_schema.response.compute import aggregates as schema
from tempest.api_schema.response.compute.v2 import aggregates as v2_schema
-from tempest.common import rest_client
-from tempest import config
from tempest import exceptions
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class AggregatesClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(AggregatesClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class AggregatesClientJSON(base.ComputeClient):
def list_aggregates(self):
"""Get aggregate list."""
diff --git a/tempest/services/compute/json/availability_zone_client.py b/tempest/services/compute/json/availability_zone_client.py
index 00f8330..b8bda68 100644
--- a/tempest/services/compute/json/availability_zone_client.py
+++ b/tempest/services/compute/json/availability_zone_client.py
@@ -16,18 +16,10 @@
import json
from tempest.api_schema.response.compute.v2 import availability_zone as schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class AvailabilityZoneClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(AvailabilityZoneClientJSON, self).__init__(
- auth_provider)
- self.service = CONF.compute.catalog_type
+class AvailabilityZoneClientJSON(base.ComputeClient):
def get_availability_zone_list(self):
resp, body = self.get('os-availability-zone')
diff --git a/tempest/services/compute/json/base.py b/tempest/services/compute/json/base.py
new file mode 100644
index 0000000..b712452
--- /dev/null
+++ b/tempest/services/compute/json/base.py
@@ -0,0 +1,36 @@
+# 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.common import rest_client
+from tempest import config
+
+CONF = config.CONF
+
+
+class ComputeClient(rest_client.RestClient):
+ """
+ Base compute client class
+ """
+
+ def __init__(self, auth_provider,
+ build_interval=None, build_timeout=None):
+ if build_interval is None:
+ build_interval = CONF.compute.build_interval
+ if build_timeout is None:
+ build_timeout = CONF.compute.build_timeout
+
+ super(ComputeClient, self).__init__(auth_provider)
+ self.service = CONF.compute.catalog_type
+ self.build_interval = build_interval
+ self.build_timeout = build_timeout
diff --git a/tempest/services/compute/json/certificates_client.py b/tempest/services/compute/json/certificates_client.py
index 356ded2..123f0b9 100644
--- a/tempest/services/compute/json/certificates_client.py
+++ b/tempest/services/compute/json/certificates_client.py
@@ -17,17 +17,10 @@
from tempest.api_schema.response.compute import certificates as schema
from tempest.api_schema.response.compute.v2 import certificates as v2schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class CertificatesClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(CertificatesClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class CertificatesClientJSON(base.ComputeClient):
def get_certificate(self, id):
url = "os-certificates/%s" % (id)
diff --git a/tempest/services/compute/json/extensions_client.py b/tempest/services/compute/json/extensions_client.py
index 41d1c4e..69ad7c0 100644
--- a/tempest/services/compute/json/extensions_client.py
+++ b/tempest/services/compute/json/extensions_client.py
@@ -16,17 +16,10 @@
import json
from tempest.api_schema.response.compute.v2 import extensions as schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class ExtensionsClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(ExtensionsClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class ExtensionsClientJSON(base.ComputeClient):
def list_extensions(self):
url = 'extensions'
diff --git a/tempest/services/compute/json/fixed_ips_client.py b/tempest/services/compute/json/fixed_ips_client.py
index 5903334..8fd24b6 100644
--- a/tempest/services/compute/json/fixed_ips_client.py
+++ b/tempest/services/compute/json/fixed_ips_client.py
@@ -16,17 +16,10 @@
import json
from tempest.api_schema.response.compute.v2 import fixed_ips as schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class FixedIPsClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(FixedIPsClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class FixedIPsClientJSON(base.ComputeClient):
def get_fixed_ip_details(self, fixed_ip):
url = "os-fixed-ips/%s" % (fixed_ip)
diff --git a/tempest/services/compute/json/flavors_client.py b/tempest/services/compute/json/flavors_client.py
index 8faf8a7..6276d3c 100644
--- a/tempest/services/compute/json/flavors_client.py
+++ b/tempest/services/compute/json/flavors_client.py
@@ -21,17 +21,10 @@
from tempest.api_schema.response.compute import flavors_extra_specs \
as schema_extra_specs
from tempest.api_schema.response.compute.v2 import flavors as v2schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class FlavorsClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(FlavorsClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class FlavorsClientJSON(base.ComputeClient):
def list_flavors(self, params=None):
url = 'flavors'
diff --git a/tempest/services/compute/json/floating_ips_client.py b/tempest/services/compute/json/floating_ips_client.py
index 0ed1720..788b4d2 100644
--- a/tempest/services/compute/json/floating_ips_client.py
+++ b/tempest/services/compute/json/floating_ips_client.py
@@ -17,17 +17,11 @@
import urllib
from tempest.api_schema.response.compute.v2 import floating_ips as schema
-from tempest.common import rest_client
-from tempest import config
from tempest import exceptions
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class FloatingIPsClientJSON(rest_client.RestClient):
- def __init__(self, auth_provider):
- super(FloatingIPsClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class FloatingIPsClientJSON(base.ComputeClient):
def list_floating_ips(self, params=None):
"""Returns a list of all floating IPs filtered by any parameters."""
diff --git a/tempest/services/compute/json/hosts_client.py b/tempest/services/compute/json/hosts_client.py
index 8644173..5d306f9 100644
--- a/tempest/services/compute/json/hosts_client.py
+++ b/tempest/services/compute/json/hosts_client.py
@@ -17,17 +17,10 @@
from tempest.api_schema.response.compute import hosts as schema
from tempest.api_schema.response.compute.v2 import hosts as v2_schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class HostsClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(HostsClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class HostsClientJSON(base.ComputeClient):
def list_hosts(self, params=None):
"""Lists all hosts."""
diff --git a/tempest/services/compute/json/hypervisor_client.py b/tempest/services/compute/json/hypervisor_client.py
index 8eacf61..52b50c8 100644
--- a/tempest/services/compute/json/hypervisor_client.py
+++ b/tempest/services/compute/json/hypervisor_client.py
@@ -17,17 +17,10 @@
from tempest.api_schema.response.compute import hypervisors as common_schema
from tempest.api_schema.response.compute.v2 import hypervisors as v2schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class HypervisorClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(HypervisorClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class HypervisorClientJSON(base.ComputeClient):
def get_hypervisor_list(self):
"""List hypervisors information."""
diff --git a/tempest/services/compute/json/images_client.py b/tempest/services/compute/json/images_client.py
index 079a91e..a4cfe57 100644
--- a/tempest/services/compute/json/images_client.py
+++ b/tempest/services/compute/json/images_client.py
@@ -17,21 +17,12 @@
import urllib
from tempest.api_schema.response.compute.v2 import images as schema
-from tempest.common import rest_client
from tempest.common import waiters
-from tempest import config
from tempest import exceptions
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class ImagesClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(ImagesClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
- self.build_interval = CONF.compute.build_interval
- self.build_timeout = CONF.compute.build_timeout
+class ImagesClientJSON(base.ComputeClient):
def create_image(self, server_id, name, meta=None):
"""Creates an image of the original server."""
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 4b0362b..f79c3de 100644
--- a/tempest/services/compute/json/instance_usage_audit_log_client.py
+++ b/tempest/services/compute/json/instance_usage_audit_log_client.py
@@ -17,18 +17,10 @@
from tempest.api_schema.response.compute.v2 import instance_usage_audit_logs \
as schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class InstanceUsagesAuditLogClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(InstanceUsagesAuditLogClientJSON, self).__init__(
- auth_provider)
- self.service = CONF.compute.catalog_type
+class InstanceUsagesAuditLogClientJSON(base.ComputeClient):
def list_instance_usage_audit_logs(self):
url = 'os-instance_usage_audit_log'
diff --git a/tempest/services/compute/json/interfaces_client.py b/tempest/services/compute/json/interfaces_client.py
index 620ed68..f1e2660 100644
--- a/tempest/services/compute/json/interfaces_client.py
+++ b/tempest/services/compute/json/interfaces_client.py
@@ -19,18 +19,11 @@
from tempest.api_schema.response.compute import interfaces as common_schema
from tempest.api_schema.response.compute import servers as servers_schema
from tempest.api_schema.response.compute.v2 import interfaces as schema
-from tempest.common import rest_client
-from tempest import config
from tempest import exceptions
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class InterfacesClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(InterfacesClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class InterfacesClientJSON(base.ComputeClient):
def list_interfaces(self, server):
resp, body = self.get('servers/%s/os-interface' % server)
diff --git a/tempest/services/compute/json/keypairs_client.py b/tempest/services/compute/json/keypairs_client.py
index 31c42a5..c4406f5 100644
--- a/tempest/services/compute/json/keypairs_client.py
+++ b/tempest/services/compute/json/keypairs_client.py
@@ -17,17 +17,10 @@
from tempest.api_schema.response.compute import keypairs as common_schema
from tempest.api_schema.response.compute.v2 import keypairs as schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class KeyPairsClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(KeyPairsClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class KeyPairsClientJSON(base.ComputeClient):
def list_keypairs(self):
resp, body = self.get("os-keypairs")
diff --git a/tempest/services/compute/json/limits_client.py b/tempest/services/compute/json/limits_client.py
index 81c602b..66a0649 100644
--- a/tempest/services/compute/json/limits_client.py
+++ b/tempest/services/compute/json/limits_client.py
@@ -16,17 +16,10 @@
import json
from tempest.api_schema.response.compute.v2 import limits as schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class LimitsClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(LimitsClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class LimitsClientJSON(base.ComputeClient):
def get_absolute_limits(self):
resp, body = self.get("limits")
diff --git a/tempest/services/compute/json/migrations_client.py b/tempest/services/compute/json/migrations_client.py
index f4abbb2..de183f1 100644
--- a/tempest/services/compute/json/migrations_client.py
+++ b/tempest/services/compute/json/migrations_client.py
@@ -16,17 +16,10 @@
import urllib
from tempest.api_schema.response.compute import migrations as schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class MigrationsClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(MigrationsClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class MigrationsClientJSON(base.ComputeClient):
def list_migrations(self, params=None):
"""Lists all migrations."""
diff --git a/tempest/services/compute/json/networks_client.py b/tempest/services/compute/json/networks_client.py
index 40eb1a6..5a2744d 100644
--- a/tempest/services/compute/json/networks_client.py
+++ b/tempest/services/compute/json/networks_client.py
@@ -15,17 +15,10 @@
import json
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class NetworksClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(NetworksClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class NetworksClientJSON(base.ComputeClient):
def list_networks(self):
resp, body = self.get("os-networks")
diff --git a/tempest/services/compute/json/quotas_client.py b/tempest/services/compute/json/quotas_client.py
index b691529..0fee57a 100644
--- a/tempest/services/compute/json/quotas_client.py
+++ b/tempest/services/compute/json/quotas_client.py
@@ -18,17 +18,10 @@
from tempest.api_schema.response.compute.v2\
import quota_classes as classes_schema
from tempest.api_schema.response.compute.v2 import quotas as schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class QuotasClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(QuotasClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class QuotasClientJSON(base.ComputeClient):
def get_quota_set(self, tenant_id, user_id=None):
"""List the quota set for a tenant."""
@@ -122,11 +115,7 @@
return resp, body
-class QuotaClassesClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(QuotaClassesClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class QuotaClassesClientJSON(base.ComputeClient):
def get_quota_class_set(self, quota_class_id):
"""List the quota class set for a quota class."""
diff --git a/tempest/services/compute/json/security_group_default_rules_client.py b/tempest/services/compute/json/security_group_default_rules_client.py
index 7743f9c..efaf329 100644
--- a/tempest/services/compute/json/security_group_default_rules_client.py
+++ b/tempest/services/compute/json/security_group_default_rules_client.py
@@ -17,18 +17,10 @@
from tempest.api_schema.response.compute.v2 import \
security_group_default_rule as schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class SecurityGroupDefaultRulesClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(SecurityGroupDefaultRulesClientJSON,
- self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class SecurityGroupDefaultRulesClientJSON(base.ComputeClient):
def create_security_default_group_rule(self, ip_protocol, from_port,
to_port, **kwargs):
diff --git a/tempest/services/compute/json/security_groups_client.py b/tempest/services/compute/json/security_groups_client.py
index 733a50b..a301a0f 100644
--- a/tempest/services/compute/json/security_groups_client.py
+++ b/tempest/services/compute/json/security_groups_client.py
@@ -17,18 +17,11 @@
import urllib
from tempest.api_schema.response.compute.v2 import security_groups as schema
-from tempest.common import rest_client
-from tempest import config
from tempest import exceptions
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class SecurityGroupsClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(SecurityGroupsClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class SecurityGroupsClientJSON(base.ComputeClient):
def list_security_groups(self, params=None):
"""List all security groups for a user."""
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 4268b1a..400f9a7 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -20,20 +20,15 @@
from tempest.api_schema.response.compute import servers as common_schema
from tempest.api_schema.response.compute.v2 import servers as schema
-from tempest.common import rest_client
from tempest.common import waiters
from tempest import config
from tempest import exceptions
+from tempest.services.compute.json import base
CONF = config.CONF
-class ServersClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(ServersClientJSON, self).__init__(auth_provider)
-
- self.service = CONF.compute.catalog_type
+class ServersClientJSON(base.ComputeClient):
def create_server(self, name, image_ref, flavor_ref, **kwargs):
"""
diff --git a/tempest/services/compute/json/services_client.py b/tempest/services/compute/json/services_client.py
index e56263c..8d73c37 100644
--- a/tempest/services/compute/json/services_client.py
+++ b/tempest/services/compute/json/services_client.py
@@ -18,17 +18,10 @@
import urllib
from tempest.api_schema.response.compute import services as schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class ServicesClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(ServicesClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class ServicesClientJSON(base.ComputeClient):
def list_services(self, params=None):
url = 'os-services'
diff --git a/tempest/services/compute/json/tenant_usages_client.py b/tempest/services/compute/json/tenant_usages_client.py
index a0b9b4a..eac23bb 100644
--- a/tempest/services/compute/json/tenant_usages_client.py
+++ b/tempest/services/compute/json/tenant_usages_client.py
@@ -17,17 +17,10 @@
import urllib
from tempest.api_schema.response.compute.v2 import tenant_usages as schema
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.compute.json import base
-class TenantUsagesClientJSON(rest_client.RestClient):
-
- def __init__(self, auth_provider):
- super(TenantUsagesClientJSON, self).__init__(auth_provider)
- self.service = CONF.compute.catalog_type
+class TenantUsagesClientJSON(base.ComputeClient):
def list_tenant_usages(self, params=None):
url = 'os-simple-tenant-usage'
diff --git a/tempest/services/compute/json/volumes_extensions_client.py b/tempest/services/compute/json/volumes_extensions_client.py
index afa6937..69b9bea 100644
--- a/tempest/services/compute/json/volumes_extensions_client.py
+++ b/tempest/services/compute/json/volumes_extensions_client.py
@@ -18,21 +18,20 @@
import urllib
from tempest.api_schema.response.compute.v2 import volumes as schema
-from tempest.common import rest_client
from tempest import config
from tempest import exceptions
+from tempest.services.compute.json import base
CONF = config.CONF
-class VolumesExtensionsClientJSON(rest_client.RestClient):
+class VolumesExtensionsClientJSON(base.ComputeClient):
def __init__(self, auth_provider):
super(VolumesExtensionsClientJSON, self).__init__(
- auth_provider)
- self.service = CONF.compute.catalog_type
- self.build_interval = CONF.volume.build_interval
- self.build_timeout = CONF.volume.build_timeout
+ auth_provider,
+ build_interval=CONF.volume.build_interval,
+ build_timeout=CONF.volume.build_timeout)
def list_volumes(self, params=None):
"""List all the volumes created."""
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 0a9a1fa..c622ee4 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -11,12 +11,18 @@
# under the License.
import json
+import time
+import urllib
from tempest.common import rest_client
-from tempest.services.network import network_client_base
+from tempest.common.utils import misc
+from tempest import config
+from tempest import exceptions
+
+CONF = config.CONF
-class NetworkClientJSON(network_client_base.NetworkClientBase):
+class NetworkClientJSON(rest_client.RestClient):
"""
Tempest REST client for Neutron. Uses v2 of the Neutron API, since the
@@ -31,8 +37,228 @@
quotas
"""
- def get_rest_client(self, auth_provider):
- return rest_client.RestClient(auth_provider)
+ def __init__(self, auth_provider):
+ super(NetworkClientJSON, self).__init__(auth_provider)
+ self.service = CONF.network.catalog_type
+ self.build_timeout = CONF.network.build_timeout
+ self.build_interval = CONF.network.build_interval
+ self.version = '2.0'
+ self.uri_prefix = "v%s" % (self.version)
+
+ def get_uri(self, plural_name):
+ # get service prefix from resource name
+
+ # The following list represents resource names that do not require
+ # changing underscore to a hyphen
+ hyphen_exceptions = ["health_monitors", "firewall_rules",
+ "firewall_policies"]
+ # the following map is used to construct proper URI
+ # for the given neutron resource
+ service_resource_prefix_map = {
+ 'networks': '',
+ 'subnets': '',
+ 'ports': '',
+ 'pools': 'lb',
+ 'vips': 'lb',
+ 'health_monitors': 'lb',
+ 'members': 'lb',
+ 'ipsecpolicies': 'vpn',
+ 'vpnservices': 'vpn',
+ 'ikepolicies': 'vpn',
+ 'ipsecpolicies': 'vpn',
+ 'metering_labels': 'metering',
+ 'metering_label_rules': 'metering',
+ 'firewall_rules': 'fw',
+ 'firewall_policies': 'fw',
+ 'firewalls': 'fw'
+ }
+ service_prefix = service_resource_prefix_map.get(
+ plural_name)
+ if plural_name not in hyphen_exceptions:
+ plural_name = plural_name.replace("_", "-")
+ if service_prefix:
+ uri = '%s/%s/%s' % (self.uri_prefix, service_prefix,
+ plural_name)
+ else:
+ uri = '%s/%s' % (self.uri_prefix, plural_name)
+ return uri
+
+ def pluralize(self, resource_name):
+ # get plural from map or just add 's'
+
+ # map from resource name to a plural name
+ # needed only for those which can't be constructed as name + 's'
+ resource_plural_map = {
+ 'security_groups': 'security_groups',
+ 'security_group_rules': 'security_group_rules',
+ 'ipsecpolicy': 'ipsecpolicies',
+ 'ikepolicy': 'ikepolicies',
+ 'ipsecpolicy': 'ipsecpolicies',
+ 'quotas': 'quotas',
+ 'firewall_policy': 'firewall_policies'
+ }
+ return resource_plural_map.get(resource_name, resource_name + 's')
+
+ def _lister(self, plural_name):
+ def _list(**filters):
+ uri = self.get_uri(plural_name)
+ if filters:
+ uri += '?' + urllib.urlencode(filters, doseq=1)
+ resp, body = self.get(uri)
+ result = {plural_name: self.deserialize_list(body)}
+ self.expected_success(200, resp.status)
+ return rest_client.ResponseBody(resp, result)
+
+ return _list
+
+ def _deleter(self, resource_name):
+ def _delete(resource_id):
+ plural = self.pluralize(resource_name)
+ uri = '%s/%s' % (self.get_uri(plural), resource_id)
+ resp, body = self.delete(uri)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ return _delete
+
+ def _shower(self, resource_name):
+ def _show(resource_id, **fields):
+ # fields is a dict which key is 'fields' and value is a
+ # list of field's name. An example:
+ # {'fields': ['id', 'name']}
+ plural = self.pluralize(resource_name)
+ uri = '%s/%s' % (self.get_uri(plural), resource_id)
+ if fields:
+ uri += '?' + urllib.urlencode(fields, doseq=1)
+ resp, body = self.get(uri)
+ body = self.deserialize_single(body)
+ self.expected_success(200, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ return _show
+
+ def _creater(self, resource_name):
+ def _create(**kwargs):
+ plural = self.pluralize(resource_name)
+ uri = self.get_uri(plural)
+ post_data = self.serialize({resource_name: kwargs})
+ resp, body = self.post(uri, post_data)
+ body = self.deserialize_single(body)
+ self.expected_success(201, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ return _create
+
+ def _updater(self, resource_name):
+ def _update(res_id, **kwargs):
+ plural = self.pluralize(resource_name)
+ uri = '%s/%s' % (self.get_uri(plural), res_id)
+ post_data = self.serialize({resource_name: kwargs})
+ resp, body = self.put(uri, post_data)
+ body = self.deserialize_single(body)
+ self.expected_success(200, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ return _update
+
+ def __getattr__(self, name):
+ method_prefixes = ["list_", "delete_", "show_", "create_", "update_"]
+ method_functors = [self._lister,
+ self._deleter,
+ self._shower,
+ self._creater,
+ self._updater]
+ for index, prefix in enumerate(method_prefixes):
+ prefix_len = len(prefix)
+ if name[:prefix_len] == prefix:
+ return method_functors[index](name[prefix_len:])
+ raise AttributeError(name)
+
+ # Common methods that are hard to automate
+ def create_bulk_network(self, names):
+ network_list = [{'name': name} for name in names]
+ post_data = {'networks': network_list}
+ body = self.serialize_list(post_data, "networks", "network")
+ uri = self.get_uri("networks")
+ resp, body = self.post(uri, body)
+ body = {'networks': self.deserialize_list(body)}
+ self.expected_success(201, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def create_bulk_subnet(self, subnet_list):
+ post_data = {'subnets': subnet_list}
+ body = self.serialize_list(post_data, 'subnets', 'subnet')
+ uri = self.get_uri('subnets')
+ resp, body = self.post(uri, body)
+ body = {'subnets': self.deserialize_list(body)}
+ self.expected_success(201, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def create_bulk_port(self, port_list):
+ post_data = {'ports': port_list}
+ body = self.serialize_list(post_data, 'ports', 'port')
+ uri = self.get_uri('ports')
+ resp, body = self.post(uri, body)
+ body = {'ports': self.deserialize_list(body)}
+ self.expected_success(201, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def wait_for_resource_deletion(self, resource_type, id):
+ """Waits for a resource to be deleted."""
+ start_time = int(time.time())
+ while True:
+ if self.is_resource_deleted(resource_type, id):
+ return
+ if int(time.time()) - start_time >= self.build_timeout:
+ raise exceptions.TimeoutException
+ time.sleep(self.build_interval)
+
+ def is_resource_deleted(self, resource_type, id):
+ method = 'show_' + resource_type
+ try:
+ getattr(self, method)(id)
+ except AttributeError:
+ raise Exception("Unknown resource type %s " % resource_type)
+ except exceptions.NotFound:
+ return True
+ return False
+
+ def wait_for_resource_status(self, fetch, status, interval=None,
+ timeout=None):
+ """
+ @summary: Waits for a network resource to reach a status
+ @param fetch: the callable to be used to query the resource status
+ @type fecth: callable that takes no parameters and returns the resource
+ @param status: the status that the resource has to reach
+ @type status: String
+ @param interval: the number of seconds to wait between each status
+ query
+ @type interval: Integer
+ @param timeout: the maximum number of seconds to wait for the resource
+ to reach the desired status
+ @type timeout: Integer
+ """
+ if not interval:
+ interval = self.build_interval
+ if not timeout:
+ timeout = self.build_timeout
+ start_time = time.time()
+
+ while time.time() - start_time <= timeout:
+ resource = fetch()
+ if resource['status'] == status:
+ return
+ time.sleep(interval)
+
+ # At this point, the wait has timed out
+ message = 'Resource %s' % (str(resource))
+ message += ' failed to reach status %s' % status
+ message += ' (current: %s)' % resource['status']
+ message += ' within the required time %s' % timeout
+ caller = misc.find_test_caller()
+ if caller:
+ message = '(%s) %s' % (caller, message)
+ raise exceptions.TimeoutException(message)
def deserialize_single(self, body):
return json.loads(body)
@@ -59,14 +285,14 @@
body = json.dumps(put_body)
uri = '%s/quotas/%s' % (self.uri_prefix, tenant_id)
resp, body = self.put(uri, body)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body['quota'])
def reset_quotas(self, tenant_id):
uri = '%s/quotas/%s' % (self.uri_prefix, tenant_id)
resp, body = self.delete(uri)
- self.rest_client.expected_success(204, resp.status)
+ self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp, body)
def create_router(self, name, admin_state_up=True, **kwargs):
@@ -76,14 +302,14 @@
body = json.dumps(post_body)
uri = '%s/routers' % (self.uri_prefix)
resp, body = self.post(uri, body)
- self.rest_client.expected_success(201, resp.status)
+ self.expected_success(201, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def _update_router(self, router_id, set_enable_snat, **kwargs):
uri = '%s/routers/%s' % (self.uri_prefix, router_id)
resp, body = self.get(uri)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
update_body = {}
update_body['name'] = kwargs.get('name', body['router']['name'])
@@ -103,7 +329,7 @@
update_body = dict(router=update_body)
update_body = json.dumps(update_body)
resp, body = self.put(uri, update_body)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -130,7 +356,7 @@
update_body = {"subnet_id": subnet_id}
update_body = json.dumps(update_body)
resp, body = self.put(uri, update_body)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -140,7 +366,7 @@
update_body = {"port_id": port_id}
update_body = json.dumps(update_body)
resp, body = self.put(uri, update_body)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -150,7 +376,7 @@
update_body = {"subnet_id": subnet_id}
update_body = json.dumps(update_body)
resp, body = self.put(uri, update_body)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -160,7 +386,7 @@
update_body = {"port_id": port_id}
update_body = json.dumps(update_body)
resp, body = self.put(uri, update_body)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -175,7 +401,7 @@
uri = '%s/lb/pools/%s/health_monitors' % (self.uri_prefix,
pool_id)
resp, body = self.post(uri, body)
- self.rest_client.expected_success(201, resp.status)
+ self.expected_success(201, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -184,13 +410,13 @@
uri = '%s/lb/pools/%s/health_monitors/%s' % (self.uri_prefix, pool_id,
health_monitor_id)
resp, body = self.delete(uri)
- self.rest_client.expected_success(204, resp.status)
+ self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp, body)
def list_router_interfaces(self, uuid):
uri = '%s/ports?device_id=%s' % (self.uri_prefix, uuid)
resp, body = self.get(uri)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -203,14 +429,14 @@
agent = {"agent": agent_info}
body = json.dumps(agent)
resp, body = self.put(uri, body)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def list_pools_hosted_by_one_lbaas_agent(self, agent_id):
uri = '%s/agents/%s/loadbalancer-pools' % (self.uri_prefix, agent_id)
resp, body = self.get(uri)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -218,21 +444,21 @@
uri = ('%s/lb/pools/%s/loadbalancer-agent' %
(self.uri_prefix, pool_id))
resp, body = self.get(uri)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def list_routers_on_l3_agent(self, agent_id):
uri = '%s/agents/%s/l3-routers' % (self.uri_prefix, agent_id)
resp, body = self.get(uri)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def list_l3_agents_hosting_router(self, router_id):
uri = '%s/routers/%s/l3-agents' % (self.uri_prefix, router_id)
resp, body = self.get(uri)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -241,7 +467,7 @@
post_body = {"router_id": router_id}
body = json.dumps(post_body)
resp, body = self.post(uri, body)
- self.rest_client.expected_success(201, resp.status)
+ self.expected_success(201, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -249,20 +475,20 @@
uri = '%s/agents/%s/l3-routers/%s' % (
self.uri_prefix, agent_id, router_id)
resp, body = self.delete(uri)
- self.rest_client.expected_success(204, resp.status)
+ self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp, body)
def list_dhcp_agent_hosting_network(self, network_id):
uri = '%s/networks/%s/dhcp-agents' % (self.uri_prefix, network_id)
resp, body = self.get(uri)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def list_networks_hosted_by_one_dhcp_agent(self, agent_id):
uri = '%s/agents/%s/dhcp-networks' % (self.uri_prefix, agent_id)
resp, body = self.get(uri)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -270,7 +496,7 @@
uri = '%s/agents/%s/dhcp-networks/%s' % (self.uri_prefix, agent_id,
network_id)
resp, body = self.delete(uri)
- self.rest_client.expected_success(204, resp.status)
+ self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp, body)
def create_ikepolicy(self, name, **kwargs):
@@ -284,7 +510,7 @@
body = json.dumps(post_body)
uri = '%s/vpn/ikepolicies' % (self.uri_prefix)
resp, body = self.post(uri, body)
- self.rest_client.expected_success(201, resp.status)
+ self.expected_success(201, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -298,7 +524,7 @@
}
body = json.dumps(put_body)
resp, body = self.put(uri, body)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -312,14 +538,14 @@
}
body = json.dumps(put_body)
resp, body = self.put(uri, body)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def list_lb_pool_stats(self, pool_id):
uri = '%s/lb/pools/%s/stats' % (self.uri_prefix, pool_id)
resp, body = self.get(uri)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -328,7 +554,7 @@
body = json.dumps(post_body)
uri = '%s/agents/%s/dhcp-networks' % (self.uri_prefix, agent_id)
resp, body = self.post(uri, body)
- self.rest_client.expected_success(201, resp.status)
+ self.expected_success(201, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -344,7 +570,7 @@
}
body = json.dumps(body)
resp, body = self.put(uri, body)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
@@ -355,6 +581,6 @@
update_body = {"firewall_rule_id": firewall_rule_id}
update_body = json.dumps(update_body)
resp, body = self.put(uri, update_body)
- self.rest_client.expected_success(200, resp.status)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/network/network_client_base.py b/tempest/services/network/network_client_base.py
deleted file mode 100644
index 53fd222..0000000
--- a/tempest/services/network/network_client_base.py
+++ /dev/null
@@ -1,268 +0,0 @@
-# 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 time
-import urllib
-
-from tempest.common import rest_client
-from tempest.common.utils import misc
-from tempest import config
-from tempest import exceptions
-
-CONF = config.CONF
-
-# the following map is used to construct proper URI
-# for the given neutron resource
-service_resource_prefix_map = {
- 'networks': '',
- 'subnets': '',
- 'ports': '',
- 'pools': 'lb',
- 'vips': 'lb',
- 'health_monitors': 'lb',
- 'members': 'lb',
- 'ipsecpolicies': 'vpn',
- 'vpnservices': 'vpn',
- 'ikepolicies': 'vpn',
- 'ipsecpolicies': 'vpn',
- 'metering_labels': 'metering',
- 'metering_label_rules': 'metering',
- 'firewall_rules': 'fw',
- 'firewall_policies': 'fw',
- 'firewalls': 'fw'
-}
-
-# The following list represents resource names that do not require
-# changing underscore to a hyphen
-hyphen_exceptions = ["health_monitors", "firewall_rules", "firewall_policies"]
-
-# map from resource name to a plural name
-# needed only for those which can't be constructed as name + 's'
-resource_plural_map = {
- 'security_groups': 'security_groups',
- 'security_group_rules': 'security_group_rules',
- 'ipsecpolicy': 'ipsecpolicies',
- 'ikepolicy': 'ikepolicies',
- 'ipsecpolicy': 'ipsecpolicies',
- 'quotas': 'quotas',
- 'firewall_policy': 'firewall_policies'
-}
-
-
-class NetworkClientBase(object):
- def __init__(self, auth_provider):
- self.rest_client = self.get_rest_client(
- auth_provider)
- self.rest_client.service = CONF.network.catalog_type
- self.version = '2.0'
- self.uri_prefix = "v%s" % (self.version)
- self.build_timeout = CONF.network.build_timeout
- self.build_interval = CONF.network.build_interval
-
- def get_rest_client(self, auth_provider):
- raise NotImplementedError
-
- def post(self, uri, body, headers=None):
- return self.rest_client.post(uri, body, headers)
-
- def put(self, uri, body, headers=None):
- return self.rest_client.put(uri, body, headers)
-
- def get(self, uri, headers=None):
- return self.rest_client.get(uri, headers)
-
- def delete(self, uri, headers=None):
- return self.rest_client.delete(uri, headers)
-
- def deserialize_list(self, body):
- raise NotImplementedError
-
- def deserialize_single(self, body):
- raise NotImplementedError
-
- def get_uri(self, plural_name):
- # get service prefix from resource name
- service_prefix = service_resource_prefix_map.get(
- plural_name)
- if plural_name not in hyphen_exceptions:
- plural_name = plural_name.replace("_", "-")
- if service_prefix:
- uri = '%s/%s/%s' % (self.uri_prefix, service_prefix,
- plural_name)
- else:
- uri = '%s/%s' % (self.uri_prefix, plural_name)
- return uri
-
- def pluralize(self, resource_name):
- # get plural from map or just add 's'
- return resource_plural_map.get(resource_name, resource_name + 's')
-
- def _lister(self, plural_name):
- def _list(**filters):
- uri = self.get_uri(plural_name)
- if filters:
- uri += '?' + urllib.urlencode(filters, doseq=1)
- resp, body = self.get(uri)
- result = {plural_name: self.deserialize_list(body)}
- self.rest_client.expected_success(200, resp.status)
- return rest_client.ResponseBody(resp, result)
-
- return _list
-
- def _deleter(self, resource_name):
- def _delete(resource_id):
- plural = self.pluralize(resource_name)
- uri = '%s/%s' % (self.get_uri(plural), resource_id)
- resp, body = self.delete(uri)
- self.rest_client.expected_success(204, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- return _delete
-
- def _shower(self, resource_name):
- def _show(resource_id, **fields):
- # fields is a dict which key is 'fields' and value is a
- # list of field's name. An example:
- # {'fields': ['id', 'name']}
- plural = self.pluralize(resource_name)
- uri = '%s/%s' % (self.get_uri(plural), resource_id)
- if fields:
- uri += '?' + urllib.urlencode(fields, doseq=1)
- resp, body = self.get(uri)
- body = self.deserialize_single(body)
- self.rest_client.expected_success(200, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- return _show
-
- def _creater(self, resource_name):
- def _create(**kwargs):
- plural = self.pluralize(resource_name)
- uri = self.get_uri(plural)
- post_data = self.serialize({resource_name: kwargs})
- resp, body = self.post(uri, post_data)
- body = self.deserialize_single(body)
- self.rest_client.expected_success(201, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- return _create
-
- def _updater(self, resource_name):
- def _update(res_id, **kwargs):
- plural = self.pluralize(resource_name)
- uri = '%s/%s' % (self.get_uri(plural), res_id)
- post_data = self.serialize({resource_name: kwargs})
- resp, body = self.put(uri, post_data)
- body = self.deserialize_single(body)
- self.rest_client.expected_success(200, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- return _update
-
- def __getattr__(self, name):
- method_prefixes = ["list_", "delete_", "show_", "create_", "update_"]
- method_functors = [self._lister,
- self._deleter,
- self._shower,
- self._creater,
- self._updater]
- for index, prefix in enumerate(method_prefixes):
- prefix_len = len(prefix)
- if name[:prefix_len] == prefix:
- return method_functors[index](name[prefix_len:])
- raise AttributeError(name)
-
- # Common methods that are hard to automate
- def create_bulk_network(self, names):
- network_list = [{'name': name} for name in names]
- post_data = {'networks': network_list}
- body = self.serialize_list(post_data, "networks", "network")
- uri = self.get_uri("networks")
- resp, body = self.post(uri, body)
- body = {'networks': self.deserialize_list(body)}
- self.rest_client.expected_success(201, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def create_bulk_subnet(self, subnet_list):
- post_data = {'subnets': subnet_list}
- body = self.serialize_list(post_data, 'subnets', 'subnet')
- uri = self.get_uri('subnets')
- resp, body = self.post(uri, body)
- body = {'subnets': self.deserialize_list(body)}
- self.rest_client.expected_success(201, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def create_bulk_port(self, port_list):
- post_data = {'ports': port_list}
- body = self.serialize_list(post_data, 'ports', 'port')
- uri = self.get_uri('ports')
- resp, body = self.post(uri, body)
- body = {'ports': self.deserialize_list(body)}
- self.rest_client.expected_success(201, resp.status)
- return rest_client.ResponseBody(resp, body)
-
- def wait_for_resource_deletion(self, resource_type, id):
- """Waits for a resource to be deleted."""
- start_time = int(time.time())
- while True:
- if self.is_resource_deleted(resource_type, id):
- return
- if int(time.time()) - start_time >= self.build_timeout:
- raise exceptions.TimeoutException
- time.sleep(self.build_interval)
-
- def is_resource_deleted(self, resource_type, id):
- method = 'show_' + resource_type
- try:
- getattr(self, method)(id)
- except AttributeError:
- raise Exception("Unknown resource type %s " % resource_type)
- except exceptions.NotFound:
- return True
- return False
-
- def wait_for_resource_status(self, fetch, status, interval=None,
- timeout=None):
- """
- @summary: Waits for a network resource to reach a status
- @param fetch: the callable to be used to query the resource status
- @type fecth: callable that takes no parameters and returns the resource
- @param status: the status that the resource has to reach
- @type status: String
- @param interval: the number of seconds to wait between each status
- query
- @type interval: Integer
- @param timeout: the maximum number of seconds to wait for the resource
- to reach the desired status
- @type timeout: Integer
- """
- if not interval:
- interval = self.build_interval
- if not timeout:
- timeout = self.build_timeout
- start_time = time.time()
-
- while time.time() - start_time <= timeout:
- resource = fetch()
- if resource['status'] == status:
- return
- time.sleep(interval)
-
- # At this point, the wait has timed out
- message = 'Resource %s' % (str(resource))
- message += ' failed to reach status %s' % status
- message += ' (current: %s)' % resource['status']
- message += ' within the required time %s' % timeout
- caller = misc.find_test_caller()
- if caller:
- message = '(%s) %s' % (caller, message)
- raise exceptions.TimeoutException(message)
diff --git a/tempest/services/object_storage/account_client.py b/tempest/services/object_storage/account_client.py
index a2044ef..23984cd 100644
--- a/tempest/services/object_storage/account_client.py
+++ b/tempest/services/object_storage/account_client.py
@@ -18,17 +18,14 @@
from xml.etree import ElementTree as etree
from tempest.common import http
-from tempest.common import rest_client
from tempest import config
from tempest import exceptions
+from tempest.services.object_storage import base
CONF = config.CONF
-class AccountClient(rest_client.RestClient):
- def __init__(self, auth_provider):
- super(AccountClient, self).__init__(auth_provider)
- self.service = CONF.object_storage.catalog_type
+class AccountClient(base.ObjectStorageClient):
def create_account(self, data=None,
params=None,
@@ -167,17 +164,10 @@
return resp, body
-class AccountClientCustomizedHeader(rest_client.RestClient):
+class AccountClientCustomizedHeader(base.ObjectStorageClient):
# TODO(andreaf) This class is now redundant, to be removed in next patch
- def __init__(self, auth_provider):
- super(AccountClientCustomizedHeader, self).__init__(
- auth_provider)
- # Overwrites json-specific header encoding in rest_client.RestClient
- self.service = CONF.object_storage.catalog_type
- self.format = 'json'
-
def request(self, method, url, extra_headers=False, headers=None,
body=None):
"""A simple HTTP request interface."""
diff --git a/tempest/services/object_storage/base.py b/tempest/services/object_storage/base.py
new file mode 100644
index 0000000..c903ca5
--- /dev/null
+++ b/tempest/services/object_storage/base.py
@@ -0,0 +1,29 @@
+# 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.common import rest_client
+from tempest import config
+
+CONF = config.CONF
+
+
+class ObjectStorageClient(rest_client.RestClient):
+ """
+ Base object storage client class
+ """
+
+ def __init__(self, auth_provider):
+ super(ObjectStorageClient, self).__init__(auth_provider)
+ self.service = CONF.object_storage.catalog_type
+ self.format = 'json'
diff --git a/tempest/services/object_storage/container_client.py b/tempest/services/object_storage/container_client.py
index 182c4d0..c55826b 100644
--- a/tempest/services/object_storage/container_client.py
+++ b/tempest/services/object_storage/container_client.py
@@ -17,20 +17,10 @@
import urllib
from xml.etree import ElementTree as etree
-from tempest.common import rest_client
-from tempest import config
-
-CONF = config.CONF
+from tempest.services.object_storage import base
-class ContainerClient(rest_client.RestClient):
- def __init__(self, auth_provider):
- super(ContainerClient, self).__init__(auth_provider)
-
- # Overwrites json-specific header encoding in rest_client.RestClient
- self.headers = {}
- self.service = CONF.object_storage.catalog_type
- self.format = 'json'
+class ContainerClient(base.ObjectStorageClient):
def create_container(
self, container_name,
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index 7a69fa8..a93a9df 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -18,18 +18,14 @@
import urlparse
from tempest.common import http
-from tempest.common import rest_client
from tempest import config
from tempest import exceptions
+from tempest.services.object_storage import base
CONF = config.CONF
-class ObjectClient(rest_client.RestClient):
- def __init__(self, auth_provider):
- super(ObjectClient, self).__init__(auth_provider)
-
- self.service = CONF.object_storage.catalog_type
+class ObjectClient(base.ObjectStorageClient):
def create_object(self, container, object_name, data,
params=None, metadata=None):
@@ -182,17 +178,10 @@
return resp.status, resp.reason, resp_headers
-class ObjectClientCustomizedHeader(rest_client.RestClient):
+class ObjectClientCustomizedHeader(base.ObjectStorageClient):
# TODO(andreaf) This class is now redundant, to be removed in next patch
- def __init__(self, auth_provider):
- super(ObjectClientCustomizedHeader, self).__init__(
- auth_provider)
- # Overwrites json-specific header encoding in rest_client.RestClient
- self.service = CONF.object_storage.catalog_type
- self.format = 'json'
-
def request(self, method, url, extra_headers=False, headers=None,
body=None):
"""A simple HTTP request interface."""
diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py
index 996aceb..d2dd375 100644
--- a/tempest/services/telemetry/json/telemetry_client.py
+++ b/tempest/services/telemetry/json/telemetry_client.py
@@ -13,15 +13,22 @@
# License for the specific language governing permissions and limitations
# under the License.
+import urllib
+
from tempest.common import rest_client
+from tempest import config
from tempest.openstack.common import jsonutils as json
-import tempest.services.telemetry.telemetry_client_base as client
+
+CONF = config.CONF
-class TelemetryClientJSON(client.TelemetryClientBase):
+class TelemetryClientJSON(rest_client.RestClient):
- def get_rest_client(self, auth_provider):
- return rest_client.RestClient(auth_provider)
+ def __init__(self, auth_provider):
+ super(TelemetryClientJSON, self).__init__(auth_provider)
+ self.service = CONF.telemetry.catalog_type
+ self.version = '2'
+ self.uri_prefix = "v%s" % self.version
def deserialize(self, body):
return json.loads(body.replace("\n", ""))
@@ -42,4 +49,87 @@
def create_sample(self, meter_name, sample_list):
uri = "%s/meters/%s" % (self.uri_prefix, meter_name)
- return self.post(uri, str(sample_list))
+ body = self.serialize(sample_list)
+ resp, body = self.post(uri, body)
+ body = self.deserialize(body)
+ return resp, body
+
+ def helper_list(self, uri, query=None, period=None):
+ uri_dict = {}
+ if query:
+ uri_dict = {'q.field': query[0],
+ 'q.op': query[1],
+ 'q.value': query[2]}
+ if period:
+ uri_dict['period'] = period
+ if uri_dict:
+ uri += "?%s" % urllib.urlencode(uri_dict)
+ resp, body = self.get(uri)
+ body = self.deserialize(body)
+ return resp, body
+
+ def list_resources(self, query=None):
+ uri = '%s/resources' % self.uri_prefix
+ return self.helper_list(uri, query)
+
+ def list_meters(self, query=None):
+ uri = '%s/meters' % self.uri_prefix
+ return self.helper_list(uri, query)
+
+ def list_alarms(self, query=None):
+ uri = '%s/alarms' % self.uri_prefix
+ return self.helper_list(uri, query)
+
+ def list_statistics(self, meter, period=None, query=None):
+ uri = "%s/meters/%s/statistics" % (self.uri_prefix, meter)
+ return self.helper_list(uri, query, period)
+
+ def list_samples(self, meter_id, query=None):
+ uri = '%s/meters/%s' % (self.uri_prefix, meter_id)
+ return self.helper_list(uri, query)
+
+ def get_resource(self, resource_id):
+ uri = '%s/resources/%s' % (self.uri_prefix, resource_id)
+ resp, body = self.get(uri)
+ body = self.deserialize(body)
+ return resp, body
+
+ def get_alarm(self, alarm_id):
+ uri = '%s/alarms/%s' % (self.uri_prefix, alarm_id)
+ resp, body = self.get(uri)
+ body = self.deserialize(body)
+ return resp, body
+
+ def delete_alarm(self, alarm_id):
+ uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
+ resp, body = self.delete(uri)
+ if body:
+ body = self.deserialize(body)
+ return resp, body
+
+ def create_alarm(self, **kwargs):
+ uri = "%s/alarms" % self.uri_prefix
+ body = self.serialize(kwargs)
+ resp, body = self.post(uri, body)
+ body = self.deserialize(body)
+ return resp, body
+
+ def update_alarm(self, alarm_id, **kwargs):
+ uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
+ body = self.serialize(kwargs)
+ resp, body = self.put(uri, body)
+ body = self.deserialize(body)
+ return resp, body
+
+ def alarm_get_state(self, alarm_id):
+ uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
+ resp, body = self.get(uri)
+ body = self.deserialize(body)
+ return resp, body
+
+ def alarm_set_state(self, alarm_id, state):
+ uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
+ body = self.serialize(state)
+ resp, body = self.put(uri, body)
+ body = self.deserialize(body)
+ return resp, body
diff --git a/tempest/services/telemetry/telemetry_client_base.py b/tempest/services/telemetry/telemetry_client_base.py
deleted file mode 100644
index a184a77..0000000
--- a/tempest/services/telemetry/telemetry_client_base.py
+++ /dev/null
@@ -1,151 +0,0 @@
-# Copyright 2013 OpenStack Foundation
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import abc
-import urllib
-
-import six
-
-from tempest import config
-
-CONF = config.CONF
-
-
-@six.add_metaclass(abc.ABCMeta)
-class TelemetryClientBase(object):
-
- """
- Tempest REST client for Ceilometer V2 API.
- Implements the following basic Ceilometer abstractions:
- resources
- meters
- alarms
- queries
- statistics
- """
-
- def __init__(self, auth_provider):
- self.rest_client = self.get_rest_client(auth_provider)
- self.rest_client.service = CONF.telemetry.catalog_type
- self.version = '2'
- self.uri_prefix = "v%s" % self.version
-
- @abc.abstractmethod
- def get_rest_client(self, auth_provider):
- """
- :param config:
- :param username:
- :param password:
- :param auth_url:
- :param tenant_name:
- :return: RestClient
- """
-
- @abc.abstractmethod
- def deserialize(self, body):
- """
- :param body:
- :return: Deserialize body
- """
-
- @abc.abstractmethod
- def serialize(self, body):
- """
- :param body:
- :return: Serialize body
- """
-
- def post(self, uri, body):
- body = self.serialize(body)
- resp, body = self.rest_client.post(uri, body)
- body = self.deserialize(body)
- return resp, body
-
- def put(self, uri, body):
- body = self.serialize(body)
- resp, body = self.rest_client.put(uri, body)
- body = self.deserialize(body)
- return resp, body
-
- def get(self, uri):
- resp, body = self.rest_client.get(uri)
- body = self.deserialize(body)
- return resp, body
-
- def delete(self, uri):
- resp, body = self.rest_client.delete(uri)
- if body:
- body = self.deserialize(body)
- return resp, body
-
- def helper_list(self, uri, query=None, period=None):
- uri_dict = {}
- if query:
- uri_dict = {'q.field': query[0],
- 'q.op': query[1],
- 'q.value': query[2]}
- if period:
- uri_dict['period'] = period
- if uri_dict:
- uri += "?%s" % urllib.urlencode(uri_dict)
- return self.get(uri)
-
- def list_resources(self, query=None):
- uri = '%s/resources' % self.uri_prefix
- return self.helper_list(uri, query)
-
- def list_meters(self, query=None):
- uri = '%s/meters' % self.uri_prefix
- return self.helper_list(uri, query)
-
- def list_alarms(self, query=None):
- uri = '%s/alarms' % self.uri_prefix
- return self.helper_list(uri, query)
-
- def list_statistics(self, meter, period=None, query=None):
- uri = "%s/meters/%s/statistics" % (self.uri_prefix, meter)
- return self.helper_list(uri, query, period)
-
- def list_samples(self, meter_id, query=None):
- uri = '%s/meters/%s' % (self.uri_prefix, meter_id)
- return self.helper_list(uri, query)
-
- def get_resource(self, resource_id):
- uri = '%s/resources/%s' % (self.uri_prefix, resource_id)
- return self.get(uri)
-
- def get_alarm(self, alarm_id):
- uri = '%s/alarms/%s' % (self.uri_prefix, alarm_id)
- return self.get(uri)
-
- def delete_alarm(self, alarm_id):
- uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
- return self.delete(uri)
-
- def create_alarm(self, **kwargs):
- uri = "%s/alarms" % self.uri_prefix
- return self.post(uri, kwargs)
-
- def update_alarm(self, alarm_id, **kwargs):
- uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
- return self.put(uri, kwargs)
-
- def alarm_get_state(self, alarm_id):
- uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
- return self.get(uri)
-
- def alarm_set_state(self, alarm_id, state):
- uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
- return self.put(uri, state)
diff --git a/tempest/test.py b/tempest/test.py
index 886e7bb..ff829f3 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -274,8 +274,8 @@
cls.resource_setup()
except Exception:
etype, value, trace = sys.exc_info()
- LOG.info("%s in %s.setUpClass. Invoking tearDownClass." % (
- cls.__name__, etype))
+ LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass." % (
+ etype, cls.__name__))
cls.tearDownClass()
try:
raise etype, value, trace
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index f29ae5a..053dae1 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -320,8 +320,8 @@
return_values = (fake_http.fake_httplib({}, status=204), {})
remove_secgroup_mock = self.patch(
- 'tempest.services.network.network_client_base.'
- 'NetworkClientBase.delete', return_value=return_values)
+ 'tempest.services.network.json.network_client.'
+ 'NetworkClientJSON.delete', return_value=return_values)
iso_creds.clear_isolated_creds()
# Verify default security group delete
calls = remove_secgroup_mock.mock_calls
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index 00b17d9..707590e 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -157,19 +157,24 @@
instance.add_tag('key1', value='value1')
tags = self.ec2_client.get_all_tags()
- self.assertEqual(tags[0].name, 'key1')
- self.assertEqual(tags[0].value, 'value1')
+ td = {item.name: item.value for item in tags}
+
+ self.assertIn('key1', td)
+ self.assertEqual('value1', td['key1'])
tags = self.ec2_client.get_all_tags(filters={'key': 'key1'})
- self.assertEqual(tags[0].name, 'key1')
- self.assertEqual(tags[0].value, 'value1')
+ td = {item.name: item.value for item in tags}
+ self.assertIn('key1', td)
+ self.assertEqual('value1', td['key1'])
tags = self.ec2_client.get_all_tags(filters={'value': 'value1'})
- self.assertEqual(tags[0].name, 'key1')
- self.assertEqual(tags[0].value, 'value1')
+ td = {item.name: item.value for item in tags}
+ self.assertIn('key1', td)
+ self.assertEqual('value1', td['key1'])
tags = self.ec2_client.get_all_tags(filters={'key': 'value2'})
- self.assertEqual(len(tags), 0, str(tags))
+ td = {item.name: item.value for item in tags}
+ self.assertNotIn('key1', td)
for instance in reservation.instances:
instance.remove_tag('key1', value='value1')
diff --git a/tox.ini b/tox.ini
index edfee15..fe2f79e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -7,7 +7,8 @@
sitepackages = True
setenv = VIRTUAL_ENV={envdir}
OS_TEST_PATH=./tempest/test_discover
-deps = -r{toxinidir}/requirements.txt
+deps = setuptools
+ -r{toxinidir}/requirements.txt
[testenv]
setenv = VIRTUAL_ENV={envdir}