Add a TLS scenario using Barbican

This patch adds a TLS load balancer scenario test using Barbican.

Story: 1627383
Task: 5149

Change-Id: I7013888f94261d94e1cd4c3167dc84da7125d1da
This commit is contained in:
Michael Johnson 2019-01-02 16:58:21 -08:00
parent f3f25825c2
commit 0a0f9b342a
11 changed files with 547 additions and 15 deletions

View File

@ -2,7 +2,7 @@
# of appearance. Changing the order has an impact on the overall integration # of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later. # process, which may cause wedges in the gate later.
sphinxcontrib-apidoc # BSD sphinxcontrib-apidoc>=0.2.0 # BSD
sphinx>=1.6.2,!=1.6.6,!=1.6.7 # BSD sphinx>=1.6.2,!=1.6.6,!=1.6.7 # BSD
openstackdocstheme>=1.18.1 # Apache-2.0 openstackdocstheme>=1.18.1 # Apache-2.0

View File

@ -0,0 +1,88 @@
# Copyright 2019 Rackspace US Inc. 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 barbicanclient import client
from keystoneauth1 import identity
from keystoneauth1 import session
from oslo_log import log as logging
from tempest.lib.common.utils import data_utils
LOG = logging.getLogger(__name__)
class BarbicanClientManager(object):
"""Class for interacting with the barbican service.
This class is an abstraction for interacting with the barbican service.
This class currently uses the barbican client code to access barbican due
to the following reasons:
1. Octavia users typically load secrets into barbican via the client.
2. The barbican-tempest-plugin is lightly tested (no py3 tests, etc.).
3. barbican-tempest-plugin is not in global requirements.
This led to the decision to not use the service client in the
barbican-tempest-plugin.
In the future it may be better to use the barbican-tempest-plugin
service client or the openstacksdk.
"""
def __init__(self, tempest_client_mgr):
"""Setup the barbican client.
:param tempest_client_mgr: A tempest client manager object, such as
os_primary.
"""
# Convert the tempest credential passed in into a keystone session
auth_provider = tempest_client_mgr.auth_provider
cert_validation = False
if not auth_provider.dscv:
cert_validation = auth_provider.ca_certs
credentials = tempest_client_mgr.credentials
keystone_auth = identity.v3.Token(
auth_url=auth_provider.auth_url,
token=auth_provider.get_token(),
project_id=credentials.project_id,
project_name=credentials.project_name,
project_domain_id=credentials.project_domain_id,
project_domain_name=credentials.project_domain_name)
id_session = session.Session(auth=keystone_auth,
verify=cert_validation)
# Setup the barbican client
self.barbican = client.Client(session=id_session)
def store_secret(self, pkcs12_secret):
"""Store a secret in barbican.
:param pkcs12_secret: A pkcs12 secret.
:returns: The barbican secret_ref.
"""
p12_secret = self.barbican.secrets.create()
p12_secret.name = data_utils.rand_name("lb_member_barbican_pkcs12")
p12_secret.payload = pkcs12_secret
secret_ref = p12_secret.store()
LOG.debug('Secret {0} has ref {1}'.format(p12_secret.name, secret_ref))
return secret_ref
def delete_secret(self, secret_ref):
self.barbican.secrets.delete(secret_ref)
def add_acl(self, secret_ref, user_id):
acl_entity = self.barbican.acls.create(entity_ref=secret_ref,
users=[user_id],
project_access=True)
acl_ref = acl_entity.submit()
LOG.debug('Secret ACL {0} added user {1}'.format(acl_ref, user_id))
return acl_ref

View File

@ -0,0 +1,130 @@
# Copyright 2018 Rackspace US Inc. 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 datetime
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from cryptography import x509
from cryptography.x509.oid import NameOID
import OpenSSL
def generate_ca_cert_and_key():
"""Creates a CA cert and key for testing.
:returns: The cryptography CA cert and CA key objects.
"""
ca_key = rsa.generate_private_key(
public_exponent=65537, key_size=2048, backend=default_backend())
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Denial"),
x509.NameAttribute(NameOID.LOCALITY_NAME, u"Corvallis"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"OpenStack"),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"Octavia"),
x509.NameAttribute(NameOID.COMMON_NAME, u"ca_cert.example.com"),
])
ca_cert = x509.CertificateBuilder().subject_name(
subject
).issuer_name(
issuer
).public_key(
ca_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
datetime.datetime.utcnow()
).not_valid_after(
datetime.datetime.utcnow() + datetime.timedelta(days=10)
).add_extension(
x509.SubjectAlternativeName([x509.DNSName(u"ca_cert.example.com")]),
critical=False,
).add_extension(
x509.BasicConstraints(ca=True, path_length=None),
critical=True,
).sign(ca_key, hashes.SHA256(), default_backend())
return ca_cert, ca_key
def generate_server_cert_and_key(ca_cert, ca_key, server_uuid):
"""Creates a server cert and key for testing.
:param ca_cert: A cryptography CA certificate (x509) object.
:param ca_key: A cryptography CA key (x509) object.
:param server_uuid: A UUID identifying the server.
:returns: The cryptography server cert and key objects.
"""
server_key = rsa.generate_private_key(
public_exponent=65537, key_size=2048, backend=default_backend())
subject = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"Denial"),
x509.NameAttribute(NameOID.LOCALITY_NAME, u"Corvallis"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"OpenStack"),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"Octavia"),
x509.NameAttribute(NameOID.COMMON_NAME, u"{}.example.com".format(
server_uuid)),
])
server_cert = x509.CertificateBuilder().subject_name(
subject
).issuer_name(
ca_cert.subject
).public_key(
server_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
datetime.datetime.utcnow()
).not_valid_after(
datetime.datetime.utcnow() + datetime.timedelta(days=10)
).add_extension(
x509.SubjectAlternativeName(
[x509.DNSName(u"{}.example.com".format(server_uuid))]),
critical=False,
).add_extension(
x509.BasicConstraints(ca=False, path_length=None),
critical=True,
).sign(ca_key, hashes.SHA256(), default_backend())
return server_cert, server_key
def generate_pkcs12_bundle(server_cert, server_key):
"""Creates a pkcs12 formated bundle.
Note: This uses pyOpenSSL as the cryptography package does not yet
support creating pkcs12 bundles. The currently un-released
2.5 version of cryptography supports reading pkcs12, but not
creation. This method should be updated to only use
cryptography once it supports creating pkcs12 bundles.
:param server_cert: A cryptography certificate (x509) object.
:param server_key: A cryptography key (x509) object.
:returns: A pkcs12 bundle.
"""
# TODO(johnsom) Replace with cryptography once it supports creating pkcs12
pkcs12 = OpenSSL.crypto.PKCS12()
pkcs12.set_privatekey(
OpenSSL.crypto.PKey.from_cryptography_key(server_key))
pkcs12.set_certificate(OpenSSL.crypto.X509.from_cryptography(server_cert))
return pkcs12.export()

View File

@ -14,9 +14,13 @@
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log as logging
from octavia_tempest_plugin.common import constants as const from octavia_tempest_plugin.common import constants as const
LOG = logging.getLogger(__name__)
service_available_group = cfg.OptGroup(name='service_available', service_available_group = cfg.OptGroup(name='service_available',
title='Available OpenStack Services') title='Available OpenStack Services')
@ -27,6 +31,19 @@ ServiceAvailableGroup = [
"to be available."), "to be available."),
] ]
# Pull in the service_available for barbican if it is not defined.
# If the barbican tempest plugin isn't loaded, this won't load from
# tempest.conf.
try:
if cfg.CONF.service_available.barbican is not None:
LOG.info('Barbican service_available state: {}'.format(
cfg.CONF.service_available.barbican))
except cfg.NoSuchOptError:
ServiceAvailableGroup.append(
cfg.BoolOpt('barbican', default=False,
help="Whether or not the barbican service is expected to "
"be available."))
octavia_group = cfg.OptGroup(name='load_balancer', octavia_group = cfg.OptGroup(name='load_balancer',
title='load-balancer service options') title='load-balancer service options')
@ -54,6 +71,9 @@ OctaviaGroup = [
default=300, default=300,
help='Timeout in seconds to wait for non-load-balancer ' help='Timeout in seconds to wait for non-load-balancer '
'resources to build'), 'resources to build'),
cfg.StrOpt('octavia_svc_username', default='admin',
help='The service_auth username the Octavia services are using'
'to access other OpenStack services.'),
# load-balancer specific options # load-balancer specific options
cfg.IntOpt('check_interval', cfg.IntOpt('check_interval',
default=5, default=5,
@ -152,4 +172,8 @@ LBFeatureEnabledGroup = [
default=True, default=True,
help="Whether Health Monitor is available with provider" help="Whether Health Monitor is available with provider"
" driver or not."), " driver or not."),
cfg.BoolOpt('terminated_tls_enabled',
default=True,
help="Whether TLS termination is available with provider "
"driver or not."),
] ]

View File

@ -0,0 +1,274 @@
# Copyright 2019 Rackspace US Inc. 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 base64
import socket
from cryptography.hazmat.primitives import serialization
from OpenSSL.crypto import X509
from OpenSSL import SSL
from oslo_log import log as logging
from oslo_utils import uuidutils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from octavia_lib.common import constants as lib_consts
from octavia_tempest_plugin.common import barbican_client_mgr
from octavia_tempest_plugin.common import cert_utils
from octavia_tempest_plugin.common import constants as const
from octavia_tempest_plugin.tests import test_base
from octavia_tempest_plugin.tests import waiters
CONF = config.CONF
LOG = logging.getLogger(__name__)
class TLSWithBarbicanTest(test_base.LoadBalancerBaseTestWithCompute):
@classmethod
def skip_checks(cls):
super(TLSWithBarbicanTest, cls).skip_checks()
if not CONF.loadbalancer_feature_enabled.terminated_tls_enabled:
raise cls.skipException('[loadbalancer-feature-enabled] '
'"terminated_tls_enabled" is False in '
'the tempest configuration. TLS tests '
'will be skipped.')
if not CONF.validation.run_validation:
raise cls.skipException('Traffic tests will not work without '
'run_validation enabled.')
if not CONF.service_available.barbican:
raise cls.skipException('TLS with Barbican tests require the '
'barbican service.')
@classmethod
def resource_setup(cls):
"""Setup resources needed by the tests."""
super(TLSWithBarbicanTest, cls).resource_setup()
# Create a CA self-signed cert and key
cls.ca_cert, ca_key = cert_utils.generate_ca_cert_and_key()
LOG.debug('CA Cert: %s' % cls.ca_cert.public_bytes(
serialization.Encoding.PEM))
LOG.debug('CA private Key: %s' % ca_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()))
LOG.debug('CA public Key: %s' % ca_key.public_key().public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo))
# Create a server cert and key
cls.server_uuid = uuidutils.generate_uuid()
server_cert, server_key = cert_utils.generate_server_cert_and_key(
cls.ca_cert, ca_key, cls.server_uuid)
LOG.debug('Server Cert: %s' % server_cert.public_bytes(
serialization.Encoding.PEM))
LOG.debug('Server private Key: %s' % server_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()))
server_public_key = server_key.public_key()
LOG.debug('Server public Key: %s' % server_public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo))
# Create the pkcs12 bundle
pkcs12 = cert_utils.generate_pkcs12_bundle(server_cert, server_key)
LOG.debug('Server PKCS12 bundle: %s' % base64.b64encode(pkcs12))
# Load the secret into the barbican service under the
# os_roles_lb_member tenant
barbican_mgr = barbican_client_mgr.BarbicanClientManager(
cls.os_roles_lb_member)
cls.secret_ref = barbican_mgr.store_secret(pkcs12)
cls.addClassResourceCleanup(barbican_mgr.delete_secret, cls.secret_ref)
# Set the barbican ACL if the Octavia API version doesn't do it
# automatically.
if not cls.mem_lb_client.is_version_supported(
cls.api_version, '2.1'):
user_list = cls.os_admin.users_v3_client.list_users(
name=CONF.load_balancer.octavia_svc_username)
msg = 'Only one user named "{0}" should exist, {1} found.'.format(
CONF.load_balancer.octavia_svc_username,
len(user_list['users']))
assert 1 == len(user_list['users']), msg
barbican_mgr.add_acl(cls.secret_ref, user_list['users'][0]['id'])
# Setup a load balancer for the tests to use
lb_name = data_utils.rand_name("lb_member_lb1-tls")
lb_kwargs = {const.PROVIDER: CONF.load_balancer.provider,
const.NAME: lb_name}
# TODO(johnsom) Update for IPv6
cls._setup_lb_network_kwargs(lb_kwargs, 4)
lb = cls.mem_lb_client.create_loadbalancer(**lb_kwargs)
cls.lb_id = lb[const.ID]
cls.addClassResourceCleanup(
cls.mem_lb_client.cleanup_loadbalancer,
cls.lb_id)
waiters.wait_for_status(cls.mem_lb_client.show_loadbalancer,
cls.lb_id, const.PROVISIONING_STATUS,
const.ACTIVE,
CONF.load_balancer.lb_build_interval,
CONF.load_balancer.lb_build_timeout)
if CONF.validation.connect_method == 'floating':
port_id = lb[const.VIP_PORT_ID]
result = cls.lb_mem_float_ip_client.create_floatingip(
floating_network_id=CONF.network.public_network_id,
port_id=port_id)
floating_ip = result['floatingip']
LOG.info('lb1_floating_ip: {}'.format(floating_ip))
cls.addClassResourceCleanup(
waiters.wait_for_not_found,
cls.lb_mem_float_ip_client.delete_floatingip,
cls.lb_mem_float_ip_client.show_floatingip,
floatingip_id=floating_ip['id'])
cls.lb_vip_address = floating_ip['floating_ip_address']
else:
cls.lb_vip_address = lb[const.VIP_ADDRESS]
pool_name = data_utils.rand_name("lb_member_pool1-tls")
pool_kwargs = {
const.NAME: pool_name,
const.PROTOCOL: const.HTTP,
const.LB_ALGORITHM: const.LB_ALGORITHM_ROUND_ROBIN,
const.LOADBALANCER_ID: cls.lb_id,
}
pool = cls.mem_pool_client.create_pool(**pool_kwargs)
cls.pool_id = pool[const.ID]
cls.addClassResourceCleanup(
cls.mem_pool_client.cleanup_pool,
cls.pool_id,
lb_client=cls.mem_lb_client, lb_id=cls.lb_id)
waiters.wait_for_status(cls.mem_lb_client.show_loadbalancer,
cls.lb_id, const.PROVISIONING_STATUS,
const.ACTIVE,
CONF.load_balancer.build_interval,
CONF.load_balancer.build_timeout)
# Set up Member 1 for Webserver 1
member1_name = data_utils.rand_name("lb_member_member1-tls")
member1_kwargs = {
const.POOL_ID: cls.pool_id,
const.NAME: member1_name,
const.ADMIN_STATE_UP: True,
const.ADDRESS: cls.webserver1_ip,
const.PROTOCOL_PORT: 80,
}
if cls.lb_member_1_subnet:
member1_kwargs[const.SUBNET_ID] = cls.lb_member_1_subnet[const.ID]
member1 = cls.mem_member_client.create_member(
**member1_kwargs)
cls.addClassResourceCleanup(
cls.mem_member_client.cleanup_member,
member1[const.ID], pool_id=cls.pool_id,
lb_client=cls.mem_lb_client, lb_id=cls.lb_id)
waiters.wait_for_status(
cls.mem_lb_client.show_loadbalancer, cls.lb_id,
const.PROVISIONING_STATUS, const.ACTIVE,
CONF.load_balancer.check_interval,
CONF.load_balancer.check_timeout)
# Set up Member 2 for Webserver 2
member2_name = data_utils.rand_name("lb_member_member2-tls")
member2_kwargs = {
const.POOL_ID: cls.pool_id,
const.NAME: member2_name,
const.ADMIN_STATE_UP: True,
const.ADDRESS: cls.webserver2_ip,
const.PROTOCOL_PORT: 80,
}
if cls.lb_member_2_subnet:
member2_kwargs[const.SUBNET_ID] = cls.lb_member_2_subnet[const.ID]
member2 = cls.mem_member_client.create_member(
**member2_kwargs)
cls.addClassResourceCleanup(
cls.mem_member_client.cleanup_member,
member2[const.ID], pool_id=cls.pool_id,
lb_client=cls.mem_lb_client, lb_id=cls.lb_id)
waiters.wait_for_status(
cls.mem_lb_client.show_loadbalancer, cls.lb_id,
const.PROVISIONING_STATUS, const.ACTIVE,
CONF.load_balancer.check_interval,
CONF.load_balancer.check_timeout)
@decorators.idempotent_id('887ece26-0f7b-4933-89ab-5bb00b106ee0')
def test_basic_tls_traffic(self):
listener_name = data_utils.rand_name("lb_member_listener1-tls")
listener_kwargs = {
const.NAME: listener_name,
const.PROTOCOL: lib_consts.PROTOCOL_TERMINATED_HTTPS,
const.PROTOCOL_PORT: '443',
const.LOADBALANCER_ID: self.lb_id,
const.DEFAULT_POOL_ID: self.pool_id,
const.DEFAULT_TLS_CONTAINER_REF: self.secret_ref,
}
listener = self.mem_listener_client.create_listener(**listener_kwargs)
self.listener_id = listener[const.ID]
self.addCleanup(
self.mem_listener_client.cleanup_listener,
self.listener_id,
lb_client=self.mem_lb_client, lb_id=self.lb_id)
waiters.wait_for_status(self.mem_lb_client.show_loadbalancer,
self.lb_id, const.PROVISIONING_STATUS,
const.ACTIVE,
CONF.load_balancer.build_interval,
CONF.load_balancer.build_timeout)
# Test HTTPS listener load balancing.
# Note: certificate validation tests will follow this test
self.check_members_balanced(self.lb_vip_address, protocol='https',
verify=False)
def _verify_cb(connection, x509, errno, errdepth, retcode):
"""Callback for certificate validation."""
# don't validate names of root certificates
if errdepth != 0:
return True
if errno == 0:
# Make sure the certificate is the one we generated
self.assertEqual('{}.example.com'.format(self.server_uuid),
x509.get_subject().commonName)
else:
LOG.error('Certificate with CN: {0} failed validation with '
'OpenSSL verify errno {1}'.format(
x509.get_subject().commonName, errno))
return False
return True
context = SSL.Context(SSL.SSLv23_METHOD)
context.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
_verify_cb)
ca_store = context.get_cert_store()
ca_store.add_cert(X509.from_cryptography(self.ca_cert))
sock = socket.socket()
sock = SSL.Connection(context, sock)
sock.connect((self.lb_vip_address, 443))
# Validate the certificate is signed by the ca_cert we created
sock.do_handshake()

View File

@ -766,13 +766,15 @@ class LoadBalancerBaseTestWithCompute(LoadBalancerBaseTest):
URL = 'http://{0}:81'.format(ip_address) URL = 'http://{0}:81'.format(ip_address)
validators.validate_URL_response(URL, expected_body=str(start_id + 1)) validators.validate_URL_response(URL, expected_body=str(start_id + 1))
def _wait_for_lb_functional(self, vip_address): def _wait_for_lb_functional(self, vip_address,
protocol='http', verify=True):
session = requests.Session() session = requests.Session()
start = time.time() start = time.time()
while time.time() - start < CONF.load_balancer.build_timeout: while time.time() - start < CONF.load_balancer.build_timeout:
try: try:
session.get("http://{0}".format(vip_address), timeout=2) session.get("{0}://{1}".format(protocol, vip_address),
timeout=2, verify=verify)
time.sleep(1) time.sleep(1)
return return
except Exception: except Exception:
@ -782,20 +784,21 @@ class LoadBalancerBaseTestWithCompute(LoadBalancerBaseTest):
'period. Failing test.') 'period. Failing test.')
raise Exception() raise Exception()
def check_members_balanced(self, vip_address, traffic_member_count=2): def check_members_balanced(self, vip_address, traffic_member_count=2,
protocol='http', verify=True):
session = requests.Session() session = requests.Session()
response_counts = {} response_counts = {}
if ipaddress.ip_address(vip_address).version == 6: if ipaddress.ip_address(vip_address).version == 6:
vip_address = '[{}]'.format(vip_address) vip_address = '[{}]'.format(vip_address)
self._wait_for_lb_functional(vip_address) self._wait_for_lb_functional(vip_address, protocol, verify)
# Send a number requests to lb vip # Send a number requests to lb vip
for i in range(20): for i in range(20):
try: try:
r = session.get('http://{0}'.format(vip_address), r = session.get('{0}://{1}'.format(protocol, vip_address),
timeout=2) timeout=2, verify=verify)
if r.content in response_counts: if r.content in response_counts:
response_counts[r.content] += 1 response_counts[r.content] += 1

View File

@ -2,13 +2,17 @@
# of appearance. Changing the order has an impact on the overall integration # of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later. # process, which may cause wedges in the gate later.
cryptography>=2.1 # BSD/Apache-2.0
python-dateutil>=2.5.3 # BSD python-dateutil>=2.5.3 # BSD
ipaddress>=1.0.17;python_version<'3.3' # PSF ipaddress>=1.0.17;python_version<'3.3' # PSF
pbr!=2.1.0,>=2.0.0 # Apache-2.0 pbr!=2.1.0,>=2.0.0 # Apache-2.0
octavia-lib>=1.0.0 # Apache-2.0
oslo.config>=5.2.0 # Apache-2.0 oslo.config>=5.2.0 # Apache-2.0
oslo.log>=3.36.0 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0
oslotest>=3.2.0 # Apache-2.0 oslotest>=3.2.0 # Apache-2.0
python-barbicanclient>=4.5.2 # Apache-2.0
pyOpenSSL>=17.1.0 # Apache-2.0
requests>=2.14.2 # Apache-2.0 requests>=2.14.2 # Apache-2.0
six>=1.10.0 # MIT six>=1.10.0 # MIT
tempest>=17.1.0 # Apache-2.0 tempest>=17.1.0 # Apache-2.0

View File

@ -87,17 +87,13 @@
parent: octavia-dsvm-base parent: octavia-dsvm-base
timeout: 9000 timeout: 9000
required-projects: required-projects:
- openstack/barbican
- openstack/diskimage-builder - openstack/diskimage-builder
- openstack/python-barbicanclient
vars: vars:
devstack_localrc: devstack_localrc:
DIB_LOCAL_ELEMENTS: openstack-ci-mirrors DIB_LOCAL_ELEMENTS: openstack-ci-mirrors
devstack_services: devstack_services:
barbican: true
neutron-qos: true neutron-qos: true
devstack_plugins: devstack_plugins:
barbican: https://git.openstack.org/openstack/barbican.git
neutron: https://git.openstack.org/openstack/neutron.git neutron: https://git.openstack.org/openstack/neutron.git
zuul_copy_output: zuul_copy_output:
'/var/log/dib-build' : logs '/var/log/dib-build' : logs
@ -108,9 +104,7 @@
nodeset: octavia-two-node nodeset: octavia-two-node
timeout: 9000 timeout: 9000
required-projects: required-projects:
- openstack/barbican
- openstack/diskimage-builder - openstack/diskimage-builder
- openstack/python-barbicanclient
host-vars: host-vars:
controller: controller:
devstack_localrc: devstack_localrc:
@ -143,7 +137,6 @@
OCTAVIA_NODES: "main:{{ hostvars['controller']['nodepool']['private_ipv4'] }},second:{{ hostvars['controller2']['nodepool']['private_ipv4'] }}" OCTAVIA_NODES: "main:{{ hostvars['controller']['nodepool']['private_ipv4'] }},second:{{ hostvars['controller2']['nodepool']['private_ipv4'] }}"
OCTAVIA_USE_PREGENERATED_CERTS: true OCTAVIA_USE_PREGENERATED_CERTS: true
devstack_plugins: devstack_plugins:
barbican: https://git.openstack.org/openstack/barbican.git
neutron: https://git.openstack.org/openstack/neutron.git neutron: https://git.openstack.org/openstack/neutron.git
octavia: https://git.openstack.org/openstack/octavia.git octavia: https://git.openstack.org/openstack/octavia.git
controller2: controller2:
@ -191,7 +184,7 @@
api_v1_enabled: False api_v1_enabled: False
devstack_services: devstack_services:
base: false base: false
barbican: true barbican: false
dstat: true dstat: true
g-api: true g-api: true
g-reg: true g-reg: true
@ -362,6 +355,20 @@
OCTAVIA_AMP_BASE_OS: ubuntu OCTAVIA_AMP_BASE_OS: ubuntu
OCTAVIA_AMP_DISTRIBUTION_RELEASE_ID: bionic OCTAVIA_AMP_DISTRIBUTION_RELEASE_ID: bionic
- job:
name: octavia-v2-dsvm-tls-barbican
parent: octavia-v2-dsvm-scenario
required-projects:
- openstack/barbican
- openstack/diskimage-builder
- openstack/python-barbicanclient
vars:
tempest_test_regex: ^octavia_tempest_plugin.tests.barbican_scenario.v2
devstack_services:
barbican: true
devstack_plugins:
barbican: https://git.openstack.org/openstack/barbican.git
# Temporary transitional aliases for gates used in other repos # Temporary transitional aliases for gates used in other repos
# Remove once octavia has transitioned job names # Remove once octavia has transitioned job names
- job: - job:

View File

@ -23,6 +23,8 @@
voting: false voting: false
- octavia-v2-dsvm-py2-scenario-two-node: - octavia-v2-dsvm-py2-scenario-two-node:
voting: false voting: false
- octavia-v2-dsvm-tls-barbican:
voting: false
gate: gate:
queue: octavia queue: octavia
jobs: jobs: