Merge "Addresses lp#940832"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 22d9f7e..b63b077 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -24,6 +24,9 @@
build_timeout=600
catalog_type=compute
create_image_enabled=true
+# For resize to work with libvirt/kvm, one of the following must be true:
+# Single node: allow_resize_to_same_host=True must be set in nova.conf
+# Cluster: the 'nova' user must have scp access between cluster nodes
resize_available=true
[image]
diff --git a/stress/README.rst b/stress/README.rst
index 00e3b90..bf44f13 100644
--- a/stress/README.rst
+++ b/stress/README.rst
@@ -23,14 +23,15 @@
------------
This particular framework assumes your working Nova cluster understands Nova
API 2.0. The stress tests can read the logs from the cluster. To enable this
-you have to
-provide the private key and user name for ssh to the cluster in the
+you have to provide the hostname to call 'nova-manage' and
+the private key and user name for ssh to the cluster in the
[stress] section of tempest.conf. You also need to provide the
value of --logdir in nova.conf:
host_private_key_path=<path to private ssh key>
host_admin_user=<name of user for ssh command>
nova_logdir=<value of --logdir in nova.conf>
+ controller=<hostname for calling nova-manage>
The stress test needs the top-level tempest directory to be on PYTHONPATH
if you are not using nosetests to run.
diff --git a/stress/config.py b/stress/config.py
index 3f107af..0dce816 100755
--- a/stress/config.py
+++ b/stress/config.py
@@ -41,3 +41,8 @@
def nova_logdir(self):
"""Directory containing log files on the compute nodes"""
return self.get("nova_logdir", None)
+
+ @property
+ def controller(self):
+ """Controller host"""
+ return self.get("controller", None)
diff --git a/stress/test_servers.py b/stress/test_servers.py
index 3f62ac3..47d30b5 100644
--- a/stress/test_servers.py
+++ b/stress/test_servers.py
@@ -57,7 +57,8 @@
return None
_key_name = kwargs.get('key_name', '')
- _timeout = int(kwargs.get('timeout', 60))
+ _timeout = int(kwargs.get('timeout',
+ manager.config.compute.build_timeout))
_image_ref = kwargs.get('image_ref', manager.config.compute.image_ref)
_flavor_ref = kwargs.get('flavor_ref',
manager.config.compute.flavor_ref)
@@ -172,7 +173,7 @@
self._logger.info('no ACTIVE instances to delete')
return
- _timeout = kwargs.get('timeout', 600)
+ _timeout = kwargs.get('timeout', manager.config.compute.build_timeout)
target = random.choice(active_vms)
killtarget = target[0]
@@ -240,7 +241,7 @@
self._logger.info('no active instances to delete')
return
- _timeout = kwargs.get('timeout', 60)
+ _timeout = kwargs.get('timeout', manager.config.compute.build_timeout)
target = random.choice(vms)
killtarget = target[0]
@@ -276,7 +277,7 @@
self._logger.info('no active instances to update')
return
- _timeout = kwargs.get('timeout', 600)
+ _timeout = kwargs.get('timeout', manager.config.compute.build_timeout)
target = random.choice(active_vms)
update_target = target[0]
diff --git a/stress/tests/create_kill.py b/stress/tests/create_kill.py
index 1457279..752f72d 100644
--- a/stress/tests/create_kill.py
+++ b/stress/tests/create_kill.py
@@ -20,13 +20,8 @@
from tempest import openstack
choice_spec = [
- BasherAction(TestCreateVM(), 50,
- kargs={'timeout': '600',
- 'image_ref': 2,
- 'flavor_ref': 1}
- ),
- BasherAction(TestKillActiveVM(), 50,
- kargs={'timeout': '600'})
+ BasherAction(TestCreateVM(), 50),
+ BasherAction(TestKillActiveVM(), 50)
]
nova = openstack.Manager()
diff --git a/stress/tests/hard_reboots.py b/stress/tests/hard_reboots.py
index 503159e..f38ef6f 100644
--- a/stress/tests/hard_reboots.py
+++ b/stress/tests/hard_reboots.py
@@ -21,10 +21,9 @@
from tempest import openstack
choice_spec = [
- BasherAction(TestCreateVM(), 50,
- kargs={'timeout': '600'}),
+ BasherAction(TestCreateVM(), 50),
BasherAction(TestRebootVM(), 50,
- kargs={'type': 'HARD'}),
+ kargs={'type': 'HARD'})
]
nova = openstack.Manager()
diff --git a/stress/utils/util.py b/stress/utils/util.py
index aac6c26..ac8f062 100644
--- a/stress/utils/util.py
+++ b/stress/utils/util.py
@@ -32,6 +32,7 @@
def ssh(keypath, user, node, command, check=True):
+ command = 'sudo ' + command
command = "ssh %s %s@%s %s" % (get_ssh_options(keypath), user,
node, command)
popenargs = shlex.split(command)
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index d4ad014..ff27384 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -93,7 +93,8 @@
management_url = service_url + tenant_id
return token, management_url
elif resp.status == 401:
- raise exceptions.AuthenticationFailure(user=user, password=api_key)
+ raise exceptions.AuthenticationFailure(user=user,
+ password=password)
def post(self, url, body, headers):
return self.request('POST', url, headers, body)
diff --git a/tempest/openstack.py b/tempest/openstack.py
index 68d924c..69b4e3c 100644
--- a/tempest/openstack.py
+++ b/tempest/openstack.py
@@ -10,6 +10,7 @@
import SecurityGroupsClient
from tempest.services.nova.json.floating_ips_client import FloatingIPsClient
from tempest.services.nova.json.keypairs_client import KeyPairsClient
+from tempest.services.nova.json.volumes_client import VolumesClient
class Manager(object):
@@ -46,6 +47,7 @@
self.keypairs_client = KeyPairsClient(*client_args)
self.security_groups_client = SecurityGroupsClient(*client_args)
self.floating_ips_client = FloatingIPsClient(*client_args)
+ self.volumes_client = VolumesClient(*client_args)
class ServiceManager(object):
diff --git a/tempest/services/nova/json/volumes_client.py b/tempest/services/nova/json/volumes_client.py
new file mode 100644
index 0000000..95131f2
--- /dev/null
+++ b/tempest/services/nova/json/volumes_client.py
@@ -0,0 +1,36 @@
+from tempest.common import rest_client
+import json
+
+
+class VolumesClient(object):
+
+ def __init__(self, config, username, key, auth_url, tenant_name=None):
+ self.config = config
+ catalog_type = self.config.compute.catalog_type
+ self.client = rest_client.RestClient(config, username, key, auth_url,
+ catalog_type, tenant_name)
+
+ def list_volumes(self, params=None):
+ """List all the volumes created"""
+ url = 'os-volumes'
+ if params != None:
+ param_list = []
+ for param, value in params.iteritems():
+ param_list.append("%s=%s&" % (param, value))
+
+ url += '?' + ' '.join(param_list)
+
+ resp, body = self.client.get(url)
+ body = json.loads(body)
+ return resp, body['volumes']
+
+ def get_volume(self, volume_id):
+ """Returns the details of a single volume"""
+ url = "os-volumes/%s" % str(volume_id)
+ resp, body = self.client.get(url)
+ body = json.loads(body)
+ return resp, body['volume']
+
+ def delete_volume(self, volume_id):
+ """Deletes the Specified Volume"""
+ return self.client.delete("os-volumes/%s" % str(volume_id))
diff --git a/tempest/tests/image/test_images.py b/tempest/tests/image/test_images.py
index 70dec32..8f75f08 100644
--- a/tempest/tests/image/test_images.py
+++ b/tempest/tests/image/test_images.py
@@ -202,4 +202,4 @@
Simple test to see all fixture images returned
"""
images = self.client.get_images()
- self.assertEqual(10, len(images) - len(cls.original_images))
+ self.assertEqual(10, len(images) - len(self.original_images))
diff --git a/tempest/tests/test_images.py b/tempest/tests/test_images.py
index c422708..8217d2a 100644
--- a/tempest/tests/test_images.py
+++ b/tempest/tests/test_images.py
@@ -7,8 +7,8 @@
def _parse_image_id(image_ref):
- temp = image_ref.rsplit('/')
- return temp[6]
+ temp = image_ref.rsplit('images/')
+ return temp[1]
class ImagesTest(unittest.TestCase):
diff --git a/tempest/tests/test_volumes_negative.py b/tempest/tests/test_volumes_negative.py
new file mode 100644
index 0000000..83eef52
--- /dev/null
+++ b/tempest/tests/test_volumes_negative.py
@@ -0,0 +1,54 @@
+from nose.plugins.attrib import attr
+import unittest2 as unittest
+from tempest import openstack
+from tempest.common.utils.data_utils import rand_name
+from tempest import exceptions
+
+
+class VolumesTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.os = openstack.Manager()
+ cls.client = cls.os.volumes_client
+
+ @attr(type='negative')
+ def test_volume_get_nonexistant_volume_id(self):
+ """Negative: Should not be able to get details of nonexistant volume"""
+ #Creating a nonexistant volume id
+ volume_id_list = list()
+ resp, body = self.client.list_volumes()
+ for i in range(len(body)):
+ volume_id_list.append(body[i]['id'])
+ while True:
+ non_exist_id = rand_name('999')
+ if non_exist_id not in volume_id_list:
+ break
+ #Trying to GET a non existant volume
+ try:
+ resp, body = self.client.get_volume(non_exist_id)
+ except exceptions.NotFound:
+ pass
+ else:
+ self.fail('Should not be able to GET the details from a '
+ 'nonexistant volume')
+
+ @attr(type='negative')
+ def test_volume_delete_nonexistant_volume_id(self):
+ """Negative: Should not be able to delete nonexistant Volume"""
+ #Creating nonexistant volume id
+ volume_id_list = list()
+ resp, body = self.client.list_volumes()
+ for i in range(len(body)):
+ volume_id_list.append(body[i]['id'])
+ while True:
+ non_exist_id = rand_name('999')
+ if non_exist_id not in volume_id_list:
+ break
+ #Trying to DELETE a non existant volume
+ try:
+ resp, body = self.client.delete_volume(non_exist_id)
+ except exceptions.NotFound:
+ pass
+ else:
+ self.fail('Should not be able to DELETE a nonexistant volume')