From 5d7d884ead4a39fab53b0c76f4854a9edc6ef90b Mon Sep 17 00:00:00 2001 From: Rodrigo Barbieri Date: Thu, 28 Sep 2023 11:26:06 -0300 Subject: [PATCH] [WIP] Remove hardcoded nova-compute app name and add ceph keys test WIP --- zaza/openstack/charm_tests/ceph/tests.py | 3 +- zaza/openstack/charm_tests/nova/tests.py | 119 ++++++++++++++++------ zaza/openstack/charm_tests/test_utils.py | 2 +- zaza/openstack/charm_tests/vault/setup.py | 6 +- zaza/openstack/utilities/openstack.py | 25 ++++- 5 files changed, 119 insertions(+), 36 deletions(-) diff --git a/zaza/openstack/charm_tests/ceph/tests.py b/zaza/openstack/charm_tests/ceph/tests.py index fa8e89879..9c0a1e6f7 100644 --- a/zaza/openstack/charm_tests/ceph/tests.py +++ b/zaza/openstack/charm_tests/ceph/tests.py @@ -1285,7 +1285,8 @@ def test_check_pool_types(self): """Check type of pools created for clients.""" app_pools = [ ('glance', 'glance'), - ('nova-compute', 'nova'), + (zaza_openstack.get_app_names_for_charm('nova-compute')[0], + 'nova'), ('cinder-ceph', 'cinder-ceph')] runtime_pool_details = zaza_ceph.get_ceph_pool_details() for app, pool_name in app_pools: diff --git a/zaza/openstack/charm_tests/nova/tests.py b/zaza/openstack/charm_tests/nova/tests.py index 34f02731c..81f1352b1 100644 --- a/zaza/openstack/charm_tests/nova/tests.py +++ b/zaza/openstack/charm_tests/nova/tests.py @@ -19,6 +19,7 @@ import json import logging import os +import re import tempfile import tenacity import unittest @@ -127,7 +128,9 @@ def check_tpm(stdin, stdout, stderr): password=password, privkey=privkey, verify=check_tpm) - @test_utils.skipUntilVersion('nova-compute', 'nova-common', '3:23.0.0') + @test_utils.skipUntilVersion( + openstack_utils.get_app_names_for_charm('nova-compute')[0], + 'nova-common', '3:23.0.0') def test_launch_vtpm_1_2_instance(self): """Launch an instance using TPM 1.2.""" self.RESOURCE_PREFIX = 'zaza-nova' @@ -138,7 +141,9 @@ def test_launch_vtpm_1_2_instance(self): # Note: TPM 1.2 presents tpm0 as a device self._check_tpm_device(instance, '/dev/tpm0') - @test_utils.skipUntilVersion('nova-compute', 'nova-common', '3:23.0.0') + @test_utils.skipUntilVersion( + openstack_utils.get_app_names_for_charm('nova-compute')[0], + 'nova-common', '3:23.0.0') def test_launch_vtpm_2_instance(self): """Launch an instance using TPM 2.0.""" self.RESOURCE_PREFIX = 'zaza-nova' @@ -265,8 +270,9 @@ def fetch_nova_service_hostname(self, unit_name): def test_940_enable_disable_actions(self): """Test disable/enable actions on nova-compute units.""" - nova_units = zaza.model.get_units('nova-compute', - model_name=self.model_name) + nova_units = zaza.model.get_units( + self.application_name, + model_name=self.model_name) # Check that nova-compute services are enabled before testing for service in self.nova_client.services.list(binary='nova-compute'): @@ -307,8 +313,9 @@ def check_instance_count(expect_count, unit_name): instances = result.data.get('results', {}).get('instance-count') self.assertEqual(instances, str(expect_count)) - nova_unit = zaza.model.get_units('nova-compute', - model_name=self.model_name)[0] + nova_unit = zaza.model.get_units( + self.application_name, + model_name=self.model_name)[0] check_instance_count(0, nova_unit.entity_id) @@ -345,8 +352,9 @@ def wait_for_nova_compute_count(expected_count): sleep_timeout = 10 return False - all_units = zaza.model.get_units('nova-compute', - model_name=self.model_name) + all_units = zaza.model.get_units( + self.application_name, + model_name=self.model_name) unit_to_remove = all_units[0] @@ -372,7 +380,7 @@ def wait_for_nova_compute_count(expected_count): # Wait for nova-compute service to be removed from the # nova-cloud-controller - if not wait_for_nova_compute_count(0): + if not wait_for_nova_compute_count(service_count-1): self.fail("nova-compute service was not unregistered from the " "nova-cloud-controller as expected.") @@ -382,7 +390,7 @@ def wait_for_nova_compute_count(expected_count): 'register-to-cloud', raise_on_failure=True) - if not wait_for_nova_compute_count(1): + if not wait_for_nova_compute_count(service_count): self.fail("nova-compute service was not re-registered to the " "nova-cloud-controller as expected.") @@ -398,12 +406,14 @@ def test_311_pci_alias_config_compute(self): """ # We are not touching the behavior of anything older than QUEENS if self.current_release >= self.XENIAL_QUEENS: - self._test_pci_alias_config("nova-compute", ['nova-compute']) + self._test_pci_alias_config( + self.application_name, ['nova-compute']) def test_500_hugepagereport_action(self): """Test hugepagereport action.""" - for unit in zaza.model.get_units('nova-compute', - model_name=self.model_name): + for unit in zaza.model.get_units( + self.application_name, + model_name=self.model_name): logging.info('Running `hugepagereport` action' ' on unit {}'.format(unit.entity_id)) action = zaza.model.run_action( @@ -446,12 +456,13 @@ def test_920_change_aa_profile(self): logging.info( 'Waiting for services ({}) to be restarted'.format(services)) zaza.model.block_until_services_restarted( - 'nova-compute', + self.application_name, mtime, services, model_name=self.model_name) - for unit in zaza.model.get_units('nova-compute', - model_name=self.model_name): + for unit in zaza.model.get_units( + self.application_name, + 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( @@ -470,10 +481,50 @@ def test_901_pause_resume(self): with self.pause_resume(['nova-compute']): logging.info("Testing pause resume") + def test_904_test_ceph_keys(self): + """Run pause and resume tests. + + Pause service and check services are stopped then resume and check + they are started + """ + # Expected default and alternate values + if zaza.model.get_application_config( + self.application_name)['libvirt-image-backend'].get( + 'value') != 'rbd': + return + + regex = re.compile(r"^\[client.(.+)\]\n\tkey = (.+)$") + key_dict = {} + + def check_keyring(app_name_dict_list): + for app_name_dict in app_name_dict_list: + for app_name, key_list in app_name_dict.items(): + for unit in zaza.model.get_units( + app_name, model_name=self.model_name): + for key_app_name in key_list: + keyring_file = ( + '/etc/ceph/ceph.client.{}.keyring'.format( + key_app_name)) + data = str(generic_utils.get_file_contents( + unit, keyring_file)) + + result = regex.findall(data) + self.assertEqual(2, len(result)) + self.assertEqual(result[0], key_app_name) + for k, v in key_dict.items(): + if k == result[0]: + self.assertEqual(v, result[1]) + else: + self.assertNotEqual(v, result[1]) + key_dict[result[0]] = result[1] + + check_keyring([{self.application_name: [self.application_name]}]) + def test_930_check_virsh_default_network(self): """Test default virt network is not present.""" - for unit in zaza.model.get_units('nova-compute', - model_name=self.model_name): + for unit in zaza.model.get_units( + self.application_name, + model_name=self.model_name): logging.info('Checking default network is absent on ' 'unit {}'.format(unit.entity_id)) run = zaza.model.run_on_unit( @@ -492,8 +543,9 @@ class NovaComputeActionTest(test_utils.OpenStackBaseTest): def test_virsh_audit_action(self): """Test virsh-audit action.""" - for unit in zaza.model.get_units('nova-compute', - model_name=self.model_name): + for unit in zaza.model.get_units( + self.application_name, + model_name=self.model_name): logging.info('Running `virsh-audit` action' ' on unit {}'.format(unit.entity_id)) action = zaza.model.run_action( @@ -520,8 +572,9 @@ def test_vgpu_in_nova_conf(self): vgpu-device-mappings has been set to something not empty like "{'nvidia-108': ['0000:c1:00.0']}". """ - for unit in zaza.model.get_units('nova-compute', - model_name=self.model_name): + for unit in zaza.model.get_units( + self.application_name, + model_name=self.model_name): nova_conf_file = '/etc/nova/nova.conf' nova_conf = str(generic_utils.get_file_contents(unit, nova_conf_file)) @@ -775,12 +828,14 @@ class NovaCloudControllerActionTest(test_utils.OpenStackBaseTest): def test_sync_compute_az_action(self): """Test sync-compute-availability-zones action.""" juju_units_az_map = {} - compute_config = zaza.model.get_application_config('nova-compute') + compute_config = zaza.model.get_application_config( + self.application_name) default_az = compute_config['default-availability-zone']['value'] use_juju_az = compute_config['customize-failure-domain']['value'] - for unit in zaza.model.get_units('nova-compute', - model_name=self.model_name): + for unit in zaza.model.get_units( + self.application_name, + model_name=self.model_name): zone = default_az if use_juju_az: result = zaza.model.run_on_unit(unit.name, @@ -943,12 +998,12 @@ def test_230_resize_to_the_same_host(self): # Make config change, wait for the services restart on # nova-cloud-controller with self.config_change(set_default, set_alternate): - # The config change should propagate to nova-cmopute units + # The config change should propagate to nova-compute units # Wait for them to get settled after relation data has changed logging.info( 'Waiting for services ({}) to be restarted'.format(services)) zaza.model.block_until_services_restarted( - 'nova-compute', + self.application_name, mtime, services, model_name=self.model_name) @@ -957,8 +1012,9 @@ def test_230_resize_to_the_same_host(self): # it's changed nova_cfg = ConfigParser() - for unit in zaza.model.get_units('nova-compute', - model_name=self.model_name): + for unit in zaza.model.get_units( + self.application_name, + model_name=self.model_name): logging.info('Checking value of {} in {}'.format( nova_config_key, unit.entity_id)) result = zaza.model.run_on_unit( @@ -1156,8 +1212,9 @@ def test_security_checklist(self): else: expected_failures.extend(tls_checks) - for unit in zaza.model.get_units(self.application_name, - model_name=self.model_name): + 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)) test_utils.audit_assertions( diff --git a/zaza/openstack/charm_tests/test_utils.py b/zaza/openstack/charm_tests/test_utils.py index c6873a678..89288e87d 100644 --- a/zaza/openstack/charm_tests/test_utils.py +++ b/zaza/openstack/charm_tests/test_utils.py @@ -472,7 +472,7 @@ def restart_on_changed(self, config_file, default_config, alternate_config, a service. :type pgrep_full: bool """ - # lead_unit is only useed to grab a timestamp, the assumption being + # lead_unit is only used to grab a timestamp, the assumption being # that all the units times are in sync. mtime = model.get_unit_time( diff --git a/zaza/openstack/charm_tests/vault/setup.py b/zaza/openstack/charm_tests/vault/setup.py index 05e8cc547..93ed718d4 100644 --- a/zaza/openstack/charm_tests/vault/setup.py +++ b/zaza/openstack/charm_tests/vault/setup.py @@ -25,6 +25,7 @@ import zaza.openstack.utilities.cert import zaza.openstack.utilities.generic import zaza.openstack.utilities.exceptions as zaza_exceptions +from zaza.openstack.utilities.openstack import get_app_names_for_charm import zaza.utilities.juju as juju_utils @@ -187,12 +188,13 @@ def auto_initialize(cacert=None, validation_application='keystone', wait=True, validate_ca(cacertificate, application=validation_application) # Once validation has completed restart nova-compute to work around # bug #1826382 + nova_compute_app_name = get_app_names_for_charm('nova-compute')[0] cmd_map = { 'nova-cloud-controller': ('systemctl restart ' 'nova-scheduler nova-conductor'), - 'nova-compute': 'systemctl restart nova-compute', + nova_compute_app_name: 'systemctl restart nova-compute', } - for app in ('nova-compute', 'nova-cloud-controller',): + for app in (nova_compute_app_name, 'nova-cloud-controller',): try: for unit in zaza.model.get_units(app): result = zaza.model.run_on_unit( diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index e548884d3..6ad2d33b4 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -811,7 +811,8 @@ def add_interface_to_netplan(server_name, mac_address): application_names = ('neutron-openvswitch',) elif ovn_present(): # OVN chassis is a subordinate to nova-compute - application_names = ('nova-compute', 'ovn-dedicated-chassis') + application_names = (get_app_names_for_charm('nova-compute')[0], + 'ovn-dedicated-chassis') else: application_names = ('neutron-gateway',) @@ -2693,6 +2694,28 @@ def upload_image_to_glance(glance, local_path, image_name, disk_format='qcow2', return image +def get_app_names_for_charm(charm_name, model_name=None): + """Get all application names for a given charm in the model. + + :returns: List of application names + :rtype: List[str] + """ + status = juju_utils.get_full_juju_status(model_name=model_name) + result = [] + try: + for app_name, app_data in status['applications'].items(): + try: + if charm_name == app_data['charm-name']: + result.append(app_name) + except KeyError: + # Older juju versions may not have the field "charm-name" + if charm_name in app_data['charm']: + result.append(app_name) + except KeyError: + pass + return result + + def is_ceph_image_backend(model_name=None): """Check if glance is related to ceph, therefore using ceph as backend.