Simplify whitebox/manager
* Allow the generic resource deletion (thing.delete) to operate on resources allocated in the setUpClass-es too. * test_images_whitebox.py is using the python client libraries as the scenario tests. * Remove the not used part of the tempest/manager.py Change-Id: I980a70d22dc7a3a65a26a8197c7888b125eb3b05
This commit is contained in:
parent
7f9a3125bb
commit
d6d8629107
|
@ -15,41 +15,8 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from tempest.common import log as logging
|
|
||||||
import tempest.config
|
import tempest.config
|
||||||
from tempest import exceptions
|
from tempest import exceptions
|
||||||
# Tempest REST Fuzz testing client libs
|
|
||||||
from tempest.services.compute.json import extensions_client
|
|
||||||
from tempest.services.compute.json import flavors_client
|
|
||||||
from tempest.services.compute.json import floating_ips_client
|
|
||||||
from tempest.services.compute.json import hypervisor_client
|
|
||||||
from tempest.services.compute.json import images_client
|
|
||||||
from tempest.services.compute.json import keypairs_client
|
|
||||||
from tempest.services.compute.json import limits_client
|
|
||||||
from tempest.services.compute.json import quotas_client
|
|
||||||
from tempest.services.compute.json import security_groups_client
|
|
||||||
from tempest.services.compute.json import servers_client
|
|
||||||
from tempest.services.compute.json import volumes_extensions_client
|
|
||||||
from tempest.services.network.json import network_client
|
|
||||||
from tempest.services.volume.json import snapshots_client
|
|
||||||
from tempest.services.volume.json import volumes_client
|
|
||||||
|
|
||||||
NetworkClient = network_client.NetworkClient
|
|
||||||
ImagesClient = images_client.ImagesClientJSON
|
|
||||||
FlavorsClient = flavors_client.FlavorsClientJSON
|
|
||||||
ServersClient = servers_client.ServersClientJSON
|
|
||||||
LimitsClient = limits_client.LimitsClientJSON
|
|
||||||
ExtensionsClient = extensions_client.ExtensionsClientJSON
|
|
||||||
FloatingIPsClient = floating_ips_client.FloatingIPsClientJSON
|
|
||||||
SecurityGroupsClient = security_groups_client.SecurityGroupsClientJSON
|
|
||||||
KeyPairsClient = keypairs_client.KeyPairsClientJSON
|
|
||||||
VolumesExtensionsClient = volumes_extensions_client.VolumesExtensionsClientJSON
|
|
||||||
VolumesClient = volumes_client.VolumesClientJSON
|
|
||||||
SnapshotsClient = snapshots_client.SnapshotsClientJSON
|
|
||||||
QuotasClient = quotas_client.QuotasClientJSON
|
|
||||||
HypervisorClient = hypervisor_client.HypervisorClientJSON
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class Manager(object):
|
class Manager(object):
|
||||||
|
@ -73,97 +40,3 @@ class Manager(object):
|
||||||
"tenant_name: %(t)s" %
|
"tenant_name: %(t)s" %
|
||||||
{'u': username, 'p': password, 't': tenant_name})
|
{'u': username, 'p': password, 't': tenant_name})
|
||||||
raise exceptions.InvalidConfiguration(msg)
|
raise exceptions.InvalidConfiguration(msg)
|
||||||
|
|
||||||
|
|
||||||
class FuzzClientManager(Manager):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Manager class that indicates the client provided by the manager
|
|
||||||
is a fuzz-testing client that Tempest contains. These fuzz-testing
|
|
||||||
clients are used to be able to throw random or invalid data at
|
|
||||||
an endpoint and check for appropriate error messages returned
|
|
||||||
from the endpoint.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ComputeFuzzClientManager(FuzzClientManager):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Manager that uses the Tempest REST client that can send
|
|
||||||
random or invalid data at the OpenStack Compute API
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, username=None, password=None, tenant_name=None):
|
|
||||||
"""
|
|
||||||
We allow overriding of the credentials used within the various
|
|
||||||
client classes managed by the Manager object. Left as None, the
|
|
||||||
standard username/password/tenant_name is used.
|
|
||||||
|
|
||||||
:param username: Override of the username
|
|
||||||
:param password: Override of the password
|
|
||||||
:param tenant_name: Override of the tenant name
|
|
||||||
"""
|
|
||||||
super(ComputeFuzzClientManager, self).__init__()
|
|
||||||
|
|
||||||
# If no creds are provided, we fall back on the defaults
|
|
||||||
# in the config file for the Compute API.
|
|
||||||
username = username or self.config.identity.username
|
|
||||||
password = password or self.config.identity.password
|
|
||||||
tenant_name = tenant_name or self.config.identity.tenant_name
|
|
||||||
|
|
||||||
self._validate_credentials(username, password, tenant_name)
|
|
||||||
|
|
||||||
auth_url = self.config.identity.uri
|
|
||||||
|
|
||||||
# Ensure /tokens is in the URL for Keystone...
|
|
||||||
if 'tokens' not in auth_url:
|
|
||||||
auth_url = auth_url.rstrip('/') + '/tokens'
|
|
||||||
|
|
||||||
client_args = (self.config, username, password, auth_url,
|
|
||||||
tenant_name)
|
|
||||||
|
|
||||||
self.servers_client = ServersClient(*client_args)
|
|
||||||
self.flavors_client = FlavorsClient(*client_args)
|
|
||||||
self.images_client = ImagesClient(*client_args)
|
|
||||||
self.limits_client = LimitsClient(*client_args)
|
|
||||||
self.extensions_client = ExtensionsClient(*client_args)
|
|
||||||
self.keypairs_client = KeyPairsClient(*client_args)
|
|
||||||
self.security_groups_client = SecurityGroupsClient(*client_args)
|
|
||||||
self.floating_ips_client = FloatingIPsClient(*client_args)
|
|
||||||
self.volumes_extensions_client = VolumesExtensionsClient(*client_args)
|
|
||||||
self.volumes_client = VolumesClient(*client_args)
|
|
||||||
self.snapshots_client = SnapshotsClient(*client_args)
|
|
||||||
self.quotas_client = QuotasClient(*client_args)
|
|
||||||
self.network_client = NetworkClient(*client_args)
|
|
||||||
self.hypervisor_client = HypervisorClient(*client_args)
|
|
||||||
|
|
||||||
|
|
||||||
class ComputeFuzzClientAltManager(Manager):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Manager object that uses the alt_XXX credentials for its
|
|
||||||
managed client objects
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
conf = tempest.config.TempestConfig()
|
|
||||||
super(ComputeFuzzClientAltManager, self).__init__(
|
|
||||||
conf.identity.alt_username,
|
|
||||||
conf.identity.alt_password,
|
|
||||||
conf.identity.alt_tenant_name)
|
|
||||||
|
|
||||||
|
|
||||||
class ComputeFuzzClientAdminManager(Manager):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Manager object that uses the alt_XXX credentials for its
|
|
||||||
managed client objects
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
conf = tempest.config.TempestConfig()
|
|
||||||
super(ComputeFuzzClientAdminManager, self).__init__(
|
|
||||||
conf.compute_admin.username,
|
|
||||||
conf.compute_admin.password,
|
|
||||||
conf.compute_admin.tenant_name)
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ from tempest.common import log as logging
|
||||||
from tempest.common.utils.data_utils import rand_name
|
from tempest.common.utils.data_utils import rand_name
|
||||||
from tempest import config
|
from tempest import config
|
||||||
from tempest import exceptions
|
from tempest import exceptions
|
||||||
from tempest import manager
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -247,19 +246,22 @@ class TestCase(BaseTestCase):
|
||||||
cls.resource_keys = {}
|
cls.resource_keys = {}
|
||||||
cls.os_resources = []
|
cls.os_resources = []
|
||||||
|
|
||||||
def set_resource(self, key, thing):
|
@classmethod
|
||||||
|
def set_resource(cls, key, thing):
|
||||||
LOG.debug("Adding %r to shared resources of %s" %
|
LOG.debug("Adding %r to shared resources of %s" %
|
||||||
(thing, self.__class__.__name__))
|
(thing, cls.__name__))
|
||||||
self.resource_keys[key] = thing
|
cls.resource_keys[key] = thing
|
||||||
self.os_resources.append(thing)
|
cls.os_resources.append(thing)
|
||||||
|
|
||||||
def get_resource(self, key):
|
@classmethod
|
||||||
return self.resource_keys[key]
|
def get_resource(cls, key):
|
||||||
|
return cls.resource_keys[key]
|
||||||
|
|
||||||
def remove_resource(self, key):
|
@classmethod
|
||||||
thing = self.resource_keys[key]
|
def remove_resource(cls, key):
|
||||||
self.os_resources.remove(thing)
|
thing = cls.resource_keys[key]
|
||||||
del self.resource_keys[key]
|
cls.os_resources.remove(thing)
|
||||||
|
del cls.resource_keys[key]
|
||||||
|
|
||||||
def status_timeout(self, things, thing_id, expected_status):
|
def status_timeout(self, things, thing_id, expected_status):
|
||||||
"""
|
"""
|
||||||
|
@ -289,13 +291,3 @@ class TestCase(BaseTestCase):
|
||||||
conf.compute.build_interval):
|
conf.compute.build_interval):
|
||||||
self.fail("Timed out waiting for thing %s to become %s"
|
self.fail("Timed out waiting for thing %s to become %s"
|
||||||
% (thing_id, expected_status))
|
% (thing_id, expected_status))
|
||||||
|
|
||||||
|
|
||||||
class ComputeFuzzClientTest(TestCase):
|
|
||||||
|
|
||||||
"""
|
|
||||||
Base test case class for OpenStack Compute API (Nova)
|
|
||||||
that uses the Tempest REST fuzz client libs for calling the API.
|
|
||||||
"""
|
|
||||||
|
|
||||||
manager_class = manager.ComputeFuzzClientManager
|
|
||||||
|
|
|
@ -21,12 +21,11 @@ import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from sqlalchemy import create_engine, MetaData
|
from sqlalchemy import create_engine, MetaData
|
||||||
|
|
||||||
from tempest.common import log as logging
|
from tempest.common import log as logging
|
||||||
from tempest.common.ssh import Client
|
from tempest.common.ssh import Client
|
||||||
from tempest.common.utils.data_utils import rand_name
|
from tempest.common.utils.data_utils import rand_name
|
||||||
from tempest import exceptions
|
from tempest import exceptions
|
||||||
from tempest import test
|
from tempest.scenario import manager
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -47,7 +46,7 @@ class WhiteboxTest(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ComputeWhiteboxTest(test.ComputeFuzzClientTest, WhiteboxTest):
|
class ComputeWhiteboxTest(manager.OfficialClientTest):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Base smoke test case class for OpenStack Compute API (Nova)
|
Base smoke test case class for OpenStack Compute API (Nova)
|
||||||
|
@ -64,15 +63,6 @@ class ComputeWhiteboxTest(test.ComputeFuzzClientTest, WhiteboxTest):
|
||||||
cls.nova_dir = cls.config.whitebox.source_dir
|
cls.nova_dir = cls.config.whitebox.source_dir
|
||||||
cls.compute_bin_dir = cls.config.whitebox.bin_dir
|
cls.compute_bin_dir = cls.config.whitebox.bin_dir
|
||||||
cls.compute_config_path = cls.config.whitebox.config_path
|
cls.compute_config_path = cls.config.whitebox.config_path
|
||||||
cls.servers_client = cls.manager.servers_client
|
|
||||||
cls.images_client = cls.manager.images_client
|
|
||||||
cls.flavors_client = cls.manager.flavors_client
|
|
||||||
cls.extensions_client = cls.manager.extensions_client
|
|
||||||
cls.floating_ips_client = cls.manager.floating_ips_client
|
|
||||||
cls.keypairs_client = cls.manager.keypairs_client
|
|
||||||
cls.security_groups_client = cls.manager.security_groups_client
|
|
||||||
cls.limits_client = cls.manager.limits_client
|
|
||||||
cls.volumes_client = cls.manager.volumes_client
|
|
||||||
cls.build_interval = cls.config.compute.build_interval
|
cls.build_interval = cls.config.compute.build_interval
|
||||||
cls.build_timeout = cls.config.compute.build_timeout
|
cls.build_timeout = cls.config.compute.build_timeout
|
||||||
cls.ssh_user = cls.config.compute.ssh_user
|
cls.ssh_user = cls.config.compute.ssh_user
|
||||||
|
@ -80,38 +70,27 @@ class ComputeWhiteboxTest(test.ComputeFuzzClientTest, WhiteboxTest):
|
||||||
cls.image_ref_alt = cls.config.compute.image_ref_alt
|
cls.image_ref_alt = cls.config.compute.image_ref_alt
|
||||||
cls.flavor_ref = cls.config.compute.flavor_ref
|
cls.flavor_ref = cls.config.compute.flavor_ref
|
||||||
cls.flavor_ref_alt = cls.config.compute.flavor_ref_alt
|
cls.flavor_ref_alt = cls.config.compute.flavor_ref_alt
|
||||||
cls.servers = []
|
|
||||||
|
|
||||||
|
#NOTE(afazekas): Mimics the helper method used in the api tests
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def create_server(cls, **kwargs):
|
||||||
# NOTE(jaypipes): Tests often add things in a particular order
|
flavor_ref = cls.config.compute.flavor_ref
|
||||||
# so we destroy resources in the reverse order in which resources
|
image_ref = cls.config.compute.image_ref
|
||||||
# are added to the test class object
|
name = rand_name(cls.__name__ + "-instance")
|
||||||
if not cls.os_resources:
|
if 'name' in kwargs:
|
||||||
return
|
name = kwargs.pop('name')
|
||||||
thing = cls.os_resources.pop()
|
flavor = kwargs.get('flavor', flavor_ref)
|
||||||
while True:
|
image_id = kwargs.get('image_id', image_ref)
|
||||||
LOG.debug("Deleting %r from shared resources of %s" %
|
|
||||||
(thing, cls.__name__))
|
|
||||||
# Resources in novaclient all have a delete() method
|
|
||||||
# which destroys the resource...
|
|
||||||
thing.delete()
|
|
||||||
if not cls.os_resources:
|
|
||||||
return
|
|
||||||
thing = cls.os_resources.pop()
|
|
||||||
|
|
||||||
@classmethod
|
server = cls.compute_client.servers.create(
|
||||||
def create_server(cls, image_id=None):
|
name, image_id, flavor, **kwargs)
|
||||||
"""Wrapper utility that returns a test server."""
|
|
||||||
server_name = rand_name(cls.__name__ + "-instance")
|
|
||||||
flavor = cls.flavor_ref
|
|
||||||
if not image_id:
|
|
||||||
image_id = cls.image_ref
|
|
||||||
|
|
||||||
resp, server = cls.servers_client.create_server(
|
if 'wait_until' in kwargs:
|
||||||
server_name, image_id, flavor)
|
cls.status_timeout(cls.compute_client.servers, server.id,
|
||||||
cls.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
|
server['id'], kwargs['wait_until'])
|
||||||
cls.servers.append(server)
|
|
||||||
|
server = cls.compute_client.servers.get(server.id)
|
||||||
|
cls.set_resource(name, server)
|
||||||
return server
|
return server
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -15,23 +15,19 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from tempest.api.compute import base
|
|
||||||
from tempest.common.utils.data_utils import rand_name
|
from tempest.common.utils.data_utils import rand_name
|
||||||
from tempest import exceptions
|
|
||||||
from tempest.whitebox import manager
|
from tempest.whitebox import manager
|
||||||
|
|
||||||
#TODO(afazekas): The whitebox tests are using complex testclass/manager
|
from novaclient import exceptions
|
||||||
# hierarchy, without a real need. It is difficult to maintain.
|
|
||||||
# They could share more code with scenario tests.
|
|
||||||
|
|
||||||
|
|
||||||
class ImagesWhiteboxTest(manager.ComputeWhiteboxTest, base.BaseComputeTest):
|
class ImagesWhiteboxTest(manager.ComputeWhiteboxTest):
|
||||||
_interface = 'json'
|
_interface = 'json'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super(ImagesWhiteboxTest, cls).setUpClass()
|
super(ImagesWhiteboxTest, cls).setUpClass()
|
||||||
cls.client = cls.images_client
|
cls.create_image = cls.compute_client.servers.create_image
|
||||||
cls.connection, cls.meta = cls.get_db_handle_and_meta()
|
cls.connection, cls.meta = cls.get_db_handle_and_meta()
|
||||||
cls.shared_server = cls.create_server()
|
cls.shared_server = cls.create_server()
|
||||||
cls.image_ids = []
|
cls.image_ids = []
|
||||||
|
@ -39,7 +35,6 @@ class ImagesWhiteboxTest(manager.ComputeWhiteboxTest, base.BaseComputeTest):
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
"""Delete images and server after a test is executed."""
|
"""Delete images and server after a test is executed."""
|
||||||
cls.servers_client.delete_server(cls.shared_server['id'])
|
|
||||||
for image_id in cls.image_ids:
|
for image_id in cls.image_ids:
|
||||||
cls.client.delete_image(image_id)
|
cls.client.delete_image(image_id)
|
||||||
cls.image_ids.remove(image_id)
|
cls.image_ids.remove(image_id)
|
||||||
|
@ -62,18 +57,18 @@ class ImagesWhiteboxTest(manager.ComputeWhiteboxTest, base.BaseComputeTest):
|
||||||
def _test_create_image_409_base(self, vm_state, task_state, deleted=0):
|
def _test_create_image_409_base(self, vm_state, task_state, deleted=0):
|
||||||
"""Base method for create image tests based on vm and task states."""
|
"""Base method for create image tests based on vm and task states."""
|
||||||
try:
|
try:
|
||||||
self.update_state(self.shared_server['id'], vm_state,
|
self.update_state(self.shared_server.id, vm_state,
|
||||||
task_state, deleted)
|
task_state, deleted)
|
||||||
|
|
||||||
image_name = rand_name('snap-')
|
image_name = rand_name('snap-')
|
||||||
self.assertRaises(exceptions.Duplicate,
|
self.assertRaises(exceptions.Conflict,
|
||||||
self.client.create_image,
|
self.create_image,
|
||||||
self.shared_server['id'], image_name)
|
self.shared_server.id, image_name)
|
||||||
except Exception:
|
except Exception:
|
||||||
self.fail("Should not allow create image when vm_state=%s and "
|
self.fail("Should not allow create image when vm_state=%s and "
|
||||||
"task_state=%s" % (vm_state, task_state))
|
"task_state=%s" % (vm_state, task_state))
|
||||||
finally:
|
finally:
|
||||||
self.update_state(self.shared_server['id'], 'active', None)
|
self.update_state(self.shared_server.id, 'active', None)
|
||||||
|
|
||||||
def test_create_image_when_vm_eq_building_task_eq_scheduling(self):
|
def test_create_image_when_vm_eq_building_task_eq_scheduling(self):
|
||||||
# 409 error when instance states are building,scheduling
|
# 409 error when instance states are building,scheduling
|
||||||
|
|
Loading…
Reference in New Issue