diff --git a/zaza/charm_tests/octavia/__init__.py b/zaza/charm_tests/octavia/__init__.py new file mode 100644 index 0000000..00916f6 --- /dev/null +++ b/zaza/charm_tests/octavia/__init__.py @@ -0,0 +1,15 @@ +# Copyright 2018 Canonical Ltd. +# +# 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. + +"""Collection of code for setting up and testing octavia.""" diff --git a/zaza/charm_tests/octavia/setup.py b/zaza/charm_tests/octavia/setup.py new file mode 100644 index 0000000..4ec0414 --- /dev/null +++ b/zaza/charm_tests/octavia/setup.py @@ -0,0 +1,83 @@ +# Copyright 2018 Canonical Ltd. +# +# 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. + +"""Code for configuring octavia.""" + +import os +import base64 +import logging + +import zaza.utilities.cert +import zaza.charm_lifecycle.utils +import zaza.charm_tests.test_utils +import zaza.charm_tests.glance.setup as glance_setup + + +def add_amphora_image(image_url=None): + """Add Octavia ``amphora`` test image to glance. + + :param image_url: URL where image resides + :type image_url: str + """ + image_name = 'amphora-x64-haproxy' + if not image_url: + image_url = ( + os.environ.get('FUNCTEST_AMPHORA_LOCATION', None) or + 'http://tarballs.openstack.org/octavia/test-images/' + 'test-only-amphora-x64-haproxy-ubuntu-xenial.qcow2') + glance_setup.add_image( + image_url, + image_name=image_name, + tags=['octavia-amphora']) + + +def configure_amphora_certs(): + """Configure certificates for internal Octavia client/server auth.""" + (issuing_cakey, issuing_cacert) = zaza.utilities.cert.generate_cert( + 'OSCI Zaza Issuer', + password='zaza', + generate_ca=True) + (controller_cakey, controller_cacert) = zaza.utilities.cert.generate_cert( + 'OSCI Zaza Octavia Controller', + generate_ca=True) + (controller_key, controller_cert) = zaza.utilities.cert.generate_cert( + '*.serverstack', + issuer_name='OSCI Zaza Octavia Controller', + signing_key=controller_cakey) + controller_bundle = controller_cert + controller_key + cert_config = { + 'lb-mgmt-issuing-cacert': base64.b64encode( + issuing_cacert).decode('utf-8'), + 'lb-mgmt-issuing-ca-private-key': base64.b64encode( + issuing_cakey).decode('utf-8'), + 'lb-mgmt-issuing-ca-key-passphrase': 'zaza', + 'lb-mgmt-controller-cacert': base64.b64encode( + controller_cacert).decode('utf-8'), + 'lb-mgmt-controller-cert': base64.b64encode( + controller_bundle).decode('utf-8'), + } + logging.info('Configuring certificates for mandatory Octavia ' + 'client/server authentication ' + '(client being the ``Amphorae`` load balancer instances)') + + # Our expected workload status will change after we have configured the + # certificates + test_config = zaza.charm_lifecycle.utils.get_charm_config() + del test_config['target_deploy_status']['octavia'] + + _singleton = zaza.charm_tests.test_utils.OpenStackBaseTest() + _singleton.setUpClass() + with _singleton.config_change(cert_config, cert_config): + # wait for configuration to be applied then return + pass diff --git a/zaza/charm_tests/octavia/tests.py b/zaza/charm_tests/octavia/tests.py new file mode 100644 index 0000000..6261394 --- /dev/null +++ b/zaza/charm_tests/octavia/tests.py @@ -0,0 +1,79 @@ +# Copyright 2018 Canonical Ltd. +# +# 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. + +"""Encapsulate octavia testing.""" + +import logging +import tenacity + +import zaza.charm_tests.test_utils as test_utils +import zaza.utilities.openstack as openstack_utils + + +class CharmOperationTest(test_utils.OpenStackBaseTest): + """Charm operation tests.""" + + @classmethod + def setUpClass(cls): + """Run class setup for running Octavia charm operation tests.""" + super(CharmOperationTest, cls).setUpClass() + + def test_pause_resume(self): + """Run pause and resume tests. + + Pause service and check services are stopped, then resume and check + they are started. + """ + self.pause_resume(['apache2']) + + +class LBAASv2Test(test_utils.OpenStackBaseTest): + """LBaaSv2 service tests.""" + + @classmethod + def setUpClass(cls): + """Run class setup for running LBaaSv2 service tests.""" + super(LBAASv2Test, cls).setUpClass() + + def test_create_loadbalancer(self): + """Create load balancer.""" + keystone_session = openstack_utils.get_overcloud_keystone_session() + neutron_client = openstack_utils.get_neutron_session_client( + keystone_session) + resp = neutron_client.list_networks(name='private') + subnet_id = resp['networks'][0]['subnets'][0] + octavia_client = openstack_utils.get_octavia_session_client( + keystone_session) + result = octavia_client.load_balancer_create( + json={ + 'loadbalancer': { + 'description': 'Created by Zaza', + 'admin_state_up': True, + 'vip_subnet_id': subnet_id, + 'name': 'zaza-lb-0', + }}) + lb_id = result['loadbalancer']['id'] + + @tenacity.retry(wait=tenacity.wait_fixed(1), + reraise=True, stop=tenacity.stop_after_delay(900)) + def wait_for_loadbalancer(octavia_client, load_balancer_id): + resp = octavia_client.load_balancer_show(load_balancer_id) + if resp['provisioning_status'] != 'ACTIVE': + raise Exception('load balancer has not reached expected ' + 'status: {}'.format(resp)) + return resp + logging.info('Awaiting loadbalancer to reach provisioning_status ' + '"ACTIVE"') + resp = wait_for_loadbalancer(octavia_client, lb_id) + logging.info(resp)