Merge "Updated from global requirements"
diff --git a/.zuul.yaml b/.zuul.yaml
index 4f17959..e5e093a 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -209,6 +209,18 @@
gate:
jobs:
- nova-multiattach
+ experimental:
+ jobs:
+ - nova-cells-v1:
+ irrelevant-files:
+ - ^(test-|)requirements.txt$
+ - ^.*\.rst$
+ - ^doc/.*$
+ - ^etc/.*$
+ - ^releasenotes/.*$
+ - ^setup.cfg$
+ - ^tempest/hacking/.*$
+ - ^tempest/tests/.*$
periodic-stable:
jobs:
- tempest-full-queens
diff --git a/releasenotes/notes/12/12.2.0-service_client_config-8a1d7b4de769c633.yaml b/releasenotes/notes/12/12.2.0-service_client_config-8a1d7b4de769c633.yaml
index 3e43f9a..985acb0 100644
--- a/releasenotes/notes/12/12.2.0-service_client_config-8a1d7b4de769c633.yaml
+++ b/releasenotes/notes/12/12.2.0-service_client_config-8a1d7b4de769c633.yaml
@@ -3,4 +3,4 @@
- A new helper method `service_client_config` has been added
to the stable module config.py that returns extracts from
configuration into a dictionary the configuration settings
- relevant for the initisialisation of a service client.
+ relevant for the initialization of a service client.
diff --git a/releasenotes/notes/16/16.0.0-add-content-type-without-spaces-b2c9b91b257814f3.yaml b/releasenotes/notes/16/16.0.0-add-content-type-without-spaces-b2c9b91b257814f3.yaml
index 0075a36..fc061bc 100644
--- a/releasenotes/notes/16/16.0.0-add-content-type-without-spaces-b2c9b91b257814f3.yaml
+++ b/releasenotes/notes/16/16.0.0-add-content-type-without-spaces-b2c9b91b257814f3.yaml
@@ -2,7 +2,7 @@
upgrade:
- The ``JSON_ENC`` and ``TXT_ENC`` option in the ``_error_checker``
section have been added with additional content-type which are
- defined in RFC7231 but missing in the currnt rest_client.py file.
+ defined in RFC7231 but missing in the current rest_client.py file.
The lack of these additional content-type will cause defcore test
to fail for OpenStack public cloud which uses tomcat module in the
api gateway. The additions are ``application/json;charset=utf-8``,
diff --git a/releasenotes/notes/16/16.0.0-create-server-tags-client-8c0042a77e859af6.yaml b/releasenotes/notes/16/16.0.0-create-server-tags-client-8c0042a77e859af6.yaml
index 9927971..18ad5b9 100644
--- a/releasenotes/notes/16/16.0.0-create-server-tags-client-8c0042a77e859af6.yaml
+++ b/releasenotes/notes/16/16.0.0-create-server-tags-client-8c0042a77e859af6.yaml
@@ -2,7 +2,7 @@
features:
- |
Add server tags APIs to the servers_client library.
- This feature enables the possibility of upating, deleting
+ This feature enables the possibility of updating, deleting
and checking existence of a tag on a server, as well
as updating and deleting all tags on a server.
diff --git a/releasenotes/notes/16/16.0.0-deprecate-resources-prefix-option-ad490c0a30a0266b.yaml b/releasenotes/notes/16/16.0.0-deprecate-resources-prefix-option-ad490c0a30a0266b.yaml
index f679208..0b45d0d 100644
--- a/releasenotes/notes/16/16.0.0-deprecate-resources-prefix-option-ad490c0a30a0266b.yaml
+++ b/releasenotes/notes/16/16.0.0-deprecate-resources-prefix-option-ad490c0a30a0266b.yaml
@@ -6,5 +6,5 @@
deprecations:
- The resources_prefix is marked as deprecated because it is
enough to set 'tempest' as the prefix on rand_name() to
- ideintify resources which are created by Tempest and no
+ identify resources which are created by Tempest and no
projects set this option on OpenStack dev community.
diff --git a/releasenotes/notes/add-additional-methods-to-policy-client-library-b8279c18335588c9.yaml b/releasenotes/notes/add-additional-methods-to-policy-client-library-b8279c18335588c9.yaml
new file mode 100644
index 0000000..cd5284d
--- /dev/null
+++ b/releasenotes/notes/add-additional-methods-to-policy-client-library-b8279c18335588c9.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Add ``v3-ext/OS-ENDPOINT-POLICY`` API calls to support creation, deletion and
+ retrieval of associations between service endpoints and policies. Such associations
+ enable an endpoint to request its policy.
diff --git a/releasenotes/notes/add-support-args-kwargs-in-call-until-true-a91k592h5a64exf7.yaml b/releasenotes/notes/add-support-args-kwargs-in-call-until-true-a91k592h5a64exf7.yaml
index e23abe3..9c30a0c 100644
--- a/releasenotes/notes/add-support-args-kwargs-in-call-until-true-a91k592h5a64exf7.yaml
+++ b/releasenotes/notes/add-support-args-kwargs-in-call-until-true-a91k592h5a64exf7.yaml
@@ -2,4 +2,4 @@
features:
- Add support of args and kwargs when calling func in call_until_true,
also to log the cost time when call_until_true returns True or False
- for debuggin.
+ for debugging.
diff --git a/releasenotes/notes/compare-header-version-func-de5139b2161b3627.yaml b/releasenotes/notes/compare-header-version-func-de5139b2161b3627.yaml
index 305e756..cc6c51b 100644
--- a/releasenotes/notes/compare-header-version-func-de5139b2161b3627.yaml
+++ b/releasenotes/notes/compare-header-version-func-de5139b2161b3627.yaml
@@ -3,7 +3,7 @@
- |
Add a new function called ``compare_version_header_to_response`` to
``tempest.lib.common.api_version_utils``, which compares the API
- micoversion in the response header to another microversion using the
+ microversion in the response header to another microversion using the
comparators defined in
``tempest.lib.common.api_version_request.APIVersionRequest``.
diff --git a/releasenotes/notes/fix-show-image-file-expected-code-92d97342d0f6d60e.yaml b/releasenotes/notes/fix-show-image-file-expected-code-92d97342d0f6d60e.yaml
new file mode 100644
index 0000000..a4050a5
--- /dev/null
+++ b/releasenotes/notes/fix-show-image-file-expected-code-92d97342d0f6d60e.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+ - |
+ Fix show_image_file interface in v2 ImagesClient: Bug#1756264.
+ The expected success code of show_image_file is changed from
+ ``200`` to ``[200, 204, 206]``.
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index d968a44..2518703 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -2,20 +2,22 @@
Tempest Release Notes
===========================
- .. toctree::
- :maxdepth: 1
+.. toctree::
+ :maxdepth: 1
- unreleased
- v18.0.0
- v17.0.0
- v16.1.0
- v16.0.0
- v15.0.0
- v14.0.0
- v13.0.0
- v12.0.0
- v11.0.0
- v10.0.0
+ unreleased
+ v18.0.0
+ v17.2.0
+ v17.1.0
+ v17.0.0
+ v16.1.0
+ v16.0.0
+ v15.0.0
+ v14.0.0
+ v13.0.0
+ v12.0.0
+ v11.0.0
+ v10.0.0
Indices and tables
==================
diff --git a/releasenotes/source/v17.1.0.rst b/releasenotes/source/v17.1.0.rst
new file mode 100644
index 0000000..b8fd570
--- /dev/null
+++ b/releasenotes/source/v17.1.0.rst
@@ -0,0 +1,6 @@
+=====================
+v17.1.0 Release Notes
+=====================
+
+.. release-notes:: 17.1.0 Release Notes
+ :version: 17.1.0
diff --git a/releasenotes/source/v17.2.0.rst b/releasenotes/source/v17.2.0.rst
new file mode 100644
index 0000000..8566ae4
--- /dev/null
+++ b/releasenotes/source/v17.2.0.rst
@@ -0,0 +1,6 @@
+=====================
+v17.2.0 Release Notes
+=====================
+
+.. release-notes:: 17.2.0 Release Notes
+ :version: 17.2.0
diff --git a/roles/process-stackviz/tasks/main.yaml b/roles/process-stackviz/tasks/main.yaml
index 82f8f3d..3724e0e 100644
--- a/roles/process-stackviz/tasks/main.yaml
+++ b/roles/process-stackviz/tasks/main.yaml
@@ -50,6 +50,7 @@
- stackviz_archive.stat.exists
- subunit_input.stat.exists
- dstat_input.stat.exists
+ failed_when: False
- name: Run stackviz without dstat
shell: |
@@ -61,3 +62,4 @@
- stackviz_archive.stat.exists
- subunit_input.stat.exists
- not dstat_input.stat.exists
+ failed_when: False
diff --git a/tempest/api/compute/admin/test_aggregates_negative.py b/tempest/api/compute/admin/test_aggregates_negative.py
index 36ff09e..6df8410 100644
--- a/tempest/api/compute/admin/test_aggregates_negative.py
+++ b/tempest/api/compute/admin/test_aggregates_negative.py
@@ -27,16 +27,16 @@
def setup_clients(cls):
super(AggregatesAdminNegativeTestJSON, cls).setup_clients()
cls.client = cls.os_admin.aggregates_client
+ cls.hyper_client = cls.os_admin.hypervisor_client
@classmethod
def resource_setup(cls):
super(AggregatesAdminNegativeTestJSON, cls).resource_setup()
cls.aggregate_name_prefix = 'test_aggregate'
- hosts_all = cls.os_admin.hosts_client.list_hosts()['hosts']
- hosts = ([host['host_name']
- for host in hosts_all if host['service'] == 'compute'])
- cls.host = hosts[0]
+ hyper_list = cls.hyper_client.list_hypervisors()['hypervisors']
+ cls.hosts = [v['hypervisor_hostname'] for v in hyper_list
+ if v['status'] == 'enabled' and v['state'] == 'up']
def _create_test_aggregate(self):
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -123,11 +123,9 @@
@decorators.idempotent_id('0ef07828-12b4-45ba-87cc-41425faf5711')
def test_aggregate_add_non_exist_host(self):
# Adding a non-exist host to an aggregate should raise exceptions.
- hosts_all = self.os_admin.hosts_client.list_hosts()['hosts']
- hosts = map(lambda x: x['host_name'], hosts_all)
while True:
non_exist_host = data_utils.rand_name('nonexist_host')
- if non_exist_host not in hosts:
+ if non_exist_host not in self.hosts:
break
aggregate = self._create_test_aggregate()
self.assertRaises(lib_exc.NotFound, self.client.add_host,
@@ -140,7 +138,7 @@
aggregate = self._create_test_aggregate()
self.assertRaises(lib_exc.Forbidden,
self.aggregates_client.add_host,
- aggregate['id'], host=self.host)
+ aggregate['id'], host=self.hosts[0])
@decorators.attr(type=['negative'])
@decorators.idempotent_id('19dd44e1-c435-4ee1-a402-88c4f90b5950')
@@ -148,12 +146,12 @@
self.useFixture(fixtures.LockFixture('availability_zone'))
aggregate = self._create_test_aggregate()
- self.client.add_host(aggregate['id'], host=self.host)
+ self.client.add_host(aggregate['id'], host=self.hosts[0])
self.addCleanup(self.client.remove_host, aggregate['id'],
- host=self.host)
+ host=self.hosts[0])
self.assertRaises(lib_exc.Conflict, self.client.add_host,
- aggregate['id'], host=self.host)
+ aggregate['id'], host=self.hosts[0])
@decorators.attr(type=['negative'])
@decorators.idempotent_id('7a53af20-137a-4e44-a4ae-e19260e626d9')
@@ -162,13 +160,13 @@
self.useFixture(fixtures.LockFixture('availability_zone'))
aggregate = self._create_test_aggregate()
- self.client.add_host(aggregate['id'], host=self.host)
+ self.client.add_host(aggregate['id'], host=self.hosts[0])
self.addCleanup(self.client.remove_host, aggregate['id'],
- host=self.host)
+ host=self.hosts[0])
self.assertRaises(lib_exc.Forbidden,
self.aggregates_client.remove_host,
- aggregate['id'], host=self.host)
+ aggregate['id'], host=self.hosts[0])
@decorators.attr(type=['negative'])
@decorators.idempotent_id('95d6a6fa-8da9-4426-84d0-eec0329f2e4d')
diff --git a/tempest/api/compute/admin/test_hosts.py b/tempest/api/compute/admin/test_hosts.py
index 00f3256..c246685 100644
--- a/tempest/api/compute/admin/test_hosts.py
+++ b/tempest/api/compute/admin/test_hosts.py
@@ -20,6 +20,8 @@
class HostsAdminTestJSON(base.BaseV2ComputeAdminTest):
"""Tests hosts API using admin privileges."""
+ max_microversion = '2.42'
+
@classmethod
def setup_clients(cls):
super(HostsAdminTestJSON, cls).setup_clients()
diff --git a/tempest/api/compute/admin/test_hosts_negative.py b/tempest/api/compute/admin/test_hosts_negative.py
index 5bd8104..8a91ae2 100644
--- a/tempest/api/compute/admin/test_hosts_negative.py
+++ b/tempest/api/compute/admin/test_hosts_negative.py
@@ -20,6 +20,8 @@
class HostsAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
"""Tests hosts API using admin privileges."""
+ max_microversion = '2.42'
+
@classmethod
def setup_clients(cls):
super(HostsAdminNegativeTestJSON, cls).setup_clients()
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index b497626..1f3af5f 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -28,6 +28,7 @@
class ImagesMetadataTestJSON(base.BaseV2ComputeTest):
+ max_microversion = '2.38'
@classmethod
def skip_checks(cls):
diff --git a/tempest/api/compute/images/test_image_metadata_negative.py b/tempest/api/compute/images/test_image_metadata_negative.py
index 03d0789..407fb08 100644
--- a/tempest/api/compute/images/test_image_metadata_negative.py
+++ b/tempest/api/compute/images/test_image_metadata_negative.py
@@ -20,6 +20,7 @@
class ImagesMetadataNegativeTestJSON(base.BaseV2ComputeTest):
+ max_microversion = '2.38'
@classmethod
def setup_clients(cls):
diff --git a/tempest/cmd/subunit_describe_calls.py b/tempest/cmd/subunit_describe_calls.py
index f0ade7e..a4402fe 100644
--- a/tempest/cmd/subunit_describe_calls.py
+++ b/tempest/cmd/subunit_describe_calls.py
@@ -29,6 +29,9 @@
written to. This contains more information than is present in stdout.
* ``--ports, -p``: (Optional) The path to a JSON file describing the ports
being used by different services
+* ``--verbose, -v``: (Optional) Print Request and Response Headers and Body
+ data to stdout
+
Usage
-----
@@ -262,6 +265,10 @@
"-p", "--ports", metavar="<ports file>", default=None,
help="A JSON file describing the ports for each service.")
+ self.add_argument(
+ "-v", "--verbose", action='store_true', default=False,
+ help="Add Request and Response header and body data to stdout.")
+
def parse(stream, non_subunit_name, ports):
if ports is not None and os.path.exists(ports):
@@ -286,7 +293,7 @@
return url_parser
-def output(url_parser, output_file):
+def output(url_parser, output_file, verbose):
if output_file is not None:
with open(output_file, "w") as outfile:
outfile.write(json.dumps(url_parser.test_logs))
@@ -302,13 +309,22 @@
sys.stdout.write('\t- {0} {1} request for {2} to {3}\n'.format(
item.get('status_code'), item.get('verb'),
item.get('service'), item.get('url')))
+ if verbose:
+ sys.stdout.write('\t\t- request headers: {0}\n'.format(
+ item.get('request_headers')))
+ sys.stdout.write('\t\t- request body: {0}\n'.format(
+ item.get('request_body')))
+ sys.stdout.write('\t\t- response headers: {0}\n'.format(
+ item.get('response_headers')))
+ sys.stdout.write('\t\t- response body: {0}\n'.format(
+ item.get('response_body')))
sys.stdout.write('\n')
def entry_point():
cl_args = ArgumentParser().parse_args()
parser = parse(cl_args.subunit, cl_args.non_subunit_name, cl_args.ports)
- output(parser, cl_args.output_file)
+ output(parser, cl_args.output_file, cl_args.verbose)
if __name__ == "__main__":
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index 638ad9b..68c4a10 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -289,7 +289,12 @@
def create_websocket(url):
url = urlparse.urlparse(url)
- for res in socket.getaddrinfo(url.hostname, url.port,
+
+ # NOTE(mnaser): It is possible that there is no port specified, so fall
+ # back to the default port based on the scheme.
+ port = url.port or (443 if url.scheme == 'https' else 80)
+
+ for res in socket.getaddrinfo(url.hostname, port,
socket.AF_UNSPEC, socket.SOCK_STREAM):
af, socktype, proto, _, sa = res
client_socket = socket.socket(af, socktype, proto)
@@ -382,7 +387,12 @@
"""Upgrade the HTTP connection to a WebSocket and verify."""
# The real request goes to the /websockify URI always
reqdata = 'GET /websockify HTTP/1.1\r\n'
- reqdata += 'Host: %s:%s\r\n' % (url.hostname, url.port)
+ reqdata += 'Host: %s' % url.hostname
+ # Add port only if we have one specified
+ if url.port:
+ reqdata += ':%s' % url.port
+ # Line-ending for Host header
+ reqdata += '\r\n'
# Tell the HTTP Server to Upgrade the connection to a WebSocket
reqdata += 'Upgrade: websocket\r\nConnection: Upgrade\r\n'
# The token=xxx is sent as a Cookie not in the URI
diff --git a/tempest/config.py b/tempest/config.py
index 8a6370a..5d27efd 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -237,7 +237,10 @@
cfg.BoolOpt('security_compliance',
default=False,
help='Does the environment have the security compliance '
- 'settings enabled?')
+ 'settings enabled?'),
+ cfg.BoolOpt('project_tags',
+ default=False,
+ help='Is the project tags identity v3 API available?')
]
compute_group = cfg.OptGroup(name='compute',
diff --git a/tempest/lib/services/identity/v3/policies_client.py b/tempest/lib/services/identity/v3/policies_client.py
index d4560e2..ca8dbbd 100644
--- a/tempest/lib/services/identity/v3/policies_client.py
+++ b/tempest/lib/services/identity/v3/policies_client.py
@@ -73,3 +73,115 @@
resp, body = self.delete(url)
self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp, body)
+
+ def update_policy_association_for_endpoint(self, policy_id, endpoint_id):
+ """Create policy association with endpoint.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/index.html#associate-policy-and-endpoint
+ """
+ url = "policies/{0}/OS-ENDPOINT-POLICY/endpoints/{1}"\
+ .format(policy_id, endpoint_id)
+ resp, body = self.put(url, '{}')
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def show_policy_association_for_endpoint(self, policy_id, endpoint_id):
+ """Get policy association of endpoint.
+
+ API reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/index.html#verify-a-policy-and-endpoint-association
+ """
+ url = "policies/{0}/OS-ENDPOINT-POLICY/endpoints/{1}"\
+ .format(policy_id, endpoint_id)
+ resp, body = self.get(url)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_policy_association_for_endpoint(self, policy_id, endpoint_id):
+ """Delete policy association with endpoint.
+
+ API reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/index.html#delete-a-policy-and-endpoint-association
+ """
+ url = "policies/{0}/OS-ENDPOINT-POLICY/endpoints/{1}"\
+ .format(policy_id, endpoint_id)
+ resp, body = self.delete(url)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_policy_association_for_service(self, policy_id, service_id):
+ """Create policy association with service.
+
+ API reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/index.html#associate-policy-and-service-type-endpoint
+ """
+ url = "policies/{0}/OS-ENDPOINT-POLICY/services/{1}"\
+ .format(policy_id, service_id)
+ resp, body = self.put(url, '{}')
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def show_policy_association_for_service(self, policy_id, service_id):
+ """Get policy association of service.
+
+ API Reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/index.html#verify-a-policy-and-service-type-endpoint-association
+ """
+ url = "policies/{0}/OS-ENDPOINT-POLICY/services/{1}"\
+ .format(policy_id, service_id)
+ resp, body = self.get(url)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_policy_association_for_service(self, policy_id, service_id):
+ """Delete policy association with service.
+
+ API reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/index.html#delete-a-policy-and-service-type-endpoint-association
+ """
+ url = "policies/{0}/OS-ENDPOINT-POLICY/services/{1}"\
+ .format(policy_id, service_id)
+ resp, body = self.delete(url)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_policy_association_for_region_and_service(
+ self, policy_id, service_id, region_id):
+ """Create policy association with service and region.
+
+ API reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/index.html#associate-policy-and-service-type-endpoint-in-a-region
+ """
+ url = "policies/{0}/OS-ENDPOINT-POLICY/services/{1}/regions/{2}"\
+ .format(policy_id, service_id, region_id)
+ resp, body = self.put(url, '{}')
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def show_policy_association_for_region_and_service(
+ self, policy_id, service_id, region_id):
+ """Get policy association of service and region.
+
+ API reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/index.html#verify-a-policy-and-service-type-endpoint-in-a-region-association
+ """
+ url = "policies/{0}/OS-ENDPOINT-POLICY/services/{1}/regions/{2}"\
+ .format(policy_id, service_id, region_id)
+ resp, body = self.get(url)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_policy_association_for_region_and_service(
+ self, policy_id, service_id, region_id):
+ """Delete policy association with service and region.
+
+ API reference:
+ https://developer.openstack.org/api-ref/identity/v3-ext/index.html#delete-a-policy-and-service-type-endpoint-in-a-region-association
+ """
+ url = "policies/{0}/OS-ENDPOINT-POLICY/services/{1}/regions/{2}"\
+ .format(policy_id, service_id, region_id)
+ resp, body = self.delete(url)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/image/v2/images_client.py b/tempest/lib/services/image/v2/images_client.py
index bcdae44..ed6df47 100644
--- a/tempest/lib/services/image/v2/images_client.py
+++ b/tempest/lib/services/image/v2/images_client.py
@@ -161,7 +161,7 @@
"""
url = 'images/%s/file' % image_id
resp, body = self.get(url)
- self.expected_success(200, resp.status)
+ self.expected_success([200, 204, 206], resp.status)
return rest_client.ResponseBodyData(resp, body)
def add_image_tag(self, image_id, tag):
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 26ae848..c78646f 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -141,13 +141,18 @@
vnic_type = CONF.network.port_vnic_type
profile = CONF.network.port_profile
- # If vnic_type is configured create port for
+ # If vnic_type or profile are configured create port for
# every network
- if vnic_type:
+ if vnic_type or profile:
ports = []
+ create_port_body = {}
- create_port_body = {'binding:vnic_type': vnic_type,
- 'binding:profile': profile}
+ if vnic_type:
+ create_port_body['binding:vnic_type'] = vnic_type
+
+ if profile:
+ create_port_body['binding:profile'] = profile
+
if kwargs:
# Convert security group names to security group ids
# to pass to create_port
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 9ff6227..f762995 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -37,7 +37,7 @@
super(TestAggregatesBasicOps, cls).setup_clients()
# Use admin client by default
cls.aggregates_client = cls.os_admin.aggregates_client
- cls.hosts_client = cls.os_admin.hosts_client
+ cls.hyper_client = cls.os_admin.hypervisor_client
def _create_aggregate(self, **kwargs):
aggregate = (self.aggregates_client.create_aggregate(**kwargs)
@@ -51,10 +51,9 @@
return aggregate
def _get_host_name(self):
- hosts = self.hosts_client.list_hosts()['hosts']
- self.assertNotEmpty(hosts)
- computes = [x for x in hosts if x['service'] == 'compute']
- return computes[0]['host_name']
+ hyper_list = self.hyper_client.list_hypervisors()['hypervisors']
+ self.assertNotEmpty(hyper_list)
+ return hyper_list[0]['hypervisor_hostname']
def _add_host(self, aggregate_id, host):
aggregate = (self.aggregates_client.add_host(aggregate_id, host=host)
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index beb039c..7ceae89 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -30,12 +30,6 @@
# breathing room to get through deletes in the time allotted.
TIMEOUT_SCALING_FACTOR = 2
- @classmethod
- def skip_checks(cls):
- super(TestVolumeBootPattern, cls).skip_checks()
- if not CONF.volume_feature_enabled.snapshot:
- raise cls.skipException("Cinder volume snapshots are disabled")
-
def _create_volume_from_image(self):
img_uuid = CONF.compute.image_ref
vol_name = data_utils.rand_name(
@@ -76,6 +70,8 @@
@decorators.idempotent_id('557cd2c2-4eb8-4dce-98be-f86765ff311b')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
+ @testtools.skipUnless(CONF.volume_feature_enabled.snapshot,
+ 'Cinder volume snapshots are disabled')
@utils.services('compute', 'volume', 'image')
def test_volume_boot_pattern(self):
@@ -156,6 +152,8 @@
@decorators.idempotent_id('05795fb2-b2a7-4c9f-8fac-ff25aedb1489')
@decorators.attr(type='slow')
+ @testtools.skipUnless(CONF.volume_feature_enabled.snapshot,
+ 'Cinder volume snapshots are disabled')
@utils.services('compute', 'image', 'volume')
def test_create_server_from_volume_snapshot(self):
# Create a volume from an image
@@ -192,6 +190,8 @@
created_volume_info['attachments'][0]['volume_id'])
@decorators.idempotent_id('36c34c67-7b54-4b59-b188-02a2f458a63b')
+ @testtools.skipUnless(CONF.volume_feature_enabled.snapshot,
+ 'Cinder volume snapshots are disabled')
@utils.services('compute', 'volume', 'image')
def test_create_ebs_image_and_check_boot(self):
# create an instance from volume
diff --git a/tempest/tests/cmd/test_subunit_describe_calls.py b/tempest/tests/cmd/test_subunit_describe_calls.py
index 5f3d770..cb34ba6 100644
--- a/tempest/tests/cmd/test_subunit_describe_calls.py
+++ b/tempest/tests/cmd/test_subunit_describe_calls.py
@@ -33,15 +33,42 @@
p.communicate()
self.assertEqual(0, p.returncode)
+ def test_verbose(self):
+ subunit_file = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ 'sample_streams/calls.subunit')
+ p = subprocess.Popen([
+ 'subunit-describe-calls', '-s', subunit_file,
+ '-v'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ stdout = p.communicate()
+ self.assertEqual(0, p.returncode)
+ self.assertIn(b'- request headers:', stdout[0])
+ self.assertIn(b'- request body:', stdout[0])
+ self.assertIn(b'- response headers:', stdout[0])
+ self.assertIn(b'- response body:', stdout[0])
+
def test_return_code_no_output(self):
subunit_file = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'sample_streams/calls.subunit')
p = subprocess.Popen([
'subunit-describe-calls', '-s', subunit_file],
- stdin=subprocess.PIPE)
- p.communicate()
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ stdout = p.communicate()
self.assertEqual(0, p.returncode)
+ self.assertIn(b'foo', stdout[0])
+ self.assertIn(b'- 200 POST request for Nova to v2.1/<id>/',
+ stdout[0])
+ self.assertIn(b'- 200 DELETE request for Nova to v2.1/<id>/',
+ stdout[0])
+ self.assertIn(b'- 200 GET request for Nova to v2.1/<id>/',
+ stdout[0])
+ self.assertIn(b'- 404 DELETE request for Nova to v2.1/<id>/',
+ stdout[0])
+ self.assertNotIn(b'- request headers:', stdout[0])
+ self.assertNotIn(b'- request body:', stdout[0])
+ self.assertNotIn(b'- response headers:', stdout[0])
+ self.assertNotIn(b'- response body:', stdout[0])
def test_parse(self):
subunit_file = os.path.join(
diff --git a/tempest/tests/lib/services/identity/v3/test_policies_client.py b/tempest/tests/lib/services/identity/v3/test_policies_client.py
index 66c3d65..0237475 100644
--- a/tempest/tests/lib/services/identity/v3/test_policies_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_policies_client.py
@@ -81,6 +81,10 @@
}
]
}
+ FAKE_ENDPOINT_ID = "234789"
+ FAKE_SERVICE_ID = "556782"
+ FAKE_POLICY_ID = "717273"
+ FAKE_REGION_ID = "73"
def setUp(self):
super(TestPoliciesClient, self).setUp()
@@ -150,3 +154,87 @@
{},
policy_id="717273",
status=204)
+
+ def test_update_policy_association_for_endpoint(self):
+ self.check_service_client_function(
+ self.client.update_policy_association_for_endpoint,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ policy_id=self.FAKE_POLICY_ID,
+ endpoint_id=self.FAKE_ENDPOINT_ID,
+ status=204)
+
+ def test_show_policy_association_for_endpoint(self):
+ self.check_service_client_function(
+ self.client.show_policy_association_for_endpoint,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ {},
+ policy_id=self.FAKE_POLICY_ID,
+ endpoint_id=self.FAKE_ENDPOINT_ID,
+ status=204)
+
+ def test_delete_policy_association_for_endpoint(self):
+ self.check_service_client_function(
+ self.client.delete_policy_association_for_endpoint,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ policy_id=self.FAKE_POLICY_ID,
+ endpoint_id=self.FAKE_ENDPOINT_ID,
+ status=204)
+
+ def test_update_policy_association_for_service(self):
+ self.check_service_client_function(
+ self.client.update_policy_association_for_service,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ policy_id=self.FAKE_POLICY_ID,
+ service_id=self.FAKE_SERVICE_ID,
+ status=204)
+
+ def test_show_policy_association_for_service(self):
+ self.check_service_client_function(
+ self.client.show_policy_association_for_service,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ {},
+ policy_id=self.FAKE_POLICY_ID,
+ service_id=self.FAKE_SERVICE_ID,
+ status=204)
+
+ def test_delete_policy_association_for_service(self):
+ self.check_service_client_function(
+ self.client.delete_policy_association_for_service,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ policy_id=self.FAKE_POLICY_ID,
+ service_id=self.FAKE_SERVICE_ID,
+ status=204)
+
+ def test_update_policy_association_for_region_and_service(self):
+ self.check_service_client_function(
+ self.client.update_policy_association_for_region_and_service,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ policy_id=self.FAKE_POLICY_ID,
+ service_id=self.FAKE_SERVICE_ID,
+ region_id=self.FAKE_REGION_ID,
+ status=204)
+
+ def test_show_policy_association_for_region_and_service(self):
+ self.check_service_client_function(
+ self.client.show_policy_association_for_region_and_service,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ {},
+ policy_id=self.FAKE_POLICY_ID,
+ service_id=self.FAKE_SERVICE_ID,
+ region_id=self.FAKE_REGION_ID,
+ status=204)
+
+ def test_delete_policy_association_for_region_and_service(self):
+ self.check_service_client_function(
+ self.client.delete_policy_association_for_region_and_service,
+ 'tempest.lib.common.rest_client.RestClient.delete',
+ {},
+ policy_id=self.FAKE_POLICY_ID,
+ service_id=self.FAKE_SERVICE_ID,
+ region_id=self.FAKE_REGION_ID,
+ status=204)