Merge "Orchestration tests to use admin user, demo tenant."
diff --git a/HACKING.rst b/HACKING.rst
index 1db1e26..d69f935 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -157,6 +157,52 @@
kwarg2=dict_of_numbers)
+Exception Handling
+------------------
+According to the ``The Zen of Python`` the
+ ``Errors should never pass silently.``
+Tempest usually runs in special environment (jenkins gate jobs), in every
+error or failure situation we should provide as much error related
+information as possible, because we usually do not have the chance to
+investigate the situation after the issue happened.
+
+In every test case the abnormal situations must be very verbosely explained,
+by the exception and the log.
+
+In most cases the very first issue is the most important information.
+
+Try to avoid using ``try`` blocks in the test cases, both the ``except``
+and ``finally`` block could replace the original exception,
+when the additional operations leads to another exception.
+
+Just letting an exception to propagate, is not bad idea in a test case,
+ at all.
+
+Try to avoid using any exception handling construct which can hide the errors
+origin.
+
+If you really need to use a ``try`` block, please ensure the original
+exception at least logged. When the exception is logged you usually need
+to ``raise`` the same or a different exception anyway.
+
+Use the ``self.assert*`` methods provided by the unit test framework
+ the signal failures early.
+
+Avoid using the ``self.fail`` alone, it's stack trace will signal
+ the ``self.fail`` line as the origin of the error.
+
+Avoid constructing complex boolean expressions for assertion.
+The ``self.assertTrue`` or ``self.assertFalse`` will just tell you the
+single boolean, and you will not know anything about the values used in
+the formula. Most other assert method can include more information.
+For example ``self.assertIn`` can include the whole set.
+
+If the test case fails you can see the related logs and the information
+carried by the exception (exception class, backtrack and exception info).
+This and the service logs are your only guide to find the root cause of flaky
+issue.
+
+
Test Skips
----------
If a test is broken because of a bug it is appropriate to skip the test until
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 0af8e9b..12aa399 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -181,9 +181,9 @@
# This section contains configuration options used when executing tests
# against the OpenStack Network API.
-# Version of the Quantum API
+# Version of the Neutron API
api_version = v1.1
-# Catalog type of the Quantum Service
+# Catalog type of the Neutron Service
catalog_type = network
# A large private cidr block from which to allocate smaller blocks for
@@ -206,8 +206,8 @@
# for each tenant to have their own router.
public_router_id = {$PUBLIC_ROUTER_ID}
-# Whether or not quantum is expected to be available
-quantum_available = false
+# Whether or not neutron is expected to be available
+neutron_available = false
[volume]
# This section contains the configuration options used when executing tests
diff --git a/requirements.txt b/requirements.txt
index 606d7ae..b3c706b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -11,7 +11,7 @@
python-glanceclient>=0.5.0
python-keystoneclient>=0.2.0
python-novaclient>=2.10.0
-python-quantumclient>=2.1
+python-neutronclient>=2.2.3,<3.0.0
python-cinderclient>=1.0.4,<2
testresources
keyring
diff --git a/tempest/api/compute/admin/test_fixed_ips.py b/tempest/api/compute/admin/test_fixed_ips.py
index 34f96ba..2eaf3b0 100644
--- a/tempest/api/compute/admin/test_fixed_ips.py
+++ b/tempest/api/compute/admin/test_fixed_ips.py
@@ -56,8 +56,8 @@
CONF = config.TempestConfig()
- @testtools.skipIf(CONF.network.quantum_available, "This feature is not" +
- "implemented by Quantum. See bug: #1194569")
+ @testtools.skipIf(CONF.network.neutron_available, "This feature is not" +
+ "implemented by Neutron. See bug: #1194569")
@attr(type='gate')
def test_list_fixed_ip_details(self):
resp, fixed_ip = self.client.get_fixed_ip_details(self.ip)
diff --git a/tempest/api/compute/admin/test_hosts.py b/tempest/api/compute/admin/test_hosts.py
new file mode 100644
index 0000000..a47e6c9
--- /dev/null
+++ b/tempest/api/compute/admin/test_hosts.py
@@ -0,0 +1,76 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 IBM Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.api.compute import base
+from tempest import exceptions
+from tempest.test import attr
+
+
+class HostsAdminTestJSON(base.BaseComputeAdminTest):
+
+ """
+ Tests hosts API using admin privileges.
+ """
+
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(HostsAdminTestJSON, cls).setUpClass()
+ cls.client = cls.os_adm.hosts_client
+ cls.non_admin_client = cls.os.hosts_client
+
+ @attr(type=['positive', 'gate'])
+ def test_list_hosts(self):
+ resp, hosts = self.client.list_hosts()
+ self.assertEqual(200, resp.status)
+ self.assertTrue(len(hosts) >= 2)
+
+ @attr(type='positive')
+ def test_list_hosts_with_zone(self):
+ resp, hosts = self.client.list_hosts()
+ host = hosts[0]
+ zone_name = host['zone']
+ params = {'zone': zone_name}
+ resp, hosts = self.client.list_hosts(params)
+ self.assertEqual(200, resp.status)
+ self.assertTrue(len(hosts) >= 1)
+ self.assertTrue(host in hosts)
+
+ @attr(type='negative')
+ def test_list_hosts_with_non_existent_zone(self):
+ params = {'zone': 'xxx'}
+ resp, hosts = self.client.list_hosts(params)
+ self.assertEqual(0, len(hosts))
+ self.assertEqual(200, resp.status)
+
+ @attr(type='negative')
+ def test_list_hosts_with_a_blank_zone(self):
+ # If send the request with a blank zone, the request will be successful
+ # and it will return all the hosts list
+ params = {'zone': ''}
+ resp, hosts = self.client.list_hosts(params)
+ self.assertNotEqual(0, len(hosts))
+ self.assertEqual(200, resp.status)
+
+ @attr(type=['negative', 'gate'])
+ def test_list_hosts_with_non_admin_user(self):
+ self.assertRaises(exceptions.Unauthorized,
+ self.non_admin_client.list_hosts)
+
+
+class HostsAdminTestXML(HostsAdminTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index 12c646d..e105121 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -158,8 +158,8 @@
self.client.create_security_group, s_name,
s_description)
- @testtools.skipIf(config.TempestConfig().network.quantum_available,
- "Quantum allows duplicate names for security groups")
+ @testtools.skipIf(config.TempestConfig().network.neutron_available,
+ "Neutron allows duplicate names for security groups")
@attr(type=['negative', 'gate'])
def test_security_group_create_with_duplicate_name(self):
# Negative test:Security Group with duplicate name should not
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 113ac78..de095c5 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -24,8 +24,8 @@
@classmethod
def setUpClass(cls):
- if not cls.config.network.quantum_available:
- raise cls.skipException("Quantum is required")
+ if not cls.config.network.neutron_available:
+ raise cls.skipException("Neutron is required")
super(AttachInterfacesTestJSON, cls).setUpClass()
cls.client = cls.os.interfaces_client
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 5f53080..5cc8dc6 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -24,12 +24,12 @@
from tempest.test import attr
-class ServersNegativeTest(base.BaseComputeTest):
+class ServersNegativeTestJSON(base.BaseComputeTest):
_interface = 'json'
@classmethod
def setUpClass(cls):
- super(ServersNegativeTest, cls).setUpClass()
+ super(ServersNegativeTestJSON, cls).setUpClass()
cls.client = cls.servers_client
cls.img_client = cls.images_client
cls.alt_os = clients.AltManager()
@@ -248,5 +248,5 @@
'999erra43')
-class ServersNegativeTestXML(ServersNegativeTest):
+class ServersNegativeTestXML(ServersNegativeTestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index 9073aeb..35f0fc0 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -37,8 +37,8 @@
resp, server = cls.create_server(wait_until='ACTIVE')
cls.server_id = server['id']
- @testtools.skipIf(CONF.network.quantum_available, "This feature is not " +
- "implemented by Quantum. See bug: #1183436")
+ @testtools.skipIf(CONF.network.neutron_available, "This feature is not " +
+ "implemented by Neutron. See bug: #1183436")
@attr(type='gate')
def test_list_virtual_interfaces(self):
# Positive test:Should be able to GET the virtual interfaces list
diff --git a/tempest/api/identity/admin/test_users.py b/tempest/api/identity/admin/test_users.py
index c029300..0bba250 100644
--- a/tempest/api/identity/admin/test_users.py
+++ b/tempest/api/identity/admin/test_users.py
@@ -15,7 +15,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import testtools
from testtools.matchers._basic import Contains
from tempest.api.identity import base
@@ -77,32 +76,6 @@
self.data.test_user, self.data.test_password,
self.data.tenant['id'], self.data.test_email)
- @testtools.skip("Until Bug #999084 is fixed")
- @attr(type=['negative', 'gate'])
- def test_create_user_with_empty_password(self):
- # User with an empty password should not be created
- self.data.setup_test_tenant()
- self.assertRaises(exceptions.BadRequest, self.client.create_user,
- self.alt_user, '', self.data.tenant['id'],
- self.alt_email)
-
- @testtools.skip("Until Bug #999084 is fixed")
- @attr(type=['negative', 'gate'])
- def test_create_user_with_long_password(self):
- # User having password exceeding max length should not be created
- self.data.setup_test_tenant()
- self.assertRaises(exceptions.BadRequest, self.client.create_user,
- self.alt_user, 'a' * 65, self.data.tenant['id'],
- self.alt_email)
-
- @testtools.skip("Until Bug #999084 is fixed")
- @attr(type=['negative', 'gate'])
- def test_create_user_with_invalid_email_format(self):
- # Email format should be validated while creating a user
- self.data.setup_test_tenant()
- self.assertRaises(exceptions.BadRequest, self.client.create_user,
- self.alt_user, '', self.data.tenant['id'], '12345')
-
@attr(type=['negative', 'gate'])
def test_create_user_for_non_existant_tenant(self):
# Attempt to create a user in a non-existent tenant should fail
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 03e73df..3b7f9dd 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -26,11 +26,11 @@
class BaseNetworkTest(tempest.test.BaseTestCase):
"""
- Base class for the Quantum tests that use the Tempest Quantum REST client
+ Base class for the Neutron tests that use the Tempest Neutron REST client
- Per the Quantum API Guide, API v1.x was removed from the source code tree
+ Per the Neutron API Guide, API v1.x was removed from the source code tree
(docs.openstack.org/api/openstack-network/2.0/content/Overview-d1e71.html)
- Therefore, v2.x of the Quantum API is assumed. It is also assumed that the
+ Therefore, v2.x of the Neutron API is assumed. It is also assumed that the
following options are defined in the [network] section of etc/tempest.conf:
tenant_network_cidr with a block of cidr's from which smaller blocks
@@ -44,8 +44,8 @@
def setUpClass(cls):
os = clients.Manager()
cls.network_cfg = os.config.network
- if not cls.network_cfg.quantum_available:
- raise cls.skipException("Quantum support is required")
+ if not cls.network_cfg.neutron_available:
+ raise cls.skipException("Neutron support is required")
cls.client = os.network_client
cls.networks = []
cls.subnets = []
diff --git a/tempest/api/network/common.py b/tempest/api/network/common.py
index 22eb1d3..c3fb821 100644
--- a/tempest/api/network/common.py
+++ b/tempest/api/network/common.py
@@ -32,7 +32,7 @@
class DeletableResource(AttributeDict):
"""
- Support deletion of quantum resources (networks, subnets) via a
+ Support deletion of neutron resources (networks, subnets) via a
delete() method, as is supported by keystone and nova resources.
"""
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 1f45f92..4481853 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -26,8 +26,8 @@
class NetworksTest(base.BaseNetworkTest):
"""
- Tests the following operations in the Quantum API using the REST client for
- Quantum:
+ Tests the following operations in the Neutron API using the REST client for
+ Neutron:
create a network for a tenant
list tenant's networks
@@ -36,7 +36,7 @@
list tenant's subnets
show a tenant subnet details
- v2.0 of the Quantum API is assumed. It is also assumed that the following
+ v2.0 of the Neutron API is assumed. It is also assumed that the following
options are defined in the [network] section of etc/tempest.conf:
tenant_network_cidr with a block of cidr's from which smaller blocks
diff --git a/tempest/config.py b/tempest/config.py
index 8795b33..96b144c 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -15,9 +15,12 @@
# License for the specific language governing permissions and limitations
# under the License.
+from __future__ import print_function
+
import os
import sys
+
from oslo.config import cfg
from tempest.common import log as logging
@@ -277,7 +280,7 @@
NetworkGroup = [
cfg.StrOpt('catalog_type',
default='network',
- help='Catalog type of the Quantum service.'),
+ help='Catalog type of the Neutron service.'),
cfg.StrOpt('tenant_network_cidr',
default="10.100.0.0/16",
help="The cidr block to allocate tenant networks from"),
@@ -296,9 +299,9 @@
default="",
help="Id of the public router that provides external "
"connectivity"),
- cfg.BoolOpt('quantum_available',
+ cfg.BoolOpt('neutron_available',
default=False,
- help="Whether or not quantum is expected to be available"),
+ help="Whether or not neutron is expected to be available"),
]
@@ -559,7 +562,7 @@
if not os.path.exists(path):
msg = "Config file %(path)s not found" % locals()
- print >> sys.stderr, RuntimeError(msg)
+ print(RuntimeError(msg), file=sys.stderr)
else:
config_files.append(path)
diff --git a/tempest/hacking/checks.py b/tempest/hacking/checks.py
index 5e941da..f9eb968 100644
--- a/tempest/hacking/checks.py
+++ b/tempest/hacking/checks.py
@@ -17,7 +17,7 @@
import re
-PYTHON_CLIENTS = ['cinder', 'glance', 'keystone', 'nova', 'swift', 'quantum']
+PYTHON_CLIENTS = ['cinder', 'glance', 'keystone', 'nova', 'swift', 'neutron']
SKIP_DECORATOR_RE = re.compile(r'\s*@testtools.skip\((.*)\)')
SKIP_STR_RE = re.compile(r'.*Bug #\d+.*')
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 366ff43..e3a23bb 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -24,9 +24,9 @@
import glanceclient
import keystoneclient.v2_0.client
import netaddr
+from neutronclient.common import exceptions as exc
+import neutronclient.v2_0.client
import novaclient.client
-from quantumclient.common import exceptions as exc
-import quantumclient.v2_0.client
from tempest.api.network import common as net_common
@@ -166,7 +166,7 @@
auth_url = self.config.identity.uri
dscv = self.config.identity.disable_ssl_certificate_validation
- return quantumclient.v2_0.client.Client(username=username,
+ return neutronclient.v2_0.client.Client(username=username,
password=password,
tenant_name=tenant_name,
auth_url=auth_url,
@@ -236,9 +236,9 @@
@classmethod
def check_preconditions(cls):
- if (cls.config.network.quantum_available):
+ if (cls.config.network.neutron_available):
cls.enabled = True
- #verify that quantum_available is telling the truth
+ #verify that neutron_available is telling the truth
try:
cls.network_client.list_networks()
except exc.EndpointNotFound:
@@ -246,7 +246,7 @@
raise
else:
cls.enabled = False
- msg = 'Quantum not available'
+ msg = 'Neutron not available'
raise cls.skipException(msg)
@classmethod
@@ -358,7 +358,7 @@
try:
result = self.network_client.create_subnet(body=body)
break
- except exc.QuantumClientException as e:
+ except exc.NeutronClientException as e:
is_overlapping_cidr = 'overlaps with another subnet' in str(e)
if not is_overlapping_cidr:
raise
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index b94caaa..390e004 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -26,7 +26,7 @@
"""
This smoke test suite assumes that Nova has been configured to
- boot VM's with Quantum-managed networking, and attempts to
+ boot VM's with Neutron-managed networking, and attempts to
verify network connectivity as follows:
* For a freshly-booted VM with an IP address ("port") on a given network:
diff --git a/tempest/scenario/test_network_quotas.py b/tempest/scenario/test_network_quotas.py
index 8c3af73..267aff6 100644
--- a/tempest/scenario/test_network_quotas.py
+++ b/tempest/scenario/test_network_quotas.py
@@ -15,7 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from quantumclient.common import exceptions as exc
+from neutronclient.common import exceptions as exc
from tempest.scenario.manager import NetworkScenarioTest
MAX_REASONABLE_ITERATIONS = 51 # more than enough. Default for port is 50.
@@ -48,7 +48,7 @@
self.networks.append(
self._create_network(self.tenant_id,
namestart='network-quotatest-'))
- except exc.QuantumClientException as e:
+ except exc.NeutronClientException as e:
if (e.status_code != 409):
raise
hit_limit = True
@@ -66,7 +66,7 @@
self.subnets.append(
self._create_subnet(self.networks[0],
namestart='subnet-quotatest-'))
- except exc.QuantumClientException as e:
+ except exc.NeutronClientException as e:
if (e.status_code != 409):
raise
hit_limit = True
@@ -84,7 +84,7 @@
self.ports.append(
self._create_port(self.networks[0],
namestart='port-quotatest-'))
- except exc.QuantumClientException as e:
+ except exc.NeutronClientException as e:
if (e.status_code != 409):
raise
hit_limit = True
diff --git a/tempest/services/compute/json/hosts_client.py b/tempest/services/compute/json/hosts_client.py
index dc3c524..8093d19 100644
--- a/tempest/services/compute/json/hosts_client.py
+++ b/tempest/services/compute/json/hosts_client.py
@@ -1,4 +1,21 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013 IBM Corp.
+#
+# 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 json
+import urllib
from tempest.common.rest_client import RestClient
@@ -10,10 +27,13 @@
auth_url, tenant_name)
self.service = self.config.compute.catalog_type
- def list_hosts(self):
+ def list_hosts(self, params=None):
"""Lists all hosts."""
url = 'os-hosts'
+ if params:
+ url += '?%s' % urllib.urlencode(params)
+
resp, body = self.get(url)
body = json.loads(body)
return resp, body['hosts']
diff --git a/tempest/services/compute/xml/hosts_client.py b/tempest/services/compute/xml/hosts_client.py
new file mode 100644
index 0000000..70aeb48
--- /dev/null
+++ b/tempest/services/compute/xml/hosts_client.py
@@ -0,0 +1,41 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013 IBM Corp.
+#
+# 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 urllib
+
+from lxml import etree
+from tempest.common.rest_client import RestClientXML
+from tempest.services.compute.xml.common import xml_to_json
+
+
+class HostsClientXML(RestClientXML):
+
+ def __init__(self, config, username, password, auth_url, tenant_name=None):
+ super(HostsClientXML, self).__init__(config, username, password,
+ auth_url, tenant_name)
+ self.service = self.config.compute.catalog_type
+
+ def list_hosts(self, params=None):
+ """Lists all hosts."""
+
+ url = 'os-hosts'
+ if params:
+ url += '?%s' % urllib.urlencode(params)
+
+ resp, body = self.get(url, self.headers)
+ node = etree.fromstring(body)
+ body = [xml_to_json(x) for x in node.getchildren()]
+ return resp, body
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 4758ddd..c4fe6b1 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -5,10 +5,10 @@
class NetworkClient(RestClient):
"""
- Tempest REST client for Quantum. Uses v2 of the Quantum API, since the
+ Tempest REST client for Neutron. Uses v2 of the Neutron API, since the
V1 API has been removed from the code base.
- Implements the following operations for each one of the basic Quantum
+ Implements the following operations for each one of the basic Neutron
abstractions (networks, sub-networks and ports):
create
diff --git a/test-requirements.txt b/test-requirements.txt
index 3912695..2185997 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -3,7 +3,6 @@
pyflakes==0.7.2
flake8==2.0
hacking>=0.5.3,<0.6
-psycopg2
# needed for doc build
sphinx>=1.1.2
diff --git a/tox.ini b/tox.ini
index caa9403..964dbca 100644
--- a/tox.ini
+++ b/tox.ini
@@ -61,6 +61,14 @@
nosetests --logging-format '%(asctime)-15s %(message)s' --with-xunit --xunit-file=nosetests-full.xml -sv tempest/api tempest/scenario tempest/thirdparty tempest/cli
python -m tools/tempest_coverage -c report --html {posargs}
+[testenv:stress]
+sitepackages = True
+setenv = VIRTUAL_ENV={envdir}
+commands =
+ python -m tempest/stress/run_stress tempest/stress/etc/sample-test.json -d 60
+ python -m tempest/stress/run_stress tempest/stress/etc/volume-create-delete-test.json -d 60
+
+
[testenv:venv]
commands = {posargs}
deps = -r{toxinidir}/requirements.txt