Merge "Fix test_get_service_by_invalid_params for microversion 2.75"
diff --git a/releasenotes/notes/account-generator-accepts-positive-numbers-only-33a366a297494ef7.yaml b/releasenotes/notes/account-generator-accepts-positive-numbers-only-33a366a297494ef7.yaml
new file mode 100644
index 0000000..dfee1db
--- /dev/null
+++ b/releasenotes/notes/account-generator-accepts-positive-numbers-only-33a366a297494ef7.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - |
+ Concurrency parameter for account-generator command was accepting
+ negative values and zero. The concurrency parameter now accepts only
+ positive numbers. When a negative value or zero is passed to the
+ program then the program ends and help is displayed.
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 322579c..bdcb5ae 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -123,7 +123,7 @@
self.assertEqual(object_content, obj_name[::-1].encode())
@decorators.attr(type='slow')
- @decorators.skip_because(bug='1317133')
+ @decorators.unstable_test(bug='1317133')
@decorators.idempotent_id('be008325-1bba-4925-b7dd-93b58f22ce9b')
@testtools.skipIf(
not CONF.object_storage_feature_enabled.container_sync,
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index bcbcf43..7af5927 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -233,12 +233,15 @@
return group
def delete_group(self, group_id, delete_volumes=True):
- self.groups_client.delete_group(group_id, delete_volumes)
+ group_vols = []
if delete_volumes:
vols = self.volumes_client.list_volumes(detail=True)['volumes']
for vol in vols:
if vol['group_id'] == group_id:
- self.volumes_client.wait_for_resource_deletion(vol['id'])
+ group_vols.append(vol['id'])
+ self.groups_client.delete_group(group_id, delete_volumes)
+ for vol in group_vols:
+ self.volumes_client.wait_for_resource_deletion(vol)
self.groups_client.wait_for_resource_deletion(group_id)
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index b230615..ff552a1 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -97,6 +97,7 @@
[OPTIONS] <accounts_file.yaml> -h``.
"""
+import argparse
import os
import traceback
@@ -199,6 +200,14 @@
LOG.info('%s generated successfully!', account_file)
+def positive_int(number):
+ number = int(number)
+ if number <= 0:
+ raise argparse.ArgumentTypeError("Concurrency value should be a "
+ "positive number")
+ return number
+
+
def _parser_add_args(parser):
parser.add_argument('-c', '--config-file',
metavar='/etc/tempest.conf',
@@ -228,7 +237,7 @@
help='Resources tag')
parser.add_argument('-r', '--concurrency',
default=1,
- type=int,
+ type=positive_int,
required=False,
dest='concurrency',
help='Concurrency count')
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index 3ceecda..6723516 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -206,7 +206,10 @@
def action(self, server_id, action_name,
schema=schema.server_actions_common_schema,
**kwargs):
- post_body = json.dumps({action_name: kwargs})
+ if 'body' in kwargs:
+ post_body = json.dumps(kwargs['body'])
+ else:
+ post_body = json.dumps({action_name: kwargs})
resp, body = self.post('servers/%s/action' % server_id,
post_body)
if body:
@@ -608,6 +611,15 @@
API reference:
https://docs.openstack.org/api-ref/compute/#unshelve-restore-shelved-server-unshelve-action
"""
+ # NOTE(gmann): pass None as request body if nothing is requested.
+ # Nova started the request body check since 2.77 microversion and only
+ # accept AZ or None as valid req body and reject the empty dict {}.
+ # Before 2.77 microverison anything is valid body as Nova does not
+ # check the request body but as per api-ref None is valid request
+ # body to pass so we do not need to check the requested microversion
+ # here and always default req body to None.
+ if not kwargs:
+ kwargs['body'] = {'unshelve': None}
return self.action(server_id, 'unshelve', **kwargs)
def shelve_offload_server(self, server_id, **kwargs):
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index d8584ec..f466729 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -297,9 +297,19 @@
ip_mask = CONF.network.project_network_mask_bits
# check if the address is not already in use, if not, set it
if ' ' + ip_address + '/' + str(ip_mask) not in ip_output:
- ssh_client.exec_command("sudo ip addr add %s/%s dev %s" % (
- ip_address, ip_mask, new_nic))
- ssh_client.exec_command("sudo ip link set %s up" % new_nic)
+ try:
+ ssh_client.exec_command("sudo ip addr add %s/%s dev %s" % (
+ ip_address, ip_mask, new_nic))
+ ssh_client.exec_command("sudo ip link set %s up" % new_nic)
+ except exceptions.SSHExecCommandFailed as exc:
+ if 'RTNETLINK answers: File exists' in str(exc):
+ LOG.debug(
+ 'IP address %(ip_address)s is already set in device '
+ '%(device)s\nPrevious "ip a" output: %(ip_output)s',
+ {'ip_address': ip_address, 'device': new_nic,
+ 'ip_output': ip_output})
+ else:
+ raise exc
def _get_server_nics(self, ssh_client):
reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+)[@]?.*:')
diff --git a/tempest/tests/cmd/test_account_generator.py b/tempest/tests/cmd/test_account_generator.py
index d15cd26..7d764be 100644
--- a/tempest/tests/cmd/test_account_generator.py
+++ b/tempest/tests/cmd/test_account_generator.py
@@ -337,3 +337,24 @@
def setUp(self):
self.mock_domains()
super(TestDumpAccountsV3, self).setUp()
+
+
+class TestAccountGeneratorCliCheck(base.TestCase):
+
+ def setUp(self):
+ super(TestAccountGeneratorCliCheck, self).setUp()
+ self.account_generator = account_generator.TempestAccountGenerator(
+ app=mock.Mock(), app_args=mock.Mock())
+ self.parser = self.account_generator.get_parser("generator")
+
+ def test_account_generator_zero_concurrency(self):
+ error = self.assertRaises(
+ SystemExit, lambda: self.parser.parse_args(
+ ['-r', '0', 'accounts_file.yaml']))
+ self.assertTrue(error.code != 0)
+
+ def test_account_generator_negative_concurrency(self):
+ error = self.assertRaises(
+ SystemExit, lambda: self.parser.parse_args(
+ ['-r', '-1', 'accounts_file.yaml']))
+ self.assertTrue(error.code != 0)
diff --git a/tools/generate-tempest-plugins-list.py b/tools/generate-tempest-plugins-list.py
index 5ffef3e..530ce5e 100644
--- a/tools/generate-tempest-plugins-list.py
+++ b/tools/generate-tempest-plugins-list.py
@@ -52,6 +52,8 @@
'x/tap-as-a-service', # To avoid sanity-job failure
'x/valet', # https://review.opendev.org/#/c/638339/
'x/kingbird', # https://bugs.launchpad.net/kingbird/+bug/1869722
+ # vmware-nsx is blacklisted since https://review.opendev.org/#/c/736952
+ 'x/vmware-nsx-tempest-plugin',
]
url = 'https://review.opendev.org/projects/'
diff --git a/tools/tempest-plugin-sanity.sh b/tools/tempest-plugin-sanity.sh
index 2ff4aea..c983da9 100644
--- a/tools/tempest-plugin-sanity.sh
+++ b/tools/tempest-plugin-sanity.sh
@@ -66,7 +66,7 @@
# function to create virtualenv to perform sanity operation
function prepare_workspace {
SANITY_DIR=$(pwd)
- virtualenv -p python3 --clear "$SANITY_DIR"/.venv
+ python3 -m venv "$SANITY_DIR"/.venv
export TVENV="$SANITY_DIR/tools/with_venv.sh"
cd "$SANITY_DIR"