Merge "Add test coverage for bug 1943724"
diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst
index 7da8ddb..ecf2930 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -350,6 +350,10 @@
.. _2.32: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id29
+ * `2.33`_
+
+ .. _2.33: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id30
+
* `2.36`_
.. _2.36: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#microversion
diff --git a/playbooks/enable-fips.yaml b/playbooks/enable-fips.yaml
new file mode 100644
index 0000000..c8f042d
--- /dev/null
+++ b/playbooks/enable-fips.yaml
@@ -0,0 +1,4 @@
+- hosts: all
+ tasks:
+ - include_role:
+ name: enable-fips
diff --git a/releasenotes/notes/add-ssh-key-type-38d7a2f900d79842.yaml b/releasenotes/notes/add-ssh-key-type-38d7a2f900d79842.yaml
new file mode 100644
index 0000000..fef3004
--- /dev/null
+++ b/releasenotes/notes/add-ssh-key-type-38d7a2f900d79842.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Add parameter to specify the SSH key type. Current options are 'rsa'
+ (which is the default) and 'ecdsa'. Tempest now supports the importing
+ and generation of both 'rsa' and 'ecdsa' SSH key types.
diff --git a/releasenotes/notes/set-default-value-of-concurrency-to-2-d916d5c31e3725d5.yaml b/releasenotes/notes/set-default-value-of-concurrency-to-2-d916d5c31e3725d5.yaml
new file mode 100644
index 0000000..0d964a9
--- /dev/null
+++ b/releasenotes/notes/set-default-value-of-concurrency-to-2-d916d5c31e3725d5.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+ - |
+ [`bug 1948935 <https://bugs.launchpad.net/tempest/+bug/1948935>`_]
+ The default value of account-generator --concurrency parameter is now
+ set to 2 instead of 1.
diff --git a/requirements.txt b/requirements.txt
index c71cabe..bc8358b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,6 +6,7 @@
jsonschema>=3.2.0 # MIT
testtools>=2.2.0 # MIT
paramiko>=2.7.0 # LGPLv2.1+
+cryptography>=2.1 # BSD/Apache-2.0
netaddr>=0.7.18 # BSD
oslo.concurrency>=3.26.0 # Apache-2.0
oslo.config>=5.2.0 # Apache-2.0
diff --git a/tempest/api/compute/admin/test_hypervisor.py b/tempest/api/compute/admin/test_hypervisor.py
index 347193d..c7a1201 100644
--- a/tempest/api/compute/admin/test_hypervisor.py
+++ b/tempest/api/compute/admin/test_hypervisor.py
@@ -145,3 +145,26 @@
hypers = self.client.search_hypervisor(
hypers[0]['hypervisor_hostname'])['hypervisors']
self.assertNotEmpty(hypers, "No hypervisors found.")
+
+
+class HypervisorAdminV253TestBase(base.BaseV2ComputeAdminTest):
+ """Tests Hypervisors API above 2.53 that require admin privileges"""
+
+ min_microversion = '2.53'
+
+ @classmethod
+ def setup_clients(cls):
+ super(HypervisorAdminV253TestBase, cls).setup_clients()
+ cls.client = cls.os_admin.hypervisor_client
+
+ @decorators.idempotent_id('4ab54a14-77a2-4e39-b9d2-1306d157c705')
+ def test_list_show_detail_hypervisors(self):
+ """Verify the list, list details, and show hypevisors
+
+ This verify the Hypervisor API response schema with v2.53 microversion
+ """
+ self.client.list_hypervisors(
+ detail=True, with_servers=True)['hypervisors']
+ hypers = self.client.list_hypervisors(with_servers=True)['hypervisors']
+ self.client.show_hypervisor(
+ hypers[0]['id'], with_servers=True)['hypervisor']
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index ac18442..efecd6c 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -68,7 +68,8 @@
self.image_ssh_password,
validation_resources['keypair']['private_key'],
server=server,
- servers_client=self.servers_client)
+ servers_client=self.servers_client,
+ ssh_key_type=CONF.validation.ssh_key_type)
linux_client.validate_authentication()
def _create_server_get_interfaces(self):
diff --git a/tempest/clients.py b/tempest/clients.py
index 327f0da..4c3d875 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -118,7 +118,8 @@
self.server_groups_client = self.compute.ServerGroupsClient()
self.limits_client = self.compute.LimitsClient()
self.compute_images_client = self.compute.ImagesClient()
- self.keypairs_client = self.compute.KeyPairsClient()
+ self.keypairs_client = self.compute.KeyPairsClient(
+ ssh_key_type=CONF.validation.ssh_key_type)
self.quotas_client = self.compute.QuotasClient()
self.quota_classes_client = self.compute.QuotaClassesClient()
self.flavors_client = self.compute.FlavorsClient()
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index 917262e..ad0b547 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -81,11 +81,11 @@
will have the prefix with the given TAG in its name. Using tag is recommended
for the further using, cleaning resources.
-* ``-r, --concurrency CONCURRENCY`` (Optional) Concurrency count
- (default: 1). The number of accounts required can be estimated as
- CONCURRENCY x 2. Each user provided in *accounts.yaml* file will be in
- a different tenant. This is required to provide isolation between test for
- running in parallel.
+* ``-r, --concurrency CONCURRENCY`` (Optional) Concurrency count (default: 2).
+ The number of accounts generated will be same as CONCURRENCY. The higher the
+ number, the more tests will run in parallel. If you want to run tests
+ sequentially then use 1 as value for concurrency (beware that tests that need
+ more credentials will fail).
* ``--with-admin`` (Optional) Creates admin for each concurrent group
(default: False).
@@ -236,7 +236,7 @@
dest='tag',
help='Resources tag')
parser.add_argument('-r', '--concurrency',
- default=1,
+ default=2,
type=positive_int,
required=False,
dest='concurrency',
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index a062f6f..2443a67 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -197,6 +197,7 @@
body = clients.servers_client.create_server(name=name, imageRef=image_id,
flavorRef=flavor,
**kwargs)
+ request_id = body.response['x-openstack-request-id']
# handle the case of multiple servers
if multiple_create_request:
@@ -234,7 +235,8 @@
for server in servers:
try:
waiters.wait_for_server_status(
- clients.servers_client, server['id'], wait_until)
+ clients.servers_client, server['id'], wait_until,
+ request_id=request_id)
# Multiple validatable servers are not supported for now. Their
# creation will fail with the condition above.
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 5d6e129..9d9fab7 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -48,7 +48,8 @@
console_output_enabled=CONF.compute_feature_enabled.console_output,
ssh_shell_prologue=CONF.validation.ssh_shell_prologue,
ping_count=CONF.validation.ping_count,
- ping_size=CONF.validation.ping_size)
+ ping_size=CONF.validation.ping_size,
+ ssh_key_type=CONF.validation.ssh_key_type)
# Note that this method will not work on SLES11 guests, as they do
# not support the TYPE column on lsblk
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 1b69349..21d0109 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -32,7 +32,8 @@
# NOTE(afazekas): This function needs to know a token and a subject.
def wait_for_server_status(client, server_id, status, ready_wait=True,
- extra_timeout=0, raise_on_error=True):
+ extra_timeout=0, raise_on_error=True,
+ request_id=None):
"""Waits for a server to reach a given status."""
# NOTE(afazekas): UNKNOWN status possible on ERROR
@@ -71,11 +72,12 @@
'/'.join((server_status, str(task_state))),
time.time() - start_time)
if (server_status == 'ERROR') and raise_on_error:
+ details = ''
if 'fault' in body:
- raise exceptions.BuildErrorException(body['fault'],
- server_id=server_id)
- else:
- raise exceptions.BuildErrorException(server_id=server_id)
+ details += 'Fault: %s.' % body['fault']
+ if request_id:
+ details += ' Server boot request ID: %s.' % request_id
+ raise exceptions.BuildErrorException(details, server_id=server_id)
timed_out = int(time.time()) - start_time >= timeout
@@ -88,6 +90,8 @@
'status': status,
'expected_task_state': expected_task_state,
'timeout': timeout})
+ if request_id:
+ message += ' Server boot request ID: %s.' % request_id
message += ' Current status: %s.' % server_status
message += ' Current task state: %s.' % task_state
caller = test_utils.find_test_caller()
diff --git a/tempest/config.py b/tempest/config.py
index a840a97..03ddbf5 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -970,6 +970,10 @@
default='public',
help="Network used for SSH connections. Ignored if "
"connect_method=floating."),
+ cfg.StrOpt('ssh_key_type',
+ default='rsa',
+ help='Type of key to use for ssh connections. '
+ 'Valid types are rsa, ecdsa'),
]
volume_group = cfg.OptGroup(name='volume',
diff --git a/tempest/lib/api_schema/response/compute/v2_33/__init__.py b/tempest/lib/api_schema/response/compute/v2_33/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_33/__init__.py
diff --git a/tempest/lib/api_schema/response/compute/v2_33/hypervisors.py b/tempest/lib/api_schema/response/compute/v2_33/hypervisors.py
new file mode 100644
index 0000000..9773605
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_33/hypervisors.py
@@ -0,0 +1,53 @@
+# 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
+from tempest.lib.api_schema.response.compute.v2_28 \
+ import hypervisors as hypervisorsv228
+
+###########################################################################
+#
+# 2.33:
+#
+# hypervisor_links parameter is added to the response body for the following
+# APIs:
+#
+# - GET /os-hypervisors
+# - GET /os-hypervisors/detail
+###########################################################################
+list_search_hypervisors = copy.deepcopy(
+ hypervisorsv228.list_search_hypervisors)
+list_search_hypervisors['response_body']['properties'].update(
+ {'hypervisors_links': parameter_types.links}
+)
+
+list_hypervisors_detail = copy.deepcopy(
+ hypervisorsv228.list_hypervisors_detail)
+list_hypervisors_detail['response_body']['properties'].update(
+ {'hypervisors_links': parameter_types.links}
+)
+
+# NOTE(zhufl): Below are the unchanged schema in this microversion. We need
+# to keep this schema in this file to have the generic way to select the
+# right schema based on self.schema_versions_info mapping in service client.
+# ****** Schemas unchanged since microversion 2.28 ***
+get_hypervisor = copy.deepcopy(hypervisorsv228.get_hypervisor)
+hypervisor_detail = copy.deepcopy(hypervisorsv228.hypervisor_detail)
+get_hypervisor_statistics = \
+ copy.deepcopy(hypervisorsv228.get_hypervisor_statistics)
+get_hypervisor_uptime = copy.deepcopy(hypervisorsv228.get_hypervisor_uptime)
+get_hypervisors_servers = copy.deepcopy(
+ hypervisorsv228.get_hypervisors_servers)
diff --git a/tempest/lib/api_schema/response/compute/v2_53/hypervisors.py b/tempest/lib/api_schema/response/compute/v2_53/hypervisors.py
new file mode 100644
index 0000000..e172f1f
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_53/hypervisors.py
@@ -0,0 +1,68 @@
+# 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_33 \
+ import hypervisors as hypervisorsv233
+
+###########################################################################
+#
+# 2.53:
+#
+# servers parameter is added to the response body for the following
+# APIs:
+#
+# - GET /os-hypervisor
+# - GET /os-hypervisors
+# - GET /os-hypervisors/detail
+#
+###########################################################################
+
+servers = {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'uuid': {'type': 'string', 'format': 'uuid'},
+ 'name': {'type': 'string'},
+ },
+ 'additionalProperties': False,
+ },
+}
+
+hypervisor_detail = copy.deepcopy(hypervisorsv233.hypervisor_detail)
+hypervisor_detail['properties'].update({'servers': servers})
+get_hypervisor = copy.deepcopy(hypervisorsv233.get_hypervisor)
+get_hypervisor['response_body']['properties'].update(
+ {'hypervisor': hypervisor_detail})
+list_hypervisors_detail = copy.deepcopy(
+ hypervisorsv233.list_hypervisors_detail)
+list_hypervisors_detail['response_body']['properties']['hypervisors'].update(
+ {'items': hypervisor_detail})
+
+list_search_hypervisors = copy.deepcopy(
+ hypervisorsv233.list_search_hypervisors)
+list_search_hypervisors['response_body']['properties']['hypervisors'][
+ 'items']['properties'].update({'servers': servers})
+
+# NOTE(zhufl): Below are the unchanged schema in this microversion. We need
+# to keep this schema in this file to have the generic way to select the
+# right schema based on self.schema_versions_info mapping in service client.
+# ****** Schemas unchanged since microversion 2.33 ***
+get_hypervisor_statistics = \
+ copy.deepcopy(hypervisorsv233.get_hypervisor_statistics)
+get_hypervisor_uptime = copy.deepcopy(hypervisorsv233.get_hypervisor_uptime)
+get_hypervisors_servers = copy.deepcopy(
+ hypervisorsv233.get_hypervisors_servers)
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index 3f735f5..ef14dfc 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -907,8 +907,8 @@
if int(time.time()) - start_time >= self.build_timeout:
message = ('Failed to delete %(resource_type)s %(id)s within '
'the required time (%(timeout)s s). Timer started '
- 'at %(start_time)s. Timer ended at %(end_time)s'
- 'waited for %(wait_time)s' %
+ 'at %(start_time)s. Timer ended at %(end_time)s. '
+ 'Waited for %(wait_time)s s.' %
{'resource_type': self.resource_type, 'id': id,
'timeout': self.build_timeout,
'start_time': start_time,
diff --git a/tempest/lib/common/ssh.py b/tempest/lib/common/ssh.py
index ee15375..eb03faa 100644
--- a/tempest/lib/common/ssh.py
+++ b/tempest/lib/common/ssh.py
@@ -37,7 +37,7 @@
def __init__(self, host, username, password=None, timeout=300, pkey=None,
channel_timeout=10, look_for_keys=False, key_filename=None,
- port=22, proxy_client=None):
+ port=22, proxy_client=None, ssh_key_type='rsa'):
"""SSH client.
Many of parameters are just passed to the underlying implementation
@@ -59,6 +59,7 @@
:param proxy_client: Another SSH client to provide a transport
for ssh-over-ssh. The default is None, which means
not to use ssh-over-ssh.
+ :param ssh_key_type: ssh key type (rsa, ecdsa)
:type proxy_client: ``tempest.lib.common.ssh.Client`` object
"""
self.host = host
@@ -66,8 +67,15 @@
self.port = port
self.password = password
if isinstance(pkey, str):
- pkey = paramiko.RSAKey.from_private_key(
- io.StringIO(str(pkey)))
+ if ssh_key_type == 'rsa':
+ pkey = paramiko.RSAKey.from_private_key(
+ io.StringIO(str(pkey)))
+ elif ssh_key_type == 'ecdsa':
+ pkey = paramiko.ECDSAKey.from_private_key(
+ io.StringIO(str(pkey)))
+ else:
+ raise exceptions.SSHClientUnsupportedKeyType(
+ key_type=ssh_key_type)
self.pkey = pkey
self.look_for_keys = look_for_keys
self.key_filename = key_filename
diff --git a/tempest/lib/common/utils/linux/remote_client.py b/tempest/lib/common/utils/linux/remote_client.py
index d84dd28..224f3bf 100644
--- a/tempest/lib/common/utils/linux/remote_client.py
+++ b/tempest/lib/common/utils/linux/remote_client.py
@@ -69,7 +69,7 @@
server=None, servers_client=None, ssh_timeout=300,
connect_timeout=60, console_output_enabled=True,
ssh_shell_prologue="set -eu -o pipefail; PATH=$PATH:/sbin;",
- ping_count=1, ping_size=56):
+ ping_count=1, ping_size=56, ssh_key_type='rsa'):
"""Executes commands in a VM over ssh
:param ip_address: IP address to ssh to
@@ -84,6 +84,7 @@
:param ssh_shell_prologue: Shell fragments to use before command
:param ping_count: Number of ping packets
:param ping_size: Packet size for ping packets
+ :param ssh_key_type: ssh key type (rsa, ecdsa)
"""
self.server = server
self.servers_client = servers_client
@@ -92,10 +93,12 @@
self.ssh_shell_prologue = ssh_shell_prologue
self.ping_count = ping_count
self.ping_size = ping_size
+ self.ssh_key_type = ssh_key_type
self.ssh_client = ssh.Client(ip_address, username, password,
ssh_timeout, pkey=pkey,
- channel_timeout=connect_timeout)
+ channel_timeout=connect_timeout,
+ ssh_key_type=ssh_key_type)
@debug_ssh
def exec_command(self, cmd):
diff --git a/tempest/lib/exceptions.py b/tempest/lib/exceptions.py
index abe68d2..dd7885e 100644
--- a/tempest/lib/exceptions.py
+++ b/tempest/lib/exceptions.py
@@ -256,6 +256,10 @@
"%(port)s and username: %(username)s as parent")
+class SSHClientUnsupportedKeyType(TempestException):
+ message = ("SSH client: unsupported key type %(key_type)s")
+
+
class UnknownServiceClient(TempestException):
message = "Service clients named %(services)s are not known"
diff --git a/tempest/lib/services/compute/hypervisor_client.py b/tempest/lib/services/compute/hypervisor_client.py
index 1cbfcc3..e237845 100644
--- a/tempest/lib/services/compute/hypervisor_client.py
+++ b/tempest/lib/services/compute/hypervisor_client.py
@@ -13,12 +13,18 @@
# License for the specific language governing permissions and limitations
# under the License.
+from urllib import parse as urllib
+
from oslo_serialization import jsonutils as json
from tempest.lib.api_schema.response.compute.v2_1 \
import hypervisors as schemav21
from tempest.lib.api_schema.response.compute.v2_28 \
import hypervisors as schemav228
+from tempest.lib.api_schema.response.compute.v2_33 \
+ import hypervisors as schemav233
+from tempest.lib.api_schema.response.compute.v2_53 \
+ import hypervisors as schemav253
from tempest.lib.common import rest_client
from tempest.lib.services.compute import base_compute_client
@@ -27,9 +33,11 @@
schema_versions_info = [
{'min': None, 'max': '2.27', 'schema': schemav21},
- {'min': '2.28', 'max': None, 'schema': schemav228}]
+ {'min': '2.28', 'max': '2.32', 'schema': schemav228},
+ {'min': '2.33', 'max': '2.52', 'schema': schemav233},
+ {'min': '2.53', 'max': None, 'schema': schemav253}]
- def list_hypervisors(self, detail=False):
+ def list_hypervisors(self, detail=False, **kwargs):
"""List hypervisors information."""
url = 'os-hypervisors'
schema = self.get_schema(self.schema_versions_info)
@@ -37,14 +45,19 @@
if detail:
url += '/detail'
_schema = schema.list_hypervisors_detail
+ if kwargs:
+ url += '?%s' % urllib.urlencode(kwargs)
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(_schema, resp, body)
return rest_client.ResponseBody(resp, body)
- def show_hypervisor(self, hypervisor_id):
+ def show_hypervisor(self, hypervisor_id, **kwargs):
"""Display the details of the specified hypervisor."""
+ url = 'os-hypervisors/%s' % hypervisor_id
+ if kwargs:
+ url += '?%s' % urllib.urlencode(kwargs)
resp, body = self.get('os-hypervisors/%s' % hypervisor_id)
body = json.loads(body)
schema = self.get_schema(self.schema_versions_info)
diff --git a/tempest/lib/services/compute/keypairs_client.py b/tempest/lib/services/compute/keypairs_client.py
index 9d7b7fc..51a4583 100644
--- a/tempest/lib/services/compute/keypairs_client.py
+++ b/tempest/lib/services/compute/keypairs_client.py
@@ -15,6 +15,10 @@
from urllib import parse as urllib
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives.asymmetric import ec
+from cryptography.hazmat.primitives import serialization
+
from oslo_serialization import jsonutils as json
from tempest.lib.api_schema.response.compute.v2_1 import keypairs as schemav21
@@ -28,6 +32,12 @@
schema_versions_info = [{'min': None, 'max': '2.1', 'schema': schemav21},
{'min': '2.2', 'max': None, 'schema': schemav22}]
+ def __init__(self, auth_provider, service, region,
+ ssh_key_type='rsa', **kwargs):
+ super(KeyPairsClient, self).__init__(
+ auth_provider, service, region, **kwargs)
+ self.ssh_key_type = ssh_key_type
+
def list_keypairs(self, **params):
"""Lists keypairs that are associated with the account.
@@ -67,12 +77,30 @@
API reference:
https://docs.openstack.org/api-ref/compute/#create-or-import-keypair
"""
+ pkey = None
+ if (self.ssh_key_type == 'ecdsa' and 'public_key' not in kwargs and
+ ('type' not in kwargs or kwargs['type'] == 'ssh')):
+ # create a ecdsa key and pass the public key into the request
+ pkey = ec.generate_private_key(ec.SECP384R1(), default_backend())
+ pubkey = pkey.public_key().public_bytes(
+ encoding=serialization.Encoding.OpenSSH,
+ format=serialization.PublicFormat.OpenSSH)
+ kwargs['public_key'] = pubkey
+
post_body = json.dumps({'keypair': kwargs})
resp, body = self.post("os-keypairs", body=post_body)
body = json.loads(body)
schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.create_keypair, resp, body)
- return rest_client.ResponseBody(resp, body)
+ resp_body = rest_client.ResponseBody(resp, body)
+ if pkey:
+ # add the privkey to the response as it was generated here
+ privkey = pkey.private_bytes(
+ encoding=serialization.Encoding.PEM,
+ format=serialization.PrivateFormat.TraditionalOpenSSL,
+ encryption_algorithm=serialization.NoEncryption())
+ resp_body['keypair']['private_key'] = privkey.decode('utf-8')
+ return resp_body
def delete_keypair(self, keypair_name, **params):
"""Deletes a keypair.
diff --git a/zuul.d/integrated-gate.yaml b/zuul.d/integrated-gate.yaml
index b86268a..1051ccc 100644
--- a/zuul.d/integrated-gate.yaml
+++ b/zuul.d/integrated-gate.yaml
@@ -296,6 +296,22 @@
TEMPEST_VOLUME_TYPE: volumev2
- job:
+ name: tempest-centos8-stream-fips
+ parent: devstack-tempest
+ description: |
+ Integration testing for a FIPS enabled Centos 8 system
+ nodeset: devstack-single-node-centos-8-stream
+ pre-run: playbooks/enable-fips.yaml
+ vars:
+ tox_envlist: full
+ configure_swap_size: 4096
+ devstack_local_conf:
+ test-config:
+ "$TEMPEST_CONFIG":
+ validation:
+ ssh_key_type: 'ecdsa'
+
+- job:
name: tempest-pg-full
parent: tempest-full-py3
description: |
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 9ab10d7..3f98f7e 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -161,6 +161,8 @@
irrelevant-files: *tempest-irrelevant-files
- tempest-full-py3-opensuse15:
irrelevant-files: *tempest-irrelevant-files
+ - tempest-centos8-stream-fips:
+ irrelevant-files: *tempest-irrelevant-files
periodic-stable:
jobs:
- tempest-full-xena