Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove hardcoded nova-compute app name and add ceph keys test #1141

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions unit_tests/utilities/test_zaza_utilities_openstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,26 @@ def test_upload_image_to_glance(self):
expected_status='active',
msg='Image status wait')

def test_get_app_names_for_charm(self):
self.patch_object(openstack_utils.juju_utils, "get_full_juju_status",
return_value={
"applications": {
"nova-compute-kvm": {
"charm-name": 'nova-compute',
},
"nova-compute-sriov": {
"charm-name": 'nova-compute'
},
"cinder": {
"charm-name": 'cinder-volume',
},
},
})
self.assertEqual(
['nova-compute-kvm', 'nova-compute-sriov'],
openstack_utils.get_app_names_for_charm('nova-compute'))
self.get_full_juju_status.assert_called_once_with(model_name=None)

def test_is_ceph_image_backend_True(self):
self.patch_object(openstack_utils.juju_utils, "get_full_juju_status",
return_value={
Expand Down
3 changes: 2 additions & 1 deletion zaza/openstack/charm_tests/ceph/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
146 changes: 115 additions & 31 deletions zaza/openstack/charm_tests/nova/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import json
import logging
import os
import re
import tempfile
import tenacity
import unittest
Expand Down Expand Up @@ -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'
Expand All @@ -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'
Expand Down Expand Up @@ -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'):
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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]

Expand All @@ -359,6 +367,9 @@ def wait_for_nova_compute_count(expected_count):
if service_count < 1:
self.fail("Unit '{}' has no nova-compute services registered in"
" nova-cloud-controller".format(unit_to_remove.name))

# This elif would be removed in a future code when we have support
# for more than 1 nova-compute node in the CI
elif service_count > 1:
self.fail("Unexpected number of nova-compute services registered"
" in nova-cloud controller. Expecting: 1, found: "
Expand All @@ -372,7 +383,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.")

Expand All @@ -382,7 +393,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.")

Expand All @@ -398,12 +409,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(
Expand Down Expand Up @@ -446,12 +459,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(
Expand All @@ -470,10 +484,74 @@ def test_901_pause_resume(self):
with self.pause_resume(['nova-compute']):
logging.info("Testing pause resume")

def test_904_test_ceph_keys(self):
"""Test if the ceph keys in /etc/ceph are correct."""
# only run if configured as rbd with ceph image backend
if zaza.model.get_application_config(
self.application_name)['libvirt-image-backend'].get(
'value') != 'rbd':
return

# Regex for
# [client.nova-compute]
# key = AQBm5xJl8CSnFxAACB9GVr2llNO0G8zWZuZnjQ ==
regex = re.compile(r"^\[client.(.+)\]\n\tkey = (.+)$")
key_dict = {}

# The new and correct behavior is to have "nova-compute" named keyring
# and one other named after the charm app, IF the charm app name is
# different than "nova-compute". Example:
# for a charm app named "nova-compute-kvm",
# it should have both nova-compute-kvm and nova-compute keyrings.
# for a charm app named "nova-compute",
# it should have only nova-compute keyring.

# Previous behaviors:
# The old behavior is to have only 1 keyring named after the charm app.
# the intermediary behavior with the partial fix is to always have only
# the "nova-compute" keyring.

nova_compute_apps = openstack_utils.get_app_names_for_charm(
'nova-compute')

def check_keyring(app_name):
"""Check matching keyring name and different from existing ones."""
keyring_file = (
'/etc/ceph/ceph.client.{}.keyring'.format(app_name))
data = str(generic_utils.get_file_contents(
unit, keyring_file))

result = regex.findall(data)

# Assert keyring file name matches intended name
self.assertEqual(2, len(result))
self.assertEqual(result[0], app_name)

# Confirm the keys are different from each already checked
# nova-compute charm app
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]

# We typically only have 1 nova-compute charm app in the CI,
# so this code is future-proofing
for app_name in nova_compute_apps:
for unit in zaza.model.get_units(
app_name, model_name=self.model_name):

check_keyring('nova-compute')
# extra future code for the new fixed version
# if app_name != 'nova-compute':
# check_keyring(app_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(
Expand All @@ -492,8 +570,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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you sure that self.application_name is being set to the name of the application in the same way as get_app_names_for_charm()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is somewhat similar. The base class code that assigns self.application_name checks if each app starts with the charm_name declared in tests.yaml, and it breaks when it finds the first one. We could remove the break and go on creating a "self.application_nameS" variable and we ultimately have the same as get_app_names_for_charm. Ultimately I'd prefer if it uses "in (contains)" instead of startswith though.

model_name=self.model_name):
logging.info('Running `virsh-audit` action'
' on unit {}'.format(unit.entity_id))
action = zaza.model.run_action(
Expand All @@ -520,8 +599,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))
Expand Down Expand Up @@ -775,12 +855,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,
Expand Down Expand Up @@ -943,12 +1025,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)
Expand All @@ -957,8 +1039,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(
Expand Down Expand Up @@ -1156,8 +1239,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(
Expand Down
2 changes: 1 addition & 1 deletion zaza/openstack/charm_tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
11 changes: 9 additions & 2 deletions zaza/openstack/charm_tests/vault/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -187,12 +188,18 @@ 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_names = get_app_names_for_charm('nova-compute')
charm_apps_to_restart_svcs = (nova_compute_app_names +
['nova-cloud-controller'])

cmd_map = {
'nova-cloud-controller': ('systemctl restart '
'nova-scheduler nova-conductor'),
'nova-compute': 'systemctl restart nova-compute',
}
for app in ('nova-compute', 'nova-cloud-controller',):
for nova_compute_app_name in nova_compute_app_names:
cmd_map[nova_compute_app_name] = 'systemctl restart nova-compute'

for app in charm_apps_to_restart_svcs:
try:
for unit in zaza.model.get_units(app):
result = zaza.model.run_on_unit(
Expand Down
17 changes: 16 additions & 1 deletion zaza/openstack/utilities/openstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',)

Expand Down Expand Up @@ -2693,6 +2694,20 @@ 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 = []
for app_name, app_data in status['applications'].items():
if charm_name == app_data['charm-name']:
result.append(app_name)
return result


def is_ceph_image_backend(model_name=None):
"""Check if glance is related to ceph, therefore using ceph as backend.

Expand Down
Loading