Merge "compute: fix missing img_signature_uuid property"
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 2e5f706..36828e0 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -108,12 +108,12 @@
insufficient for certain use cases because of the admin credentials requirement
to create the credential sets on demand. To get around that the accounts.yaml
file was introduced and with that a new internal credential provider to enable
-using the list of credentials instead of creating them on demand. With locking
-test accounts each test class will reserve a set of credentials from the
-accounts.yaml before executing any of its tests so that each class is isolated
-like with dynamic credentials.
+using the list of credentials instead of creating them on demand. With
+pre-provisioned credentials (also known as locking test accounts) each test
+class will reserve a set of credentials from the accounts.yaml before executing
+any of its tests so that each class is isolated like with dynamic credentials.
-To enable and use locking test accounts you need do a few things:
+To enable and use pre-provisioned credentials you need do a few things:
#. Create an accounts.yaml file which contains the set of pre-existing
credentials to use for testing. To make sure you don't have a credentials
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index c8221c2..7cf26fb 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -47,6 +47,10 @@
def test_delete_saving_image(self):
server = self.create_test_server(wait_until='ACTIVE')
self.addCleanup(self.servers_client.delete_server, server['id'])
+ # wait for server active to avoid conflict when deleting server
+ # in task_state image_snapshot
+ self.addCleanup(waiters.wait_for_server_status, self.servers_client,
+ server['id'], 'ACTIVE')
image = self.create_image_from_server(server['id'],
wait_until='SAVING')
self.client.delete_image(image['id'])
diff --git a/tempest/api/identity/admin/v3/test_list_projects.py b/tempest/api/identity/admin/v3/test_list_projects.py
index 299a618..9022b2d 100644
--- a/tempest/api/identity/admin/v3/test_list_projects.py
+++ b/tempest/api/identity/admin/v3/test_list_projects.py
@@ -94,40 +94,43 @@
@classmethod
def resource_setup(cls):
super(ListProjectsStaticTestJSON, cls).resource_setup()
- cls.domain_id = CONF.identity.default_domain_id
- cls.project_ids = list()
- cls.p1_name = cls.os_primary.credentials.project_name
+ # Fetch an existing project from os_primary
cls.p1 = cls.projects_client.show_project(
cls.os_primary.credentials.project_id)['project']
- cls.project_ids.append(cls.p1['id'])
+ # Create a test project
p2_name = data_utils.rand_name('project')
+ p2_domain_id = CONF.identity.default_domain_id
cls.p2 = cls.projects_client.create_project(
- p2_name, domain_id=cls.domain_id)['project']
+ p2_name, domain_id=p2_domain_id)['project']
cls.addClassResourceCleanup(cls.projects_client.delete_project,
cls.p2['id'])
- cls.project_ids.append(cls.p2['id'])
@decorators.idempotent_id('1d830662-22ad-427c-8c3e-4ec854b0af44')
def test_list_projects(self):
# List projects
list_projects = self.projects_client.list_projects()['projects']
- for p in self.project_ids:
- show_project = self.projects_client.show_project(p)['project']
+ for p in [self.p1, self.p2]:
+ show_project = self.projects_client.show_project(p['id'])[
+ 'project']
self.assertIn(show_project, list_projects)
@decorators.idempotent_id('fa178524-4e6d-4925-907c-7ab9f42c7e26')
def test_list_projects_with_name(self):
# List projects with name
self._list_projects_with_params(
- [self.p1], [self.p2], {'name': self.p1_name}, 'name')
+ [self.p1], [self.p2], {'name': self.p1['name']}, 'name')
@decorators.idempotent_id('fab13f3c-f6a6-4b9f-829b-d32fd44fdf10')
def test_list_projects_with_domains(self):
- # List projects with domain
+ # Verify project list filtered by domain
key = 'domain_id'
- params = {key: self.domain_id}
- # Verify both projects are in the self.domain_id which is the default
- # domain
- self._list_projects_with_params(
- [self.p1, self.p2], [], params, key)
+ for p in [self.p1, self.p2]:
+ params = {key: p[key]}
+ # Verify filter shows both projects in their respective domains
+ self._list_projects_with_params([p], [], params, key)
+ # Verify filter excludes projects that are filtered out
+ if self.p1[key] != self.p2[key]:
+ exclude = [self.p2]
+ params = {key: self.p1[key]}
+ self._list_projects_with_params([self.p1], exclude, params, key)
diff --git a/tempest/api/identity/v3/test_tokens.py b/tempest/api/identity/v3/test_tokens.py
index f13aa10..fa1c47f 100644
--- a/tempest/api/identity/v3/test_tokens.py
+++ b/tempest/api/identity/v3/test_tokens.py
@@ -43,7 +43,15 @@
self.assertEqual(authenticated_token, token_body)
# test to see if token has been properly authenticated
self.assertEqual(authenticated_token['user']['id'], user_id)
- self.assertEqual(authenticated_token['user']['name'], username)
+ # NOTE: resource name that are case-sensitive in keystone
+ # depends on backends such as MySQL or LDAP which are
+ # case-insensitive, case-preserving. Resource name is
+ # returned as it is stored in the backend, not as it is
+ # requested. Verifying the username with both lower-case to
+ # avoid failure on different backends
+ self.assertEqual(
+ authenticated_token['user']['name'].lower(), username.lower())
+
self.non_admin_client.delete_token(subject_token)
self.assertRaises(
lib_exc.NotFound, self.non_admin_client.show_token, subject_token)
@@ -84,10 +92,17 @@
self.assertIsNotNone(subject_id, 'Expected user ID in token.')
subject_name = resp['user']['name']
+
if username:
- self.assertEqual(subject_name, username)
+ # NOTE: resource name that are case-sensitive in keystone
+ # depends on backends such as MySQL or LDAP which are
+ # case-insensitive, case-preserving. Resource name is
+ # returned as it is stored in the backend, not as it is
+ # requested. Verifying the username with both lower-case to
+ # avoid failure on different backends
+ self.assertEqual(subject_name.lower(), username.lower())
else:
- # Expect a user name, but don't know what it will be.
+ # Expect a user name, but don't know what it will be
self.assertIsNotNone(subject_name, 'Expected user name in token.')
self.assertEqual(resp['methods'][0], 'password')
@@ -110,7 +125,15 @@
subject_token)['token']
self.assertEqual(resp['x-subject-token'], subject_token)
self.assertEqual(token_details['user']['id'], user.user_id)
- self.assertEqual(token_details['user']['name'], user.username)
+ # NOTE: resource name that are case-sensitive in keystone
+ # depends on backends such as MySQL or LDAP which are
+ # case-insensitive, case-preserving. Resource name is
+ # returned as it is stored in the backend, not as it is
+ # requested. Verifying the username with both lower-case to
+ # avoid failure on different backends
+ self.assertEqual(
+ token_details['user']['name'].lower(),
+ user.username.lower())
# Perform Delete Token
self.non_admin_client.delete_token(subject_token)
self.assertRaises(lib_exc.NotFound,
diff --git a/tempest/api/volume/admin/test_volume_retype.py b/tempest/api/volume/admin/test_volume_retype.py
index 9136139..18e0b9b 100644
--- a/tempest/api/volume/admin/test_volume_retype.py
+++ b/tempest/api/volume/admin/test_volume_retype.py
@@ -94,7 +94,7 @@
super(VolumeRetypeTest, cls).skip_checks()
if not CONF.volume_feature_enabled.multi_backend:
- raise cls.skipException("Cinder multi-backend feature disabled.")
+ raise cls.skipException("Cinder multi-backend feature disabled")
if len(set(CONF.volume.backend_names)) < 2:
raise cls.skipException("Requires at least two different "
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index 495b6b9..645a952 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-#
# Copyright 2014 Dell Inc.
# 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
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index fd9f284..8b625d0 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
# Copyright 2015 Dell Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
diff --git a/tempest/cmd/list_plugins.py b/tempest/cmd/list_plugins.py
index 86732da..51decc7 100644
--- a/tempest/cmd/list_plugins.py
+++ b/tempest/cmd/list_plugins.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
# 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
diff --git a/tempest/lib/api_schema/response/volume/extensions.py b/tempest/lib/api_schema/response/volume/extensions.py
new file mode 100644
index 0000000..8dcb07d
--- /dev/null
+++ b/tempest/lib/api_schema/response/volume/extensions.py
@@ -0,0 +1,43 @@
+# Copyright 2018 ZTE Corporation. 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 tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+
+list_extensions = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'extensions': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'updated': parameter_types.date_time,
+ 'description': {'type': 'string'},
+ 'links': {'type': 'array'},
+ 'namespace': {'type': 'string'},
+ 'alias': {'type': 'string'},
+ 'name': {'type': 'string'}
+ },
+ 'additionalProperties': False,
+ 'required': ['updated', 'links', 'alias', 'name',
+ 'description']
+ }
+ }
+ },
+ 'additionalProperties': False,
+ 'required': ['extensions'],
+ }
+}
diff --git a/tempest/lib/api_schema/response/volume/services.py b/tempest/lib/api_schema/response/volume/services.py
new file mode 100644
index 0000000..70de878
--- /dev/null
+++ b/tempest/lib/api_schema/response/volume/services.py
@@ -0,0 +1,92 @@
+# Copyright 2018 ZTE Corporation. 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.
+import copy
+
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+
+list_services = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'services': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'binary': {'type': 'string'},
+ 'disabled_reason': {'type': ['string', 'null']},
+ 'host': {'type': 'string'},
+ 'state': {'enum': ['up', 'down']},
+ 'status': {'enum': ['enabled', 'disabled']},
+ 'frozen': {'type': 'boolean'},
+ 'updated_at': parameter_types.date_time,
+ 'zone': {'type': 'string'},
+ # TODO(zhufl): cluster is added in 3.7, we should move
+ # it to the 3.7 schema file when microversion is
+ # supported in volume interfaces
+ 'cluster': {'type': 'string'},
+ 'replication_status': {'type': 'string'},
+ 'active_backend_id': {'type': ['string', 'null']},
+ 'backend_state': {'type': 'string'},
+ },
+ 'additionalProperties': False,
+ 'required': ['binary', 'disabled_reason', 'host', 'state',
+ 'status', 'updated_at', 'zone']
+ }
+ }
+ },
+ 'additionalProperties': False,
+ 'required': ['services']
+ }
+}
+
+enable_service = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'disabled': {'type': 'boolean'},
+ 'status': {'enum': ['enabled', 'disabled']},
+ 'host': {'type': 'string'},
+ 'service': {'type': 'string'},
+ 'binary': {'type': 'string'},
+ 'disabled_reason': {'type': ['string', 'null']}
+ },
+ 'additionalProperties': False,
+ 'required': ['disabled', 'status', 'host', 'service',
+ 'binary', 'disabled_reason']
+ }
+}
+
+disable_service = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'disabled': {'type': 'boolean'},
+ 'status': {'enum': ['enabled', 'disabled']},
+ 'host': {'type': 'string'},
+ 'service': {'type': 'string'},
+ 'binary': {'type': 'string'},
+ },
+ 'additionalProperties': False,
+ 'required': ['disabled', 'status', 'host', 'service', 'binary']
+ }
+}
+
+disable_log_reason = copy.deepcopy(enable_service)
+
+freeze_host = {'status_code': [200]}
+thaw_host = {'status_code': [200]}
diff --git a/tempest/lib/services/network/metering_label_rules_client.py b/tempest/lib/services/network/metering_label_rules_client.py
index 8ccabee..dd5fd52 100644
--- a/tempest/lib/services/network/metering_label_rules_client.py
+++ b/tempest/lib/services/network/metering_label_rules_client.py
@@ -27,10 +27,17 @@
return self.create_resource(uri, post_data)
def show_metering_label_rule(self, metering_label_rule_id, **fields):
+ """Show metering label rule.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/network/v2/index.html#show-metering-label-rule-details
+ """
uri = '/metering/metering-label-rules/%s' % metering_label_rule_id
return self.show_resource(uri, **fields)
def delete_metering_label_rule(self, metering_label_rule_id):
+ """Delete metering label rule."""
uri = '/metering/metering-label-rules/%s' % metering_label_rule_id
return self.delete_resource(uri)
diff --git a/tempest/lib/services/volume/v3/extensions_client.py b/tempest/lib/services/volume/v3/extensions_client.py
index 45b7a56..f1fe5c9 100644
--- a/tempest/lib/services/volume/v3/extensions_client.py
+++ b/tempest/lib/services/volume/v3/extensions_client.py
@@ -15,6 +15,7 @@
from oslo_serialization import jsonutils as json
+from tempest.lib.api_schema.response.volume import extensions as schema
from tempest.lib.common import rest_client
@@ -25,5 +26,5 @@
url = 'extensions'
resp, body = self.get(url)
body = json.loads(body)
- self.expected_success(200, resp.status)
+ self.validate_response(schema.list_extensions, resp, body)
return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/volume/v3/services_client.py b/tempest/lib/services/volume/v3/services_client.py
index c4a511c..8bc82c9 100644
--- a/tempest/lib/services/volume/v3/services_client.py
+++ b/tempest/lib/services/volume/v3/services_client.py
@@ -16,6 +16,7 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
+from tempest.lib.api_schema.response.volume import services as schema
from tempest.lib.common import rest_client
@@ -35,7 +36,7 @@
resp, body = self.get(url)
body = json.loads(body)
- self.expected_success(200, resp.status)
+ self.validate_response(schema.list_services, resp, body)
return rest_client.ResponseBody(resp, body)
def enable_service(self, **kwargs):
@@ -48,7 +49,7 @@
put_body = json.dumps(kwargs)
resp, body = self.put('os-services/enable', put_body)
body = json.loads(body)
- self.expected_success(200, resp.status)
+ self.validate_response(schema.enable_service, resp, body)
return rest_client.ResponseBody(resp, body)
def disable_service(self, **kwargs):
@@ -61,7 +62,7 @@
put_body = json.dumps(kwargs)
resp, body = self.put('os-services/disable', put_body)
body = json.loads(body)
- self.expected_success(200, resp.status)
+ self.validate_response(schema.disable_service, resp, body)
return rest_client.ResponseBody(resp, body)
def disable_log_reason(self, **kwargs):
@@ -74,7 +75,7 @@
put_body = json.dumps(kwargs)
resp, body = self.put('os-services/disable-log-reason', put_body)
body = json.loads(body)
- self.expected_success(200, resp.status)
+ self.validate_response(schema.disable_log_reason, resp, body)
return rest_client.ResponseBody(resp, body)
def freeze_host(self, **kwargs):
@@ -85,8 +86,8 @@
https://docs.openstack.org/api-ref/block-storage/v3/#freeze-a-cinder-backend-host
"""
put_body = json.dumps(kwargs)
- resp, _ = self.put('os-services/freeze', put_body)
- self.expected_success(200, resp.status)
+ resp, body = self.put('os-services/freeze', put_body)
+ self.validate_response(schema.freeze_host, resp, body)
return rest_client.ResponseBody(resp)
def thaw_host(self, **kwargs):
@@ -97,6 +98,6 @@
https://docs.openstack.org/api-ref/block-storage/v3/#thaw-a-cinder-backend-host
"""
put_body = json.dumps(kwargs)
- resp, _ = self.put('os-services/thaw', put_body)
- self.expected_success(200, resp.status)
+ resp, body = self.put('os-services/thaw', put_body)
+ self.validate_response(schema.thaw_host, resp, body)
return rest_client.ResponseBody(resp)
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 5f6dae8..f03e9de 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -200,7 +200,8 @@
self.assertEqual(resize_flavor, server['flavor']['id'])
else:
flavor = self.flavors_client.show_flavor(resize_flavor)['flavor']
- for key in ['original_name', 'ram', 'vcpus', 'disk']:
+ self.assertEqual(flavor['name'], server['original_name'])
+ for key in ['ram', 'vcpus', 'disk']:
self.assertEqual(flavor[key], server['flavor'][key])
self._wait_server_status_and_check_network_connectivity(
server, keypair, floating_ip)
diff --git a/tempest/tests/lib/services/volume/v3/test_group_types_client.py b/tempest/tests/lib/services/volume/v3/test_group_types_client.py
index a333b81..8b853d7 100644
--- a/tempest/tests/lib/services/volume/v3/test_group_types_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_group_types_client.py
@@ -22,10 +22,13 @@
class TestGroupTypesClient(base.BaseServiceTest):
FAKE_CREATE_GROUP_TYPE = {
"group_type": {
- "name": "group-type-001",
- "description": "Test group type 1",
- "group_specs": {},
+ "id": "6685584b-1eac-4da6-b5c3-555430cf68ff",
+ "name": "grp-type-001",
+ "description": "group type 001",
"is_public": True,
+ "group_specs": {
+ "consistent_group_snapshot_enabled": "<is> False"
+ }
}
}
@@ -35,7 +38,6 @@
"name": "group-type-001",
"description": "Test group type 1",
"is_public": True,
- "created_at": "20127-06-20T03:50:07Z",
"group_specs": {},
}
}
@@ -57,24 +59,27 @@
"name": "group-type-001",
"description": "Test group type 1",
"is_public": True,
- "created_at": "2017-06-20T03:50:07Z",
- "group_specs": {},
+ "group_specs": {
+ "consistent_group_snapshot_enabled": "<is> False"
+ }
},
{
"id": "e479997c-650b-40a4-9dfe-77655818b0d2",
"name": "group-type-002",
"description": "Test group type 2",
"is_public": True,
- "created_at": "2017-06-19T01:52:47Z",
- "group_specs": {},
+ "group_specs": {
+ "consistent_group_snapshot_enabled": "<is> False"
+ }
},
{
"id": "c5c4769e-213c-40a6-a568-8e797bb691d4",
"name": "group-type-003",
"description": "Test group type 3",
"is_public": True,
- "created_at": "2017-06-18T06:34:32Z",
- "group_specs": {},
+ "group_specs": {
+ "consistent_group_snapshot_enabled": "<is> False"
+ }
}
]
}
@@ -140,15 +145,12 @@
def _test_update_group_types(self, bytes_body=False):
resp_body = copy.deepcopy(self.FAKE_INFO_GROUP_TYPE)
- resp_body['group_type'].pop('created_at')
-
self.check_service_client_function(
self.client.update_group_type,
'tempest.lib.common.rest_client.RestClient.put',
resp_body,
bytes_body,
- group_type_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5",
- name='updated-group-type-name')
+ group_type_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5")
def _test_create_or_update_group_type_specs(self, bytes_body=False):
group_specs = self.FAKE_CREATE_GROUP_TYPE_SPECS['group_specs']
diff --git a/tools/generate-tempest-plugins-list.py b/tools/generate-tempest-plugins-list.py
index f1003a0..d4ffd01 100644
--- a/tools/generate-tempest-plugins-list.py
+++ b/tools/generate-tempest-plugins-list.py
@@ -27,14 +27,8 @@
import re
import sys
-try:
- # For Python 3.0 and later
- from urllib.error import HTTPError
- import urllib.request as urllib
-except ImportError:
- # Fall back to Python 2's urllib2
- import urllib2 as urllib
- from urllib2 import HTTPError
+import urllib3
+from urllib3.util import retry
# List of projects having tempest plugin stale or unmaintained for a long time
# (6 months or more)
@@ -56,7 +50,6 @@
# https://review.opendev.org/#/c/637718/
'openstack/neutron-vpnaas', # https://review.opendev.org/#/c/637719/
'x/valet', # https://review.opendev.org/#/c/638339/
- 'x/ranger-tempest-plugin', # It looks this doesn't work correctly yet.
]
url = 'https://review.opendev.org/projects/'
@@ -69,23 +62,21 @@
},
'''
+http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED')
+retries = retry.Retry(status_forcelist=[500], backoff_factor=1.0)
-# Rather than returning a 404 for a nonexistent file, cgit delivers a
-# 0-byte response to a GET request. It also does not provide a
-# Content-Length in a HEAD response, so the way we tell if a file exists
-# is to check the length of the entire GET response body.
+
def has_tempest_plugin(proj):
try:
- r = urllib.urlopen(
- "https://opendev.org/%s/raw/branch/"
- "master/setup.cfg" % proj)
- except HTTPError as err:
- if err.code == 404:
+ r = http.request('GET', "https://opendev.org/%s/raw/branch/"
+ "master/setup.cfg" % proj, retries=retries)
+ if r.status == 404:
return False
+ except urllib3.exceptions.MaxRetryError as err:
# We should not ignore non 404 errors.
raise err
p = re.compile(r'^tempest\.test_plugins', re.M)
- if p.findall(r.read().decode('utf-8')):
+ if p.findall(r.data.decode('utf-8')):
return True
else:
False
@@ -98,11 +89,11 @@
# So, this exits here.
sys.exit()
-r = urllib.urlopen(url)
+r = http.request('GET', url, retries=retries)
# Gerrit prepends 4 garbage octets to the JSON, in order to counter
# cross-site scripting attacks. Therefore we must discard it so the
# json library won't choke.
-content = r.read().decode('utf-8')[4:]
+content = r.data.decode('utf-8')[4:]
projects = sorted(json.loads(content))
# Retrieve projects having no deployment tool repo (such as deb,
diff --git a/tools/generate-tempest-plugins-list.sh b/tools/generate-tempest-plugins-list.sh
index b6a7c77..961cd09 100755
--- a/tools/generate-tempest-plugins-list.sh
+++ b/tools/generate-tempest-plugins-list.sh
@@ -69,7 +69,7 @@
i=0
for plugin in $1; do
i=$((i+1))
- giturl="https://opendev.org/openstack/${plugin}"
+ giturl="https://opendev.org/${plugin}"
printf "%-3s %-${name_col_len}s %s\n" "$i" "${plugin}" "${giturl}"
done
diff --git a/tools/verify-ipv6-only-deployments.sh b/tools/verify-ipv6-only-deployments.sh
index 90807a3..2596395 100755
--- a/tools/verify-ipv6-only-deployments.sh
+++ b/tools/verify-ipv6-only-deployments.sh
@@ -15,10 +15,14 @@
source $TOP_DIR/openrc admin admin
function verify_devstack_ipv6_setting {
- local _service_host=$(echo $SERVICE_HOST | tr -d [])
- local _host_ipv6=$(echo $HOST_IPV6 | tr -d [])
- local _service_listen_address=$(echo $SERVICE_LISTEN_ADDRESS | tr -d [])
- local _service_local_host=$(echo $SERVICE_LOCAL_HOST | tr -d [])
+ local _service_host=''
+ _service_host=$(echo $SERVICE_HOST | tr -d [])
+ local _host_ipv6=''
+ _host_ipv6=$(echo $HOST_IPV6 | tr -d [])
+ local _service_listen_address=''
+ _service_listen_address=$(echo $SERVICE_LISTEN_ADDRESS | tr -d [])
+ local _service_local_host=''
+ _service_local_host=$(echo $SERVICE_LOCAL_HOST | tr -d [])
if [[ "$SERVICE_IP_VERSION" != 6 ]]; then
echo $SERVICE_IP_VERSION "SERVICE_IP_VERSION is not set to 6 which is must for devstack to deploy services with IPv6 address."
exit 1
@@ -61,9 +65,11 @@
local all_ipv6=True
endpoints=$(openstack endpoint list -f value -c URL)
for endpoint in ${endpoints}; do
- local endpoint_address=$(echo "$endpoint" | awk -F/ '{print $3}' | awk -F] '{print $1}')
+ local endpoint_address=''
+ endpoint_address=$(echo "$endpoint" | awk -F/ '{print $3}' | awk -F] '{print $1}')
endpoint_address=$(echo $endpoint_address | tr -d [])
- local is_endpoint_ipv6=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$endpoint_address'"))')
+ local is_endpoint_ipv6=''
+ is_endpoint_ipv6=$(python3 -c 'import oslo_utils.netutils as nutils; print(nutils.is_valid_ipv6("'$endpoint_address'"))')
if [[ "$is_endpoint_ipv6" != "True" ]]; then
all_ipv6=False
echo $endpoint ": This is not ipv6 endpoint which means corresponding service is not listening on IPv6 address."
diff --git a/tox.ini b/tox.ini
index b6ea143..ca4bb3f 100644
--- a/tox.ini
+++ b/tox.ini
@@ -327,7 +327,7 @@
-not \( -type d -name .?\* -prune \) \
-type f \
-name \*.sh \
- -print0 | xargs -0 bashate -v"
+ -print0 | xargs -0 bashate -v -eE005,E042 -i E006"
[testenv:pip-check-reqs]
# Do not install test-requirements as that will pollute the virtualenv for