From 7d23285ce00d9491e5cc3846b893cb65c4cb1291 Mon Sep 17 00:00:00 2001 From: Jose Guedez Date: Thu, 5 Dec 2019 16:22:29 +1100 Subject: [PATCH 1/7] Ported neutron-gateway tests to zaza (900/910) --- zaza/openstack/charm_tests/neutron/tests.py | 91 +++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/zaza/openstack/charm_tests/neutron/tests.py b/zaza/openstack/charm_tests/neutron/tests.py index e7d609d..e3d5cd7 100644 --- a/zaza/openstack/charm_tests/neutron/tests.py +++ b/zaza/openstack/charm_tests/neutron/tests.py @@ -29,6 +29,97 @@ import zaza.openstack.configure.guest as guest import zaza.openstack.utilities.openstack as openstack_utils +class NeutronGatewayTest(test_utils.OpenStackBaseTest): + """Test basic Neutron Gateway Charm functionality.""" + + @classmethod + def setUpClass(cls): + """Run class setup for running Neutron Gateway tests.""" + super(NeutronGatewayTest, cls).setUpClass() + cls.current_os_release = openstack_utils.get_os_release() + cls.services = cls._get_services() + + def test_900_restart_on_config_change(self): + """Checking restart happens on config change. + + Change disk format and assert then change propagates to the correct + file and that services are restarted as a result + """ + # Expected default and alternate values + current_value = zaza.model.get_application_config( + 'neutron-gateway')['debug']['value'] + new_value = str(not bool(current_value)).title() + current_value = str(current_value).title() + + set_default = {'debug': current_value} + set_alternate = {'debug': new_value} + default_entry = {'DEFAULT': {'debug': [current_value]}} + alternate_entry = {'DEFAULT': {'debug': [new_value]}} + + # Config file affected by juju set config change + conf_file = '/etc/neutron/neutron.conf' + + bionic_stein = openstack_utils.get_os_release('bionic_stein') + + # Make config change, check for service restarts + logging.info( + 'Setting verbose on neutron-api {}'.format(set_alternate)) + if self.current_os_release >= bionic_stein: + pgrep_full = True + else: + pgrep_full = False + self.restart_on_changed( + conf_file, + set_default, + set_alternate, + default_entry, + alternate_entry, + self.services, + pgrep_full=pgrep_full) + + def test_910_pause_and_resume(self): + """Run pause and resume tests. + + Pause service and check services are stopped then resume and check + they are started + """ + bionic_stein = openstack_utils.get_os_release('bionic_stein') + if self.current_os_release >= bionic_stein: + pgrep_full = True + else: + pgrep_full = False + with self.pause_resume( + self.services, + pgrep_full=pgrep_full): + logging.info("Testing pause resume") + + @classmethod + def _get_services(cls): + """ + Return the services expected in Neutron Gateway. + + :returns: A list of services + :rtype: list[str] + """ + services = ['neutron-dhcp-agent', + 'neutron-metadata-agent', + 'neutron-metering-agent', + 'neutron-openvswitch-agent'] + + trusty_icehouse = openstack_utils.get_os_release('trusty_icehouse') + xenial_newton = openstack_utils.get_os_release('xenial_newton') + bionic_train = openstack_utils.get_os_release('bionic_train') + + if cls.current_os_release <= trusty_icehouse: + services.append('neutron-vpn-agent') + if cls.current_os_release < xenial_newton: + services.append('neutron-lbaas-agent') + if xenial_newton <= cls.current_os_release < bionic_train: + services.append('neutron-lbaasv2-agent') + + return services + + class NeutronApiTest(test_utils.OpenStackBaseTest): """Test basic Neutron API Charm functionality.""" From 2704fe654cb895c8c95a1166dbd33eb7a3b086c8 Mon Sep 17 00:00:00 2001 From: Jose Guedez Date: Mon, 9 Dec 2019 17:33:25 +1100 Subject: [PATCH 2/7] Ported neutron-gateway tests to zaza (500) --- zaza/openstack/charm_tests/neutron/tests.py | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/zaza/openstack/charm_tests/neutron/tests.py b/zaza/openstack/charm_tests/neutron/tests.py index e3d5cd7..6821f30 100644 --- a/zaza/openstack/charm_tests/neutron/tests.py +++ b/zaza/openstack/charm_tests/neutron/tests.py @@ -120,6 +120,32 @@ class NeutronGatewayTest(test_utils.OpenStackBaseTest): return services +class NeutronGatewaySecurityTest(test_utils.OpenStackBaseTest): + """Neutron Gateway Security Tests.""" + + def test_security_checklist(self): + """Verify expected state with security-checklist.""" + expected_failures = [] + expected_passes = [ + 'validate-file-ownership', + 'validate-file-permissions', + ] + + for unit in zaza.model.get_units('neutron-gateway', + model_name=self.model_name): + logging.info('Running `security-checklist` action' + ' on unit {}'.format(unit.entity_id)) + test_utils.audit_assertions( + zaza.model.run_action( + unit.entity_id, + 'security-checklist', + model_name=self.model_name, + action_params={}), + expected_passes, + expected_failures, + expected_to_pass=True) + + class NeutronApiTest(test_utils.OpenStackBaseTest): """Test basic Neutron API Charm functionality.""" From a3cf1bf7e70fe4a736ccbf687d83f3b09a087733 Mon Sep 17 00:00:00 2001 From: Jose Guedez Date: Mon, 9 Dec 2019 18:36:33 +1100 Subject: [PATCH 3/7] Ported neutron-gateway tests to zaza (400/401) --- zaza/openstack/charm_tests/neutron/tests.py | 82 +++++++++++++++++---- 1 file changed, 69 insertions(+), 13 deletions(-) diff --git a/zaza/openstack/charm_tests/neutron/tests.py b/zaza/openstack/charm_tests/neutron/tests.py index 6821f30..5d75099 100644 --- a/zaza/openstack/charm_tests/neutron/tests.py +++ b/zaza/openstack/charm_tests/neutron/tests.py @@ -17,6 +17,7 @@ """Encapsulating `neutron-openvswitch` testing.""" +import time import logging import tenacity import unittest @@ -39,6 +40,72 @@ class NeutronGatewayTest(test_utils.OpenStackBaseTest): cls.current_os_release = openstack_utils.get_os_release() cls.services = cls._get_services() + # set up clients + cls.neutron_client = ( + openstack_utils.get_neutron_session_client(cls.keystone_session)) + + bionic_stein = openstack_utils.get_os_release('bionic_stein') + + cls.pgrep_full = (True if cls.current_os_release >= bionic_stein + else False) + + def test_400_create_network(self): + """Create a network, verify that it exists, and then delete it.""" + logging.debug('Creating neutron network...') + self.neutron_client.format = 'json' + net_name = 'test_net' + + # Verify that the network doesn't exist + networks = self.neutron_client.list_networks(name=net_name) + net_count = len(networks['networks']) + assert net_count == 0, ( + "Expected zero networks, found {}".format(net_count)) + + # Create a network and verify that it exists + network = {'name': net_name} + self.neutron_client.create_network({'network': network}) + + networks = self.neutron_client.list_networks(name=net_name) + logging.debug('Networks: {}'.format(networks)) + net_len = len(networks['networks']) + assert net_len == 1, ( + "Expected 1 network, found {}".format(net_len)) + + logging.debug('Confirming new neutron network...') + network = networks['networks'][0] + assert network['name'] == net_name, "network ext_net not found" + + # Cleanup + logging.debug('Deleting neutron network...') + self.neutron_client.delete_network(network['id']) + + def test_401_enable_qos(self): + """Check qos settings set via neutron-api charm.""" + if (self.current_os_release >= + openstack_utils.get_os_release('trusty_mitaka')): + logging.info('running qos check') + + with self.config_change( + {'enable-qos': 'False'}, + {'enable-qos': 'True'}, + application_name="neutron-api"): + + # wait for neutron-gateway to complete as well + time.sleep(60) + + # obtain dhcp agent to identify the neutron-gateway host + dhcp_agent = self.neutron_client.list_agents( + binary='neutron-dhcp-agent')['agents'][0] + neutron_gw_host = dhcp_agent['host'] + logging.debug('neutron gw host: {}'.format(neutron_gw_host)) + + # check extensions on the ovs agent to validate qos + ovs_agent = self.neutron_client.list_agents( + binary='neutron-openvswitch-agent', + host=neutron_gw_host)['agents'][0] + + self.assertIn('qos', ovs_agent['configurations']['extensions']) + def test_900_restart_on_config_change(self): """Checking restart happens on config change. @@ -59,15 +126,9 @@ class NeutronGatewayTest(test_utils.OpenStackBaseTest): # Config file affected by juju set config change conf_file = '/etc/neutron/neutron.conf' - bionic_stein = openstack_utils.get_os_release('bionic_stein') - # Make config change, check for service restarts logging.info( 'Setting verbose on neutron-api {}'.format(set_alternate)) - if self.current_os_release >= bionic_stein: - pgrep_full = True - else: - pgrep_full = False self.restart_on_changed( conf_file, set_default, @@ -75,7 +136,7 @@ class NeutronGatewayTest(test_utils.OpenStackBaseTest): default_entry, alternate_entry, self.services, - pgrep_full=pgrep_full) + pgrep_full=self.pgrep_full) def test_910_pause_and_resume(self): """Run pause and resume tests. @@ -83,14 +144,9 @@ class NeutronGatewayTest(test_utils.OpenStackBaseTest): Pause service and check services are stopped then resume and check they are started """ - bionic_stein = openstack_utils.get_os_release('bionic_stein') - if self.current_os_release >= bionic_stein: - pgrep_full = True - else: - pgrep_full = False with self.pause_resume( self.services, - pgrep_full=pgrep_full): + pgrep_full=self.pgrep_full): logging.info("Testing pause resume") @classmethod From 99eed41697a3526c8390b291971fbc43e3033ee7 Mon Sep 17 00:00:00 2001 From: Jose Guedez Date: Mon, 9 Dec 2019 18:52:23 +1100 Subject: [PATCH 4/7] Ported neutron-gateway tests to zaza (920) --- zaza/openstack/charm_tests/neutron/tests.py | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/zaza/openstack/charm_tests/neutron/tests.py b/zaza/openstack/charm_tests/neutron/tests.py index 5d75099..e39043e 100644 --- a/zaza/openstack/charm_tests/neutron/tests.py +++ b/zaza/openstack/charm_tests/neutron/tests.py @@ -149,6 +149,34 @@ class NeutronGatewayTest(test_utils.OpenStackBaseTest): pgrep_full=self.pgrep_full): logging.info("Testing pause resume") + def test_920_change_aa_profile(self): + """Test changing the Apparmor profile mode.""" + services = ['neutron-openvswitch-agent', + 'neutron-dhcp-agent', + 'neutron-l3-agent', + 'neutron-metadata-agent', + 'neutron-metering-agent'] + + set_default = {'aa-profile-mode': 'disable'} + set_alternate = {'aa-profile-mode': 'complain'} + + mtime = zaza.model.get_unit_time( + self.lead_unit, + model_name=self.model_name) + logging.debug('Remote unit timestamp {}'.format(mtime)) + + with self.config_change(set_default, set_alternate): + for unit in zaza.model.get_units('neutron-gateway', + model_name=self.model_name): + logging.info('Checking number of profiles in complain ' + 'mode in {}'.format(unit.entity_id)) + run = zaza.model.run_on_unit( + unit.entity_id, + 'aa-status --complaining', + model_name=self.model_name) + output = run['Stdout'] + self.assertTrue(int(output) >= len(services)) + @classmethod def _get_services(cls): """ From 79bb61243f25d3264ab81edfd9279036d930dd5d Mon Sep 17 00:00:00 2001 From: Jose Guedez Date: Wed, 11 Dec 2019 12:51:43 +1100 Subject: [PATCH 5/7] Use a single security test class for neutron-api and neutron-gateway --- zaza/openstack/charm_tests/neutron/tests.py | 69 +++++++++------------ 1 file changed, 28 insertions(+), 41 deletions(-) diff --git a/zaza/openstack/charm_tests/neutron/tests.py b/zaza/openstack/charm_tests/neutron/tests.py index e39043e..3d4588b 100644 --- a/zaza/openstack/charm_tests/neutron/tests.py +++ b/zaza/openstack/charm_tests/neutron/tests.py @@ -204,32 +204,6 @@ class NeutronGatewayTest(test_utils.OpenStackBaseTest): return services -class NeutronGatewaySecurityTest(test_utils.OpenStackBaseTest): - """Neutron Gateway Security Tests.""" - - def test_security_checklist(self): - """Verify expected state with security-checklist.""" - expected_failures = [] - expected_passes = [ - 'validate-file-ownership', - 'validate-file-permissions', - ] - - for unit in zaza.model.get_units('neutron-gateway', - model_name=self.model_name): - logging.info('Running `security-checklist` action' - ' on unit {}'.format(unit.entity_id)) - test_utils.audit_assertions( - zaza.model.run_action( - unit.entity_id, - 'security-checklist', - model_name=self.model_name, - action_params={}), - expected_passes, - expected_failures, - expected_to_pass=True) - - class NeutronApiTest(test_utils.OpenStackBaseTest): """Test basic Neutron API Charm functionality.""" @@ -288,28 +262,41 @@ class NeutronApiTest(test_utils.OpenStackBaseTest): class SecurityTest(test_utils.OpenStackBaseTest): - """Neutron APIsecurity tests tests.""" + """Neutron Security Tests.""" def test_security_checklist(self): """Verify expected state with security-checklist.""" - tls_checks = [ - 'validate-uses-tls-for-keystone', - ] - expected_failures = [ - 'validate-enables-tls', # LP: #1851610 - ] + expected_failures = [] expected_passes = [ 'validate-file-ownership', 'validate-file-permissions', - 'validate-uses-keystone', ] - if zaza.model.get_relation_id( - 'neutron-api', 'vault', remote_interface_name='certificates'): - expected_passes.extend(tls_checks) - else: - expected_failures.extend(tls_checks) + expected_to_pass = True - for unit in zaza.model.get_units('neutron-api', + # override settings depending on application name so we can reuse + # the class for multiple charms + if self.application_name == 'neutron-api': + tls_checks = [ + 'validate-uses-tls-for-keystone', + ] + + expected_failures = [ + 'validate-enables-tls', # LP: #1851610 + ] + + expected_passes.append('validate-uses-keystone') + + if zaza.model.get_relation_id( + 'neutron-api', + 'vault', + remote_interface_name='certificates'): + expected_passes.extend(tls_checks) + else: + expected_failures.extend(tls_checks) + + expected_to_pass = False + + for unit in zaza.model.get_units(self.application_name, model_name=self.model_name): logging.info('Running `security-checklist` action' ' on unit {}'.format(unit.entity_id)) @@ -321,7 +308,7 @@ class SecurityTest(test_utils.OpenStackBaseTest): action_params={}), expected_passes, expected_failures, - expected_to_pass=False) + expected_to_pass=expected_to_pass) class NeutronNetworkingTest(unittest.TestCase): From f79f2fb54c062651324f7140e9f90941c565c302 Mon Sep 17 00:00:00 2001 From: Jose Guedez Date: Wed, 11 Dec 2019 14:05:19 +1100 Subject: [PATCH 6/7] NeutronGatewayTest: refactor test 401 to use tenacity --- zaza/openstack/charm_tests/neutron/tests.py | 33 +++++++++++---------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/zaza/openstack/charm_tests/neutron/tests.py b/zaza/openstack/charm_tests/neutron/tests.py index 3d4588b..f6cde67 100644 --- a/zaza/openstack/charm_tests/neutron/tests.py +++ b/zaza/openstack/charm_tests/neutron/tests.py @@ -17,7 +17,6 @@ """Encapsulating `neutron-openvswitch` testing.""" -import time import logging import tenacity import unittest @@ -90,21 +89,7 @@ class NeutronGatewayTest(test_utils.OpenStackBaseTest): {'enable-qos': 'True'}, application_name="neutron-api"): - # wait for neutron-gateway to complete as well - time.sleep(60) - - # obtain dhcp agent to identify the neutron-gateway host - dhcp_agent = self.neutron_client.list_agents( - binary='neutron-dhcp-agent')['agents'][0] - neutron_gw_host = dhcp_agent['host'] - logging.debug('neutron gw host: {}'.format(neutron_gw_host)) - - # check extensions on the ovs agent to validate qos - ovs_agent = self.neutron_client.list_agents( - binary='neutron-openvswitch-agent', - host=neutron_gw_host)['agents'][0] - - self.assertIn('qos', ovs_agent['configurations']['extensions']) + self._validate_openvswitch_agent_qos() def test_900_restart_on_config_change(self): """Checking restart happens on config change. @@ -177,6 +162,22 @@ class NeutronGatewayTest(test_utils.OpenStackBaseTest): output = run['Stdout'] self.assertTrue(int(output) >= len(services)) + @tenacity.retry(wait=tenacity.wait_exponential(min=5, max=60)) + def _validate_openvswitch_agent_qos(self): + """Validate that the qos extension is enabled in the ovs agent.""" + # obtain the dhcp agent to identify the neutron-gateway host + dhcp_agent = self.neutron_client.list_agents( + binary='neutron-dhcp-agent')['agents'][0] + neutron_gw_host = dhcp_agent['host'] + logging.debug('neutron gw host: {}'.format(neutron_gw_host)) + + # check extensions on the ovs agent to validate qos + ovs_agent = self.neutron_client.list_agents( + binary='neutron-openvswitch-agent', + host=neutron_gw_host)['agents'][0] + + self.assertIn('qos', ovs_agent['configurations']['extensions']) + @classmethod def _get_services(cls): """ From 55fc718f981f22cb7a555de993960841d8d5196a Mon Sep 17 00:00:00 2001 From: Jose Guedez Date: Wed, 11 Dec 2019 15:05:12 +1100 Subject: [PATCH 7/7] Move tests (400/401) from neutron-gateway to neutron-api --- zaza/openstack/charm_tests/neutron/tests.py | 132 ++++++++++---------- 1 file changed, 69 insertions(+), 63 deletions(-) diff --git a/zaza/openstack/charm_tests/neutron/tests.py b/zaza/openstack/charm_tests/neutron/tests.py index f6cde67..4df7021 100644 --- a/zaza/openstack/charm_tests/neutron/tests.py +++ b/zaza/openstack/charm_tests/neutron/tests.py @@ -39,58 +39,11 @@ class NeutronGatewayTest(test_utils.OpenStackBaseTest): cls.current_os_release = openstack_utils.get_os_release() cls.services = cls._get_services() - # set up clients - cls.neutron_client = ( - openstack_utils.get_neutron_session_client(cls.keystone_session)) - bionic_stein = openstack_utils.get_os_release('bionic_stein') cls.pgrep_full = (True if cls.current_os_release >= bionic_stein else False) - def test_400_create_network(self): - """Create a network, verify that it exists, and then delete it.""" - logging.debug('Creating neutron network...') - self.neutron_client.format = 'json' - net_name = 'test_net' - - # Verify that the network doesn't exist - networks = self.neutron_client.list_networks(name=net_name) - net_count = len(networks['networks']) - assert net_count == 0, ( - "Expected zero networks, found {}".format(net_count)) - - # Create a network and verify that it exists - network = {'name': net_name} - self.neutron_client.create_network({'network': network}) - - networks = self.neutron_client.list_networks(name=net_name) - logging.debug('Networks: {}'.format(networks)) - net_len = len(networks['networks']) - assert net_len == 1, ( - "Expected 1 network, found {}".format(net_len)) - - logging.debug('Confirming new neutron network...') - network = networks['networks'][0] - assert network['name'] == net_name, "network ext_net not found" - - # Cleanup - logging.debug('Deleting neutron network...') - self.neutron_client.delete_network(network['id']) - - def test_401_enable_qos(self): - """Check qos settings set via neutron-api charm.""" - if (self.current_os_release >= - openstack_utils.get_os_release('trusty_mitaka')): - logging.info('running qos check') - - with self.config_change( - {'enable-qos': 'False'}, - {'enable-qos': 'True'}, - application_name="neutron-api"): - - self._validate_openvswitch_agent_qos() - def test_900_restart_on_config_change(self): """Checking restart happens on config change. @@ -162,22 +115,6 @@ class NeutronGatewayTest(test_utils.OpenStackBaseTest): output = run['Stdout'] self.assertTrue(int(output) >= len(services)) - @tenacity.retry(wait=tenacity.wait_exponential(min=5, max=60)) - def _validate_openvswitch_agent_qos(self): - """Validate that the qos extension is enabled in the ovs agent.""" - # obtain the dhcp agent to identify the neutron-gateway host - dhcp_agent = self.neutron_client.list_agents( - binary='neutron-dhcp-agent')['agents'][0] - neutron_gw_host = dhcp_agent['host'] - logging.debug('neutron gw host: {}'.format(neutron_gw_host)) - - # check extensions on the ovs agent to validate qos - ovs_agent = self.neutron_client.list_agents( - binary='neutron-openvswitch-agent', - host=neutron_gw_host)['agents'][0] - - self.assertIn('qos', ovs_agent['configurations']['extensions']) - @classmethod def _get_services(cls): """ @@ -208,6 +145,59 @@ class NeutronGatewayTest(test_utils.OpenStackBaseTest): class NeutronApiTest(test_utils.OpenStackBaseTest): """Test basic Neutron API Charm functionality.""" + @classmethod + def setUpClass(cls): + """Run class setup for running Neutron Gateway tests.""" + super(NeutronApiTest, cls).setUpClass() + cls.current_os_release = openstack_utils.get_os_release() + + # set up clients + cls.neutron_client = ( + openstack_utils.get_neutron_session_client(cls.keystone_session)) + + def test_400_create_network(self): + """Create a network, verify that it exists, and then delete it.""" + logging.debug('Creating neutron network...') + self.neutron_client.format = 'json' + net_name = 'test_net' + + # Verify that the network doesn't exist + networks = self.neutron_client.list_networks(name=net_name) + net_count = len(networks['networks']) + assert net_count == 0, ( + "Expected zero networks, found {}".format(net_count)) + + # Create a network and verify that it exists + network = {'name': net_name} + self.neutron_client.create_network({'network': network}) + + networks = self.neutron_client.list_networks(name=net_name) + logging.debug('Networks: {}'.format(networks)) + net_len = len(networks['networks']) + assert net_len == 1, ( + "Expected 1 network, found {}".format(net_len)) + + logging.debug('Confirming new neutron network...') + network = networks['networks'][0] + assert network['name'] == net_name, "network ext_net not found" + + # Cleanup + logging.debug('Deleting neutron network...') + self.neutron_client.delete_network(network['id']) + + def test_401_enable_qos(self): + """Check qos settings set via neutron-api charm.""" + if (self.current_os_release >= + openstack_utils.get_os_release('trusty_mitaka')): + logging.info('running qos check') + + with self.config_change( + {'enable-qos': 'False'}, + {'enable-qos': 'True'}, + application_name="neutron-api"): + + self._validate_openvswitch_agent_qos() + def test_900_restart_on_config_change(self): """Checking restart happens on config change. @@ -261,6 +251,22 @@ class NeutronApiTest(test_utils.OpenStackBaseTest): pgrep_full=pgrep_full): logging.info("Testing pause resume") + @tenacity.retry(wait=tenacity.wait_exponential(min=5, max=60)) + def _validate_openvswitch_agent_qos(self): + """Validate that the qos extension is enabled in the ovs agent.""" + # obtain the dhcp agent to identify the neutron-gateway host + dhcp_agent = self.neutron_client.list_agents( + binary='neutron-dhcp-agent')['agents'][0] + neutron_gw_host = dhcp_agent['host'] + logging.debug('neutron gw host: {}'.format(neutron_gw_host)) + + # check extensions on the ovs agent to validate qos + ovs_agent = self.neutron_client.list_agents( + binary='neutron-openvswitch-agent', + host=neutron_gw_host)['agents'][0] + + self.assertIn('qos', ovs_agent['configurations']['extensions']) + class SecurityTest(test_utils.OpenStackBaseTest): """Neutron Security Tests."""