diff --git a/doc/requirements.txt b/doc/requirements.txt index 467e8203..d2e8cfc7 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -2,7 +2,7 @@ # of appearance. Changing the order has an impact on the overall integration # 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 openstackdocstheme>=1.18.1 # Apache-2.0 diff --git a/octavia_tempest_plugin/common/barbican_client_mgr.py b/octavia_tempest_plugin/common/barbican_client_mgr.py new file mode 100644 index 00000000..e93f9030 --- /dev/null +++ b/octavia_tempest_plugin/common/barbican_client_mgr.py @@ -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 diff --git a/octavia_tempest_plugin/common/cert_utils.py b/octavia_tempest_plugin/common/cert_utils.py new file mode 100644 index 00000000..dcdd6f08 --- /dev/null +++ b/octavia_tempest_plugin/common/cert_utils.py @@ -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() diff --git a/octavia_tempest_plugin/config.py b/octavia_tempest_plugin/config.py index 1d874a68..1bc4a63f 100644 --- a/octavia_tempest_plugin/config.py +++ b/octavia_tempest_plugin/config.py @@ -14,9 +14,13 @@ from oslo_config import cfg +from oslo_log import log as logging from octavia_tempest_plugin.common import constants as const + +LOG = logging.getLogger(__name__) + service_available_group = cfg.OptGroup(name='service_available', title='Available OpenStack Services') @@ -27,6 +31,19 @@ ServiceAvailableGroup = [ "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', title='load-balancer service options') @@ -54,6 +71,9 @@ OctaviaGroup = [ default=300, help='Timeout in seconds to wait for non-load-balancer ' '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 cfg.IntOpt('check_interval', default=5, @@ -152,4 +172,8 @@ LBFeatureEnabledGroup = [ default=True, help="Whether Health Monitor is available with provider" " driver or not."), + cfg.BoolOpt('terminated_tls_enabled', + default=True, + help="Whether TLS termination is available with provider " + "driver or not."), ] diff --git a/octavia_tempest_plugin/tests/barbican_scenario/__init__.py b/octavia_tempest_plugin/tests/barbican_scenario/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/octavia_tempest_plugin/tests/barbican_scenario/v2/__init__.py b/octavia_tempest_plugin/tests/barbican_scenario/v2/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py b/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py new file mode 100644 index 00000000..86dac047 --- /dev/null +++ b/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py @@ -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() diff --git a/octavia_tempest_plugin/tests/test_base.py b/octavia_tempest_plugin/tests/test_base.py index c443347b..a48ba0b9 100644 --- a/octavia_tempest_plugin/tests/test_base.py +++ b/octavia_tempest_plugin/tests/test_base.py @@ -766,13 +766,15 @@ class LoadBalancerBaseTestWithCompute(LoadBalancerBaseTest): URL = 'http://{0}:81'.format(ip_address) 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() start = time.time() while time.time() - start < CONF.load_balancer.build_timeout: 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) return except Exception: @@ -782,20 +784,21 @@ class LoadBalancerBaseTestWithCompute(LoadBalancerBaseTest): 'period. Failing test.') 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() response_counts = {} if ipaddress.ip_address(vip_address).version == 6: 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 for i in range(20): try: - r = session.get('http://{0}'.format(vip_address), - timeout=2) + r = session.get('{0}://{1}'.format(protocol, vip_address), + timeout=2, verify=verify) if r.content in response_counts: response_counts[r.content] += 1 diff --git a/requirements.txt b/requirements.txt index 5b1b3eed..815be940 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,13 +2,17 @@ # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. +cryptography>=2.1 # BSD/Apache-2.0 python-dateutil>=2.5.3 # BSD ipaddress>=1.0.17;python_version<'3.3' # PSF 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.log>=3.36.0 # Apache-2.0 oslo.utils>=3.33.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 six>=1.10.0 # MIT tempest>=17.1.0 # Apache-2.0 diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml index e90c7066..f5426cce 100644 --- a/zuul.d/jobs.yaml +++ b/zuul.d/jobs.yaml @@ -87,17 +87,13 @@ parent: octavia-dsvm-base timeout: 9000 required-projects: - - openstack/barbican - openstack/diskimage-builder - - openstack/python-barbicanclient vars: devstack_localrc: DIB_LOCAL_ELEMENTS: openstack-ci-mirrors devstack_services: - barbican: true neutron-qos: true devstack_plugins: - barbican: https://git.openstack.org/openstack/barbican.git neutron: https://git.openstack.org/openstack/neutron.git zuul_copy_output: '/var/log/dib-build' : logs @@ -108,9 +104,7 @@ nodeset: octavia-two-node timeout: 9000 required-projects: - - openstack/barbican - openstack/diskimage-builder - - openstack/python-barbicanclient host-vars: controller: devstack_localrc: @@ -143,7 +137,6 @@ OCTAVIA_NODES: "main:{{ hostvars['controller']['nodepool']['private_ipv4'] }},second:{{ hostvars['controller2']['nodepool']['private_ipv4'] }}" OCTAVIA_USE_PREGENERATED_CERTS: true devstack_plugins: - barbican: https://git.openstack.org/openstack/barbican.git neutron: https://git.openstack.org/openstack/neutron.git octavia: https://git.openstack.org/openstack/octavia.git controller2: @@ -191,7 +184,7 @@ api_v1_enabled: False devstack_services: base: false - barbican: true + barbican: false dstat: true g-api: true g-reg: true @@ -362,6 +355,20 @@ OCTAVIA_AMP_BASE_OS: ubuntu 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 # Remove once octavia has transitioned job names - job: diff --git a/zuul.d/projects.yaml b/zuul.d/projects.yaml index 94aa8c1f..07ec7ff0 100644 --- a/zuul.d/projects.yaml +++ b/zuul.d/projects.yaml @@ -23,6 +23,8 @@ voting: false - octavia-v2-dsvm-py2-scenario-two-node: voting: false + - octavia-v2-dsvm-tls-barbican: + voting: false gate: queue: octavia jobs: