Merge "Simplify volume test classes inheritance"
diff --git a/HACKING.rst b/HACKING.rst
index fed4130..a546f8c 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -153,10 +153,25 @@
kwarg2=dict_of_numbers)
+openstack-common
+----------------
+
+A number of modules from openstack-common are imported into the project.
+
+These modules are "incubating" in openstack-common and are kept in sync
+with the help of openstack-common's update.py script. See:
+
+ http://wiki.openstack.org/CommonLibrary#Incubation
+
+The copy of the code should never be directly modified here. Please
+always update openstack-common first and then run the script to copy
+the changes across.
+
+
OpenStack Trademark
-------------------
-OpenStack is a registered trademark of OpenStack, LLC, and uses the
+OpenStack is a registered trademark of the OpenStack Foundation, and uses the
following capitalization:
OpenStack
diff --git a/tempest/clients.py b/tempest/clients.py
index 8d9c216..7eb17f3 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -19,8 +19,7 @@
from tempest import config
from tempest import exceptions
-from tempest.services.boto.clients import APIClientEC2
-from tempest.services.boto.clients import ObjectClientS3
+from tempest.services import botoclients
from tempest.services.compute.json.extensions_client import \
ExtensionsClientJSON
from tempest.services.compute.json.flavors_client import FlavorsClientJSON
@@ -216,8 +215,8 @@
self.image_client = ImageClientJSON(*client_args)
self.container_client = ContainerClient(*client_args)
self.object_client = ObjectClient(*client_args)
- self.ec2api_client = APIClientEC2(*client_args)
- self.s3_client = ObjectClientS3(*client_args)
+ self.ec2api_client = botoclients.APIClientEC2(*client_args)
+ self.s3_client = botoclients.ObjectClientS3(*client_args)
self.custom_object_client = ObjectClientCustomizedHeader(*client_args)
self.custom_account_client = \
AccountClientCustomizedHeader(*client_args)
diff --git a/tempest/services/boto/__init__.py b/tempest/services/boto/__init__.py
deleted file mode 100644
index f744d9d..0000000
--- a/tempest/services/boto/__init__.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 OpenStack, LLC
-# 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 ConfigParser import DuplicateSectionError
-from contextlib import closing
-import re
-from types import MethodType
-
-import boto
-
-from tempest.exceptions import InvalidConfiguration
-from tempest.exceptions import NotFound
-
-
-class BotoClientBase(object):
-
- ALLOWED_METHODS = set()
-
- def __init__(self, config,
- username=None, password=None,
- auth_url=None, tenant_name=None,
- *args, **kwargs):
-
- self.connection_timeout = str(config.boto.http_socket_timeout)
- self.num_retries = str(config.boto.num_retries)
- self.build_timeout = config.boto.build_timeout
- self.ks_cred = {"username": username,
- "password": password,
- "auth_url": auth_url,
- "tenant_name": tenant_name}
-
- def _keystone_aws_get(self):
- import keystoneclient.v2_0.client
-
- keystone = keystoneclient.v2_0.client.Client(**self.ks_cred)
- ec2_cred_list = keystone.ec2.list(keystone.auth_user_id)
- ec2_cred = None
- for cred in ec2_cred_list:
- if cred.tenant_id == keystone.auth_tenant_id:
- ec2_cred = cred
- break
- else:
- ec2_cred = keystone.ec2.create(keystone.auth_user_id,
- keystone.auth_tenant_id)
- if not all((ec2_cred, ec2_cred.access, ec2_cred.secret)):
- raise NotFound("Unable to get access and secret keys")
- return ec2_cred
-
- def _config_boto_timeout(self, timeout, retries):
- try:
- boto.config.add_section("Boto")
- except DuplicateSectionError:
- pass
- boto.config.set("Boto", "http_socket_timeout", timeout)
- boto.config.set("Boto", "num_retries", retries)
-
- def __getattr__(self, name):
- """Automatically creates methods for the allowed methods set."""
- if name in self.ALLOWED_METHODS:
- def func(self, *args, **kwargs):
- with closing(self.get_connection()) as conn:
- return getattr(conn, name)(*args, **kwargs)
-
- func.__name__ = name
- setattr(self, name, MethodType(func, self, self.__class__))
- setattr(self.__class__, name,
- MethodType(func, None, self.__class__))
- return getattr(self, name)
- else:
- raise AttributeError(name)
-
- def get_connection(self):
- self._config_boto_timeout(self.connection_timeout, self.num_retries)
- if not all((self.connection_data["aws_access_key_id"],
- self.connection_data["aws_secret_access_key"])):
- if all(self.ks_cred.itervalues()):
- ec2_cred = self._keystone_aws_get()
- self.connection_data["aws_access_key_id"] = \
- ec2_cred.access
- self.connection_data["aws_secret_access_key"] = \
- ec2_cred.secret
- else:
- raise InvalidConfiguration(
- "Unable to get access and secret keys")
- return self.connect_method(**self.connection_data)
diff --git a/tempest/services/boto/clients.py b/tempest/services/botoclients.py
similarity index 63%
rename from tempest/services/boto/clients.py
rename to tempest/services/botoclients.py
index 228e826..143257a 100644
--- a/tempest/services/boto/clients.py
+++ b/tempest/services/botoclients.py
@@ -15,13 +15,90 @@
# License for the specific language governing permissions and limitations
# under the License.
+import ConfigParser
+import contextlib
+import re
+import types
import urlparse
-import boto
-from boto.ec2.regioninfo import RegionInfo
-from boto.s3.connection import OrdinaryCallingFormat
+from tempest import exceptions
-from tempest.services.boto import BotoClientBase
+import boto
+import boto.ec2
+import boto.s3.connection
+
+
+class BotoClientBase(object):
+
+ ALLOWED_METHODS = set()
+
+ def __init__(self, config,
+ username=None, password=None,
+ auth_url=None, tenant_name=None,
+ *args, **kwargs):
+
+ self.connection_timeout = str(config.boto.http_socket_timeout)
+ self.num_retries = str(config.boto.num_retries)
+ self.build_timeout = config.boto.build_timeout
+ self.ks_cred = {"username": username,
+ "password": password,
+ "auth_url": auth_url,
+ "tenant_name": tenant_name}
+
+ def _keystone_aws_get(self):
+ import keystoneclient.v2_0.client
+
+ keystone = keystoneclient.v2_0.client.Client(**self.ks_cred)
+ ec2_cred_list = keystone.ec2.list(keystone.auth_user_id)
+ ec2_cred = None
+ for cred in ec2_cred_list:
+ if cred.tenant_id == keystone.auth_tenant_id:
+ ec2_cred = cred
+ break
+ else:
+ ec2_cred = keystone.ec2.create(keystone.auth_user_id,
+ keystone.auth_tenant_id)
+ if not all((ec2_cred, ec2_cred.access, ec2_cred.secret)):
+ raise exceptions.NotFound("Unable to get access and secret keys")
+ return ec2_cred
+
+ def _config_boto_timeout(self, timeout, retries):
+ try:
+ boto.config.add_section("Boto")
+ except ConfigParser.DuplicateSectionError:
+ pass
+ boto.config.set("Boto", "http_socket_timeout", timeout)
+ boto.config.set("Boto", "num_retries", retries)
+
+ def __getattr__(self, name):
+ """Automatically creates methods for the allowed methods set."""
+ if name in self.ALLOWED_METHODS:
+ def func(self, *args, **kwargs):
+ with contextlib.closing(self.get_connection()) as conn:
+ return getattr(conn, name)(*args, **kwargs)
+
+ func.__name__ = name
+ setattr(self, name, types.MethodType(func, self, self.__class__))
+ setattr(self.__class__, name,
+ types.MethodType(func, None, self.__class__))
+ return getattr(self, name)
+ else:
+ raise AttributeError(name)
+
+ def get_connection(self):
+ self._config_boto_timeout(self.connection_timeout, self.num_retries)
+ if not all((self.connection_data["aws_access_key_id"],
+ self.connection_data["aws_secret_access_key"])):
+ if all(self.ks_cred.itervalues()):
+ ec2_cred = self._keystone_aws_get()
+ self.connection_data["aws_access_key_id"] = \
+ ec2_cred.access
+ self.connection_data["aws_secret_access_key"] = \
+ ec2_cred.secret
+ else:
+ raise exceptions.InvalidConfiguration(
+ "Unable to get access and secret keys")
+ return self.connect_method(**self.connection_data)
class APIClientEC2(BotoClientBase):
@@ -35,8 +112,8 @@
aws_secret = config.boto.aws_secret
purl = urlparse.urlparse(config.boto.ec2_url)
- region = RegionInfo(name=config.identity.region,
- endpoint=purl.hostname)
+ region = boto.ec2.regioninfo.RegionInfo(name=config.identity.region,
+ endpoint=purl.hostname)
port = purl.port
if port is None:
if purl.scheme is not "https":
@@ -134,7 +211,8 @@
"is_secure": purl.scheme == "https",
"host": purl.hostname,
"port": port,
- "calling_format": OrdinaryCallingFormat()}
+ "calling_format": boto.s3.connection.
+ OrdinaryCallingFormat()}
ALLOWED_METHODS = set(('create_bucket', 'delete_bucket', 'generate_url',
'get_all_buckets', 'get_bucket', 'delete_key',
diff --git a/tempest/services/compute/admin/json/quotas_client.py b/tempest/services/compute/admin/json/quotas_client.py
index 0a4bd72..b886834 100644
--- a/tempest/services/compute/admin/json/quotas_client.py
+++ b/tempest/services/compute/admin/json/quotas_client.py
@@ -37,38 +37,38 @@
"""
post_body = {}
- if injected_file_content_bytes >= 0:
+ if injected_file_content_bytes is not None:
post_body['injected_file_content_bytes'] = \
injected_file_content_bytes
- if metadata_items >= 0:
+ if metadata_items is not None:
post_body['metadata_items'] = metadata_items
- if ram >= 0:
+ if ram is not None:
post_body['ram'] = ram
- if floating_ips >= 0:
+ if floating_ips is not None:
post_body['floating_ips'] = floating_ips
- if key_pairs >= 0:
+ if key_pairs is not None:
post_body['key_pairs'] = key_pairs
- if instances >= 0:
+ if instances is not None:
post_body['instances'] = instances
- if security_group_rules >= 0:
+ if security_group_rules is not None:
post_body['security_group_rules'] = security_group_rules
- if injected_files >= 0:
+ if injected_files is not None:
post_body['injected_files'] = injected_files
- if cores >= 0:
+ if cores is not None:
post_body['cores'] = cores
- if injected_file_path_bytes >= 0:
+ if injected_file_path_bytes is not None:
post_body['injected_file_path_bytes'] = injected_file_path_bytes
- if security_groups >= 0:
+ if security_groups is not None:
post_body['security_groups'] = security_groups
post_body = json.dumps({'quota_set': post_body})
diff --git a/tempest/services/compute/json/volumes_extensions_client.py b/tempest/services/compute/json/volumes_extensions_client.py
index a5f6ec3..e4271d9 100644
--- a/tempest/services/compute/json/volumes_extensions_client.py
+++ b/tempest/services/compute/json/volumes_extensions_client.py
@@ -105,7 +105,7 @@
def is_resource_deleted(self, id):
try:
- self.get_volume(id, wait=True)
+ self.get_volume(id)
except exceptions.NotFound:
return True
return False
diff --git a/tempest/services/compute/xml/images_client.py b/tempest/services/compute/xml/images_client.py
index bde9e16..3b01efb 100644
--- a/tempest/services/compute/xml/images_client.py
+++ b/tempest/services/compute/xml/images_client.py
@@ -39,43 +39,43 @@
self.build_timeout = self.config.compute.build_timeout
def _parse_server(self, node):
- json = xml_to_json(node)
- return self._parse_links(node, json)
+ data = xml_to_json(node)
+ return self._parse_links(node, data)
def _parse_image(self, node):
"""Parses detailed XML image information into dictionary."""
- json = xml_to_json(node)
+ data = xml_to_json(node)
- self._parse_links(node, json)
+ self._parse_links(node, data)
# parse all metadata
- if 'metadata' in json:
+ if 'metadata' in data:
tag = node.find('{%s}metadata' % XMLNS_11)
- json['metadata'] = dict((x.get('key'), x.text)
+ data['metadata'] = dict((x.get('key'), x.text)
for x in tag.getchildren())
# parse server information
- if 'server' in json:
+ if 'server' in data:
tag = node.find('{%s}server' % XMLNS_11)
- json['server'] = self._parse_server(tag)
- return json
+ data['server'] = self._parse_server(tag)
+ return data
- def _parse_links(self, node, json):
+ def _parse_links(self, node, data):
"""Append multiple links under a list."""
# look for links
- if 'link' in json:
+ if 'link' in data:
# remove single link element
- del json['link']
- json['links'] = [xml_to_json(x) for x in
+ del data['link']
+ data['links'] = [xml_to_json(x) for x in
node.findall('{http://www.w3.org/2005/Atom}link')]
- return json
+ return data
def _parse_images(self, xml):
- json = {'images': []}
+ data = {'images': []}
images = xml.getchildren()
for image in images:
- json['images'].append(self._parse_image(image))
- return json
+ data['images'].append(self._parse_image(image))
+ return data
def create_image(self, server_id, name, meta=None):
"""Creates an image of the original server."""
@@ -160,9 +160,17 @@
body = xml_to_json(etree.fromstring(body))
return resp, body['metadata']
+ def _metadata_body(image_id, meta):
+ post_body = Document('metadata')
+ for k, v in meta:
+ text = Text(v)
+ metadata = Element('meta', text, key=k)
+ post_body.append(metadata)
+ return post_body
+
def set_image_metadata(self, image_id, meta):
"""Sets the metadata for an image."""
- post_body = json.dumps({'metadata': meta})
+ post_body = self._metadata_body(image_id, meta)
resp, body = self.put('images/%s/metadata' % str(image_id),
post_body, self.headers)
body = xml_to_json(etree.fromstring(body))
@@ -170,13 +178,7 @@
def update_image_metadata(self, image_id, meta):
"""Updates the metadata for an image."""
- post_body = Element('metadata', meta)
- for k, v in meta:
- metadata = Element('meta', key=k)
- text = Text(v)
- metadata.append(text)
- post_body.append(metadata)
-
+ post_body = self._metadata_body(image_id, meta)
resp, body = self.post('images/%s/metadata' % str(image_id),
post_body, self.headers)
body = xml_to_json(etree.fromstring(body))
@@ -191,7 +193,15 @@
def set_image_metadata_item(self, image_id, key, meta):
"""Sets the value for a specific image metadata key."""
- post_body = json.dumps({'meta': meta})
+ post_body = Document('meta', Text(meta), key=key)
+ resp, body = self.post('images/%s/metadata/%s' % (str(image_id), key),
+ post_body, self.headers)
+ body = xml_to_json(etree.fromstring(body))
+ return resp, body['meta']
+
+ def update_image_metadata_item(self, image_id, key, meta):
+ """Sets the value for a specific image metadata key."""
+ post_body = Document('meta', Text(meta), key=key)
resp, body = self.put('images/%s/metadata/%s' % (str(image_id), key),
post_body, self.headers)
body = xml_to_json(etree.fromstring(body))
diff --git a/tempest/services/compute/xml/volumes_extensions_client.py b/tempest/services/compute/xml/volumes_extensions_client.py
index 60ef398..69b9bac 100644
--- a/tempest/services/compute/xml/volumes_extensions_client.py
+++ b/tempest/services/compute/xml/volumes_extensions_client.py
@@ -141,7 +141,7 @@
def is_resource_deleted(self, id):
try:
- self.get_volume(id, wait=True)
+ self.get_volume(id)
except exceptions.NotFound:
return True
return False
diff --git a/tempest/services/identity/json/identity_client.py b/tempest/services/identity/json/identity_client.py
index 403a3ac..68e7d4b 100644
--- a/tempest/services/identity/json/identity_client.py
+++ b/tempest/services/identity/json/identity_client.py
@@ -244,8 +244,10 @@
if headers is None:
headers = {}
+ self._log_request(method, url, headers, body)
resp, resp_body = self.http_obj.request(url, method,
headers=headers, body=body)
+ self._log_response(resp, resp_body)
if resp.status in (401, 403):
resp_body = json.loads(resp_body)
diff --git a/tempest/services/identity/xml/identity_client.py b/tempest/services/identity/xml/identity_client.py
index 1b96ae0..2431282 100644
--- a/tempest/services/identity/xml/identity_client.py
+++ b/tempest/services/identity/xml/identity_client.py
@@ -45,8 +45,8 @@
return array
def _parse_body(self, body):
- json = xml_to_json(body)
- return json
+ data = xml_to_json(body)
+ return data
def has_admin_extensions(self):
"""
@@ -272,9 +272,10 @@
self.http_obj = httplib2.Http(disable_ssl_certificate_validation=dscv)
if headers is None:
headers = {}
-
+ self._log_request(method, url, headers, body)
resp, resp_body = self.http_obj.request(url, method,
headers=headers, body=body)
+ self._log_response(resp, resp_body)
if resp.status in (401, 403):
resp_body = json.loads(resp_body)
diff --git a/tempest/services/image/json/image_client.py b/tempest/services/image/json/image_client.py
index d595ec3..e9276aa 100644
--- a/tempest/services/image/json/image_client.py
+++ b/tempest/services/image/json/image_client.py
@@ -16,6 +16,7 @@
# under the License.
import copy
+import errno
import json
import os
import time
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index 75e1a8b..ff1556f 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -125,7 +125,7 @@
def is_resource_deleted(self, id):
try:
- self.get_volume(id, wait=True)
+ self.get_volume(id)
except exceptions.NotFound:
return True
return False
diff --git a/tempest/services/volume/xml/volumes_client.py b/tempest/services/volume/xml/volumes_client.py
index 862ffae..5041869 100644
--- a/tempest/services/volume/xml/volumes_client.py
+++ b/tempest/services/volume/xml/volumes_client.py
@@ -151,7 +151,7 @@
def is_resource_deleted(self, id):
try:
- self.get_volume(id, wait=True)
+ self.get_volume(id)
except exceptions.NotFound:
return True
return False
diff --git a/tempest/tests/compute/base.py b/tempest/tests/compute/base.py
index f2af1fc..594535f 100644
--- a/tempest/tests/compute/base.py
+++ b/tempest/tests/compute/base.py
@@ -154,7 +154,7 @@
@classmethod
def clear_isolated_creds(cls):
if not cls.isolated_creds:
- pass
+ return
admin_client = cls._get_identity_admin_client()
for user, tenant in cls.isolated_creds:
diff --git a/tempest/tests/compute/servers/test_console_output.py b/tempest/tests/compute/servers/test_console_output.py
index 78639f8..bdf449d 100644
--- a/tempest/tests/compute/servers/test_console_output.py
+++ b/tempest/tests/compute/servers/test_console_output.py
@@ -28,7 +28,6 @@
@classmethod
def setUpClass(self, cls):
cls.name = rand_name('server')
- cls.client = cls.servers_client
resp, server = cls.servers_client.create_server(cls.name,
cls.image_ref,
cls.flavor_ref)
@@ -45,7 +44,8 @@
# Positive test:Should be able to GET the console output
# for a given server_id and number of lines
def get_output():
- resp, output = self.client.get_console_output(self.server_id, 10)
+ resp, output = self.servers_client.get_console_output(
+ self.server_id, 10)
self.assertEqual(200, resp.status)
self.assertNotEqual(output, None)
lines = len(output.split('\n'))
@@ -57,7 +57,8 @@
# Negative test: Should not be able to get the console output
# for an invalid server_id
try:
- resp, output = self.client.get_console_output('!@#$%^&*()', 10)
+ resp, output = self.servers_client.get_console_output(
+ '!@#$%^&*()', 10)
except exceptions.NotFound:
pass
@@ -72,8 +73,8 @@
'REBOOT')
resp, server = self.servers_client.get_server(self.server_id)
if (server['status'] == 'REBOOT'):
- resp, output = self.client.get_console_output(self.server_id,
- 10)
+ resp, output = self.servers_client.get_console_output(
+ self.server_id, 10)
self.assertEqual(200, resp.status)
self.assertNotEqual(output, None)
lines = len(output.split('\n'))
diff --git a/tempest/tests/compute/servers/test_server_actions.py b/tempest/tests/compute/servers/test_server_actions.py
index c30538f..06e441a 100644
--- a/tempest/tests/compute/servers/test_server_actions.py
+++ b/tempest/tests/compute/servers/test_server_actions.py
@@ -206,6 +206,18 @@
self.fail('The server rebuild for a non existing server should not'
' be allowed')
+ @classmethod
+ def rebuild_servers(cls):
+ # Destroy any existing server and creates a new one
+ cls.clear_servers()
+ cls.name = rand_name('server')
+ resp, server = cls.create_server_with_extras(cls.name,
+ cls.image_ref,
+ cls.flavor_ref)
+ cls.server_id = server['id']
+ cls.password = server['adminPass']
+ cls.client.wait_for_server_status(cls.server_id, 'ACTIVE')
+
class ServerActionsTestXML(base.BaseComputeTestXML,
ServerActionsTestBase):
@@ -216,30 +228,13 @@
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
except exceptions:
# Rebuild server if something happened to it during a test
- self.clear_servers()
- resp, server = self.create_server_with_extras(self.name,
- self.image_ref,
- self.flavor_ref)
- self.server_id = server['id']
- self.password = server['adminPass']
- self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+ self.rebuild_servers()
@classmethod
def setUpClass(cls):
super(ServerActionsTestXML, cls).setUpClass()
cls.client = cls.servers_client
- cls.name = rand_name('server')
- resp, server = cls.create_server_with_extras(cls.name,
- cls.image_ref,
- cls.flavor_ref)
- cls.server_id = server['id']
- cls.password = server['adminPass']
- cls.client.wait_for_server_status(cls.server_id, 'ACTIVE')
-
- @classmethod
- def tearDownClass(cls):
- cls.clear_servers()
- super(ServerActionsTestXML, cls).tearDownClass()
+ cls.rebuild_servers()
class ServerActionsTestJSON(base.BaseComputeTestJSON,
@@ -251,27 +246,10 @@
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
except exceptions:
# Rebuild server if something happened to it during a test
- self.clear_servers()
- resp, server = self.create_server_with_extras(self.name,
- self.image_ref,
- self.flavor_ref)
- self.server_id = server['id']
- self.password = server['adminPass']
- self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+ self.rebuild_servers()
@classmethod
def setUpClass(cls):
super(ServerActionsTestJSON, cls).setUpClass()
cls.client = cls.servers_client
- cls.name = rand_name('server')
- resp, server = cls.create_server_with_extras(cls.name,
- cls.image_ref,
- cls.flavor_ref)
- cls.server_id = server['id']
- cls.password = server['adminPass']
- cls.client.wait_for_server_status(cls.server_id, 'ACTIVE')
-
- @classmethod
- def tearDownClass(cls):
- cls.clear_servers()
- super(ServerActionsTestJSON, cls).tearDownClass()
+ cls.rebuild_servers()
diff --git a/tempest/tests/compute/servers/test_servers.py b/tempest/tests/compute/servers/test_servers.py
index fbcfe85..caf0679 100644
--- a/tempest/tests/compute/servers/test_servers.py
+++ b/tempest/tests/compute/servers/test_servers.py
@@ -161,25 +161,9 @@
super(ServersTestJSON, cls).setUpClass()
cls.client = cls.servers_client
- def tearDown(self):
- # clean up any remaining servers and wait for them to fully
- # delete. This is done because delete calls are async, and if
- # deletes are running slow we could very well overrun system
- # memory
- self.clear_servers()
- super(ServersTestJSON, self).tearDown()
-
class ServersTestXML(base.BaseComputeTestXML, ServersTestBase):
@classmethod
def setUpClass(cls):
super(ServersTestXML, cls).setUpClass()
cls.client = cls.servers_client
-
- def tearDown(self):
- # clean up any remaining servers and wait for them to fully
- # delete. This is done because delete calls are async, and if
- # deletes are running slow we could very well overrun system
- # memory
- self.clear_servers()
- super(ServersTestXML, self).tearDown()
diff --git a/tempest/tests/compute/servers/test_servers_negative.py b/tempest/tests/compute/servers/test_servers_negative.py
index 09d2a9c..9b528f6 100644
--- a/tempest/tests/compute/servers/test_servers_negative.py
+++ b/tempest/tests/compute/servers/test_servers_negative.py
@@ -273,3 +273,17 @@
self.assertRaises(exceptions.NotFound, self.client.delete_server,
sys.maxint + 1)
+
+ @attr(type='negative')
+ def test_create_with_nonexistent_security_group(self):
+ # Create a server with a nonexistent security group
+ try:
+ security_groups = [{'name': 'does_not_exist'}]
+ self.create_server_with_extras('fail',
+ self.image_ref,
+ self.flavor_ref,
+ security_groups=security_groups)
+ except exceptions.BadRequest:
+ pass
+ else:
+ self.fail('Server was created with nonexistent security group')
diff --git a/tempest/tests/volume/admin/test_volume_types_extra_specs.py b/tempest/tests/volume/admin/test_volume_types_extra_specs.py
index 98756db..31e2879 100644
--- a/tempest/tests/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/tests/volume/admin/test_volume_types_extra_specs.py
@@ -26,7 +26,6 @@
def setUpClass(cls):
super(VolumeTypesExtraSpecsTest, cls).setUpClass()
vol_type_name = rand_name('Volume-type-')
- cls.extra_spec = {"spec1": "val1"}
resp, cls.volume_type = cls.client.create_volume_type(vol_type_name)
@classmethod
@@ -37,6 +36,12 @@
def test_volume_type_extra_specs_list(self):
# List Volume types extra specs.
try:
+ extra_specs = {"spec1": "val1"}
+ resp, body = self.client.\
+ create_volume_type_extra_specs(self.volume_type['id'], extra_specs)
+ self.assertEqual(200, resp.status)
+ self.assertEqual(extra_specs, body,
+ "Volume type extra spec incorrectly created")
resp, body = self.client.\
list_volume_types_extra_specs(self.volume_type['id'])
self.assertEqual(200, resp.status)
@@ -49,49 +54,46 @@
def test_volume_type_extra_specs_update(self):
# Update volume type extra specs
try:
- extra_spec = {"spec1": "val2"}
- resp, body = self.client.\
- update_volume_type_extra_specs(self.volume_type['id'],
- extra_spec.keys()[0],
- extra_spec)
- self.assertEqual(200, resp.status)
- self.assertTrue('spec1' in body,
- "Volume type extra spec incorrectly updated")
- self.assertEqual(extra_spec['spec1'], body['spec1'],
- "Volume type extra spec incorrectly updated")
- except Exception:
- self.fail("Couldnt update volume type extra spec")
-
- def test_volume_type_extra_spec_create_delete(self):
- # Create/Delete volume type extra spec.
- try:
extra_specs = {"spec2": "val1"}
resp, body = self.client.\
create_volume_type_extra_specs(self.volume_type['id'], extra_specs)
self.assertEqual(200, resp.status)
self.assertEqual(extra_specs, body,
"Volume type extra spec incorrectly created")
- resp, _ = self.client.\
- delete_volume_type_extra_specs(self.volume_type['id'],
- extra_specs.keys()[0])
- self.assertEqual(202, resp.status)
- except Exception:
- self.fail("Could not create a volume_type extra spec")
- def test_volume_type_extra_spec_create_get(self):
- # Create/get volume type extra spec
+ extra_spec = {"spec2": "val2"}
+ resp, body = self.client.\
+ update_volume_type_extra_specs(self.volume_type['id'],
+ extra_spec.keys()[0],
+ extra_spec)
+ self.assertEqual(200, resp.status)
+ self.assertTrue('spec2' in body,
+ "Volume type extra spec incorrectly updated")
+ self.assertEqual(extra_spec['spec2'], body['spec2'],
+ "Volume type extra spec incorrectly updated")
+ except Exception:
+ self.fail("Couldnt update volume type extra spec")
+
+ def test_volume_type_extra_spec_create_get_delete(self):
+ # Create/Get/Delete volume type extra spec.
try:
- extra_specs = {"spec1": "val1"}
+ extra_specs = {"spec3": "val1"}
resp, body = self.client.\
create_volume_type_extra_specs(self.volume_type['id'], extra_specs)
self.assertEqual(200, resp.status)
self.assertEqual(extra_specs, body,
"Volume type extra spec incorrectly created")
+
resp, fetched_vol_type_extra_spec = self.client.\
get_volume_type_extra_specs(self.volume_type['id'],
extra_specs.keys()[0])
self.assertEqual(200, resp.status)
self.assertEqual(extra_specs, body,
"Volume type extra spec incorrectly fetched")
+
+ resp, _ = self.client.\
+ delete_volume_type_extra_specs(self.volume_type['id'],
+ extra_specs.keys()[0])
+ self.assertEqual(202, resp.status)
except Exception:
self.fail("Could not create a volume_type extra spec")
diff --git a/tempest/tests/volume/base.py b/tempest/tests/volume/base.py
index 480f125..4ddd670 100644
--- a/tempest/tests/volume/base.py
+++ b/tempest/tests/volume/base.py
@@ -113,7 +113,7 @@
@classmethod
def clear_isolated_creds(cls):
if not cls.isolated_creds:
- pass
+ return
admin_client = cls._get_identity_admin_client()
for user, tenant in cls.isolated_creds: