Merge "Refactor unit tests to avoid leaks of mocks." into stable/zed

This commit is contained in:
Zuul
2023-06-01 12:39:48 +00:00
committed by Gerrit Code Review
8 changed files with 200 additions and 123 deletions

View File

@@ -90,9 +90,11 @@ def _network_manager():
return manager()
def _get_availability_zone():
from nova_compute_utils import get_availability_zone as get_az
return get_az()
def get_availability_zone():
use_juju_az = config('customize-failure-domain')
juju_az = os.environ.get('JUJU_AVAILABILITY_ZONE')
return (juju_az if use_juju_az and juju_az
else config('default-availability-zone'))
def _neutron_security_groups():
@@ -948,7 +950,7 @@ class NovaComputeAvailabilityZoneContext(context.OSContextGenerator):
def __call__(self):
ctxt = {}
ctxt['default_availability_zone'] = _get_availability_zone()
ctxt['default_availability_zone'] = get_availability_zone()
return ctxt

View File

@@ -123,7 +123,6 @@ from nova_compute_utils import (
configure_local_ephemeral_storage,
pause_unit_helper,
resume_unit_helper,
get_availability_zone,
remove_old_packages,
MULTIPATH_PACKAGES,
USE_FQDN_KEY,
@@ -140,6 +139,7 @@ from nova_compute_context import (
nova_metadata_requirement,
CEPH_SECRET_UUID,
assert_libvirt_rbd_imagebackend_allowed,
get_availability_zone,
NovaAPIAppArmorContext,
NovaComputeAppArmorContext,
NovaNetworkAppArmorContext,

View File

@@ -1235,10 +1235,3 @@ def install_mount_override(mountpoint):
{'mount_point': mountpoint.replace('/', '-')[1:]},
perms=0o644,
)
def get_availability_zone():
use_juju_az = config('customize-failure-domain')
juju_az = os.environ.get('JUJU_AVAILABILITY_ZONE')
return (juju_az if use_juju_az and juju_az
else config('default-availability-zone'))

View File

@@ -12,40 +12,58 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import importlib
import sys
from unittest.mock import patch
import os
os.environ['JUJU_UNIT_NAME'] = 'nova_compute'
import nova_compute_utils as utils # noqa
with patch('charmhelpers.core.hookenv.config') as config:
config.return_value = 'nova'
with patch('charmhelpers.contrib.openstack.context.HostInfoContext'):
import nova_compute_utils as utils # noqa
with patch('nova_compute_utils.restart_map'):
with patch('nova_compute_utils.register_configs'):
import openstack_upgrade
from test_utils import (
CharmTestCase
)
openstack_upgrade = None # placeholder for module loaded in setUpModule
TO_PATCH = [
'config_changed',
'do_openstack_upgrade'
]
def setUpModule():
# to make sure python loads a mocked version of the module we unload it
# first.
if 'openstack_upgrade' in sys.modules:
del sys.modules['openstack_upgrade']
with patch('nova_compute_utils.restart_map'):
with patch('nova_compute_utils.register_configs'):
global openstack_upgrade
openstack_upgrade = importlib.import_module('openstack_upgrade')
def tearDownModule():
# we unload the module since it was mocked, this prevents side effects.
if 'openstack_upgrade' in sys.modules:
del sys.modules['openstack_upgrade']
@patch('nova_compute_utils.register_configs')
@patch('nova_compute_utils.restart_map')
@patch('charmhelpers.core.hookenv.config')
@patch('charmhelpers.contrib.openstack.context.HostInfoContext')
class TestNovaComputeUpgradeActions(CharmTestCase):
def setUp(self):
super(TestNovaComputeUpgradeActions, self).setUp(openstack_upgrade,
TO_PATCH)
@patch.object(openstack_upgrade, 'nova_vgpu_joined')
@patch.object(openstack_upgrade, 'nova_ceilometer_joined')
@patch.object(openstack_upgrade, 'neutron_plugin_joined')
@patch.object(openstack_upgrade, 'relation_ids')
@patch('openstack_upgrade.nova_vgpu_joined')
@patch('openstack_upgrade.nova_ceilometer_joined')
@patch('openstack_upgrade.neutron_plugin_joined')
@patch('openstack_upgrade.relation_ids')
@patch('charmhelpers.contrib.openstack.utils.config')
@patch('charmhelpers.contrib.openstack.utils.action_set')
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available')
@@ -53,7 +71,8 @@ class TestNovaComputeUpgradeActions(CharmTestCase):
def test_openstack_upgrade_true(self, log, upgrade_avail,
action_set, config, relation_ids,
neutron_plugin_joined,
nova_ceilometer_joined, nova_vgpu_joined):
nova_ceilometer_joined, nova_vgpu_joined,
*args):
upgrade_avail.return_value = True
config.return_value = True
@@ -77,10 +96,10 @@ class TestNovaComputeUpgradeActions(CharmTestCase):
@patch('charmhelpers.contrib.openstack.utils.config')
@patch('charmhelpers.contrib.openstack.utils.action_set')
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available') # noqa
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available')
@patch('charmhelpers.contrib.openstack.utils.juju_log')
def test_openstack_upgrade_false(self, log, upgrade_avail,
action_set, config):
action_set, config, *args):
upgrade_avail.return_value = True
config.return_value = False

View File

@@ -12,52 +12,67 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import importlib
import sys
from unittest.mock import patch
import os
os.environ['JUJU_UNIT_NAME'] = 'nova_compute'
import nova_compute_utils as utils # noqa
with patch('charmhelpers.core.hookenv.config') as config:
config.return_value = 'nova'
with patch('charmhelpers.contrib.openstack.context.HostInfoContext'):
import nova_compute_utils as utils # noqa
with patch('nova_compute_utils.restart_map'):
with patch('nova_compute_utils.register_configs'):
import package_upgrade
from test_utils import (
CharmTestCase
)
package_upgrade = None # placeholder for module loaded in setUpModule
TO_PATCH = [
'config_changed',
'do_openstack_upgrade'
]
def setUpModule():
# to make sure python loads a mocked version of the module we unload it
# first.
if 'package_upgrade' in sys.modules:
del sys.modules['package_upgrade']
with patch('nova_compute_hooks.register_configs'):
global package_upgrade
package_upgrade = importlib.import_module('package_upgrade')
def tearDownModule():
# we unload the module since it was mocked, this prevents side effects.
if 'package_upgrade' in sys.modules:
del sys.modules['package_upgrade']
@patch('nova_compute_utils.register_configs')
@patch('nova_compute_utils.restart_map')
@patch('charmhelpers.core.hookenv.config')
@patch('charmhelpers.contrib.openstack.context.HostInfoContext')
class TestNovaComputeUpgradeActions(CharmTestCase):
def setUp(self):
super(TestNovaComputeUpgradeActions, self).setUp(package_upgrade,
TO_PATCH)
@patch.object(package_upgrade, 'relation_ids')
@patch('package_upgrade.relation_ids')
@patch('charmhelpers.contrib.openstack.utils.action_set')
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available')
@patch('charmhelpers.contrib.openstack.utils.juju_log')
def test_package_upgrade_success(self, log, upgrade_avail,
action_set, relation_ids):
action_set, relation_ids, *args):
upgrade_avail.return_value = False
package_upgrade.package_upgrade()
self.assertTrue(self.do_openstack_upgrade.called)
@patch.object(package_upgrade, 'relation_ids')
@patch('package_upgrade.relation_ids')
@patch('charmhelpers.contrib.openstack.utils.action_set')
@patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available')
@patch('charmhelpers.contrib.openstack.utils.juju_log')
def test_openstack_upgrade_failure(self, log, upgrade_avail,
action_set, relation_ids):
action_set, relation_ids, *args):
upgrade_avail.return_value = True
package_upgrade.package_upgrade()
self.assertFalse(self.do_openstack_upgrade.called)

View File

@@ -1090,6 +1090,58 @@ class NovaComputeContextTests(CharmTestCase):
'"name": " Cirrus Logic ", "product_id": "0ff2", '
'"vendor_id": "10de"}'))
@patch.object(context.os.environ, 'get')
def test_get_az_customize_with_env(self, os_environ_get_mock):
self.test_config.set('customize-failure-domain', True)
self.test_config.set('default-availability-zone', 'nova')
def os_environ_get_side_effect(key):
return {
'JUJU_AVAILABILITY_ZONE': 'az1',
}[key]
os_environ_get_mock.side_effect = os_environ_get_side_effect
az = context.get_availability_zone()
self.assertEqual('az1', az)
@patch.object(context.os.environ, 'get')
def test_get_az_customize_without_env(self, os_environ_get_mock):
self.test_config.set('customize-failure-domain', True)
self.test_config.set('default-availability-zone', 'mynova')
def os_environ_get_side_effect(key):
return {
'JUJU_AVAILABILITY_ZONE': '',
}[key]
os_environ_get_mock.side_effect = os_environ_get_side_effect
az = context.get_availability_zone()
self.assertEqual('mynova', az)
@patch.object(context.os.environ, 'get')
def test_get_az_no_customize_without_env(self, os_environ_get_mock):
self.test_config.set('customize-failure-domain', False)
self.test_config.set('default-availability-zone', 'nova')
def os_environ_get_side_effect(key):
return {
'JUJU_AVAILABILITY_ZONE': '',
}[key]
os_environ_get_mock.side_effect = os_environ_get_side_effect
az = context.get_availability_zone()
self.assertEqual('nova', az)
@patch.object(context.os.environ, 'get')
def test_get_az_no_customize_with_env(self, os_environ_get_mock):
self.test_config.set('customize-failure-domain', False)
self.test_config.set('default-availability-zone', 'nova')
def os_environ_get_side_effect(key):
return {
'JUJU_AVAILABILITY_ZONE': 'az1',
}[key]
os_environ_get_mock.side_effect = os_environ_get_side_effect
az = context.get_availability_zone()
self.assertEqual('nova', az)
class IronicAPIContextTests(CharmTestCase):
@@ -1199,7 +1251,7 @@ class NovaComputeAvailabilityZoneContextTests(CharmTestCase):
self).setUp(context, TO_PATCH)
self.os_release.return_value = 'kilo'
@patch('nova_compute_utils.config')
@patch('nova_compute_context.config')
@patch('os.environ.get')
def test_availability_zone_no_juju_with_env(self, mock_get,
mock_config):
@@ -1220,7 +1272,7 @@ class NovaComputeAvailabilityZoneContextTests(CharmTestCase):
self.assertEqual(
{'default_availability_zone': 'nova'}, az_context())
@patch('nova_compute_utils.config')
@patch('nova_compute_context.config')
@patch('os.environ.get')
def test_availability_zone_no_juju_no_env(self, mock_get,
mock_config):
@@ -1300,12 +1352,16 @@ class NovaComputeCephContextTest(CharmTestCase):
self.config.side_effect = self.test_config.get
self.os_release.return_value = 'queens'
@patch.dict(context.os.environ, {'JUJU_UNIT_NAME': 'nova_compute'},
clear=True)
@patch('charmhelpers.contrib.openstack.context.CephContext.__call__')
def test_rbd_replicated_pool(self, mock_call):
mock_call.return_value = {'mon_hosts': 'foo,bar'}
ctxt = context.NovaComputeCephContext()()
self.assertEqual(ctxt['rbd_pool'], 'nova')
@patch.dict(context.os.environ, {'JUJU_UNIT_NAME': 'nova_compute'},
clear=True)
@patch('charmhelpers.contrib.openstack.context.CephContext.__call__')
def test_rbd_ec_pool(self, mock_call):
self.test_config.set('pool-type', 'erasure-coded')

View File

@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import copy
import importlib
import json
@@ -22,7 +23,6 @@ from unittest.mock import (
MagicMock
)
from nova_compute_hooks import update_nrpe_config
from test_utils import CharmTestCase
@@ -108,6 +108,31 @@ TO_PATCH = [
]
class TestNrpeConfig(CharmTestCase):
def setUp(self):
objs_to_patch = copy.copy(TO_PATCH)
objs_to_patch.remove('update_nrpe_config')
super().setUp(hooks, objs_to_patch)
self.config.side_effect = self.test_config.get
self.filter_installed_packages.side_effect = \
MagicMock(side_effect=lambda pkgs: pkgs)
self.gethostname.return_value = 'testserver'
self.get_relation_ip.return_value = '10.0.0.50'
self.is_container.return_value = False
@patch('nova_compute_hooks.nrpe')
@patch('nova_compute_hooks.services')
@patch('charmhelpers.core.hookenv')
def test_nrpe_services_no_qemu_kvm(self, hookenv, services, nrpe):
'''
The qemu-kvm service is not monitored by NRPE, since it's one-shot.
'''
services.return_value = ['libvirtd', 'qemu-kvm', 'libvirt-bin']
hooks.update_nrpe_config()
nrpe.add_init_service_checks.assert_called_with(
ANY, ['libvirtd', 'libvirt-bin'], ANY)
class NovaComputeRelationsTests(CharmTestCase):
def setUp(self):
@@ -424,18 +449,6 @@ class NovaComputeRelationsTests(CharmTestCase):
user='nova'
)
@patch('nova_compute_hooks.nrpe')
@patch('nova_compute_hooks.services')
@patch('charmhelpers.core.hookenv')
def test_nrpe_services_no_qemu_kvm(self, hookenv, services, nrpe):
'''
The qemu-kvm service is not monitored by NRPE, since it's one-shot.
'''
services.return_value = ['libvirtd', 'qemu-kvm', 'libvirt-bin']
update_nrpe_config()
nrpe.add_init_service_checks.assert_called_with(
ANY, ['libvirtd', 'libvirt-bin'], ANY)
def test_amqp_joined(self):
hooks.amqp_joined()
self.relation_set.assert_called_with(
@@ -497,7 +510,9 @@ class NovaComputeRelationsTests(CharmTestCase):
'availability_zone': 'az1',
})
def test_compute_joined_with_ssh_migration(self):
@patch('nova_compute_context.config')
def test_compute_joined_with_ssh_migration(self, config):
config.side_effect = self.test_config.get
self.migration_enabled.return_value = True
self.test_config.set('migration-auth-type', 'ssh')
self.public_ssh_key.return_value = 'foo'
@@ -521,7 +536,9 @@ class NovaComputeRelationsTests(CharmTestCase):
'migration', cidr_network=None
)
def test_compute_joined_with_resize(self):
@patch('nova_compute_context.config')
def test_compute_joined_with_resize(self, config):
config.side_effect = self.test_config.get
self.migration_enabled.return_value = False
self.test_config.set('enable-resize', True)
self.public_ssh_key.return_value = 'bar'
@@ -902,6 +919,7 @@ class NovaComputeRelationsTests(CharmTestCase):
compression_mode='fake',
)
@patch('nova_compute_context.config')
@patch.object(hooks.ch_context, 'CephBlueStoreCompressionContext')
@patch('charmhelpers.contrib.storage.linux.ceph.CephBrokerRq'
'.add_op_request_access_to_group')
@@ -910,7 +928,8 @@ class NovaComputeRelationsTests(CharmTestCase):
@patch('uuid.uuid1')
def test_get_ceph_request_perms(self, uuid1, mock_create_pool,
mock_request_access,
mock_bluestore_compression):
mock_bluestore_compression, config):
config.side_effect = self.test_config.get
self.assert_libvirt_rbd_imagebackend_allowed.return_value = True
self.test_config.set('rbd-pool', 'nova')
self.test_config.set('ceph-osd-replication-count', 3)
@@ -987,8 +1006,10 @@ class NovaComputeRelationsTests(CharmTestCase):
default_service='nova-compute')
self.restart_failed_subordinate_services.assert_called()
@patch('nova_compute_context.config')
@patch.object(hooks, 'get_hugepage_number')
def test_neutron_plugin_joined_relid(self, get_hugepage_number):
def test_neutron_plugin_joined_relid(self, get_hugepage_number, config):
config.side_effect = self.test_config.get
get_hugepage_number.return_value = None
hooks.neutron_plugin_joined(relid='relid23')
expect_rel_settings = {
@@ -1000,11 +1021,13 @@ class NovaComputeRelationsTests(CharmTestCase):
**expect_rel_settings
)
@patch('nova_compute_context.config')
@patch('os.environ.get')
@patch.object(hooks, 'get_hugepage_number')
def test_neutron_plugin_joined_relid_juju_az(self,
get_hugepage_number,
mock_env_get):
mock_env_get, config):
config.side_effect = self.test_config.get
self.test_config.set('customize-failure-domain', True)
def environ_get_side_effect(key):
@@ -1023,8 +1046,10 @@ class NovaComputeRelationsTests(CharmTestCase):
**expect_rel_settings
)
@patch('nova_compute_context.config')
@patch.object(hooks, 'get_hugepage_number')
def test_neutron_plugin_joined_huge(self, get_hugepage_number):
def test_neutron_plugin_joined_huge(self, get_hugepage_number, config):
config.side_effect = self.test_config.get
get_hugepage_number.return_value = 12
hooks.neutron_plugin_joined()
expect_rel_settings = {
@@ -1036,8 +1061,11 @@ class NovaComputeRelationsTests(CharmTestCase):
**expect_rel_settings
)
@patch('nova_compute_context.config')
@patch.object(hooks, 'get_hugepage_number')
def test_neutron_plugin_joined_remote_restart(self, get_hugepage_number):
def test_neutron_plugin_joined_remote_restart(self, get_hugepage_number,
config):
config.side_effect = self.test_config.get
get_hugepage_number.return_value = None
self.uuid.uuid4.return_value = 'e030b959-7207'
hooks.neutron_plugin_joined(remote_restart=True)

View File

@@ -367,6 +367,8 @@ class NovaComputeUtilsTests(CharmTestCase):
for pkg in utils.MULTIPATH_PACKAGES:
self.assertFalse(pkg in result)
@patch.dict(utils.os.environ, {'JUJU_UNIT_NAME': 'nova_compute'},
clear=True)
@patch.object(utils, 'os')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'network_manager')
@@ -428,15 +430,17 @@ class NovaComputeUtilsTests(CharmTestCase):
self.assertEqual(set(ex[k]['services']),
set(result[k]['services']))
@patch.object(utils, 'os')
@patch.dict(utils.os.environ, {'JUJU_UNIT_NAME': 'nova_compute'},
clear=True)
@patch.object(utils.os.path, 'exists')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'network_manager')
def test_resource_map_nova_network_ocata(self, net_man, en_meta, _os):
def test_resource_map_nova_network_ocata(self, net_man, en_meta, exists):
self.os_release.return_value = 'ocata'
self.test_config.set('multi-host', 'yes')
en_meta.return_value = (False, None)
net_man.return_value = 'flatdhcpmanager'
_os.path.exists.return_value = False
exists.return_value = False
result = utils.resource_map()
ex = {
'/etc/default/libvirt-bin': {
@@ -484,6 +488,8 @@ class NovaComputeUtilsTests(CharmTestCase):
self.assertEqual(set(ex[k]['services']),
set(result[k]['services']))
@patch.dict(utils.os.environ, {'JUJU_UNIT_NAME': 'nova_compute'},
clear=True)
@patch.object(utils, 'os')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'network_manager')
@@ -494,6 +500,7 @@ class NovaComputeUtilsTests(CharmTestCase):
self.test_config.set('multi-host', 'yes')
net_man.return_value = 'flatdhcpmanager'
_os.path.exists.return_value = True
_os.environ['JUJU_UNIT_NAME'] = 'nova-compute'
result = utils.resource_map()
ex = {
@@ -612,6 +619,8 @@ class NovaComputeUtilsTests(CharmTestCase):
self.assertEqual(set(ex[k]['services']),
set(result[k]['services']))
@patch.dict(utils.os.environ, {'JUJU_UNIT_NAME': 'nova_compute'},
clear=True)
@patch.object(utils.os.path, 'exists')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'network_manager')
@@ -620,6 +629,8 @@ class NovaComputeUtilsTests(CharmTestCase):
self.os_release.return_value = 'diablo'
self._test_resource_map_neutron(net_man, en_meta, 'libvirt-bin')
@patch.dict(utils.os.environ, {'JUJU_UNIT_NAME': 'nova_compute'},
clear=True)
@patch.object(utils.os.path, 'exists')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'network_manager')
@@ -679,11 +690,13 @@ class NovaComputeUtilsTests(CharmTestCase):
driver = nova_config.get('DEFAULT', 'compute_driver')
self.assertEqual(driver, 'ironic.IronicDriver')
@patch.object(compute_context, 'config')
@patch.object(compute_context, 'relation_ids')
@patch.object(compute_context, 'os_release')
@patch.object(utils, 'nova_metadata_requirement')
def test_resource_map_ironic_wallaby(self, _metadata, _os_release,
_relation_ids):
_relation_ids, config):
config.side_effect = self.test_config.get
_metadata.return_value = (True, None)
self.relation_ids.return_value = []
self.os_release.return_value = 'wallaby'
@@ -696,14 +709,17 @@ class NovaComputeUtilsTests(CharmTestCase):
nova_config = self._get_rendered_config(utils.NOVA_COMPUTE_CONF,
result)
driver = nova_config.get('DEFAULT', 'compute_driver')
self.assertEqual(driver, 'libvirt.LibvirtDriver')
self.assertEqual(driver, 'ironic.IronicDriver')
@patch.object(compute_context, 'config')
@patch.object(compute_context, 'relation_ids')
@patch.object(compute_context, 'os_release')
@patch.object(utils, 'nova_metadata_requirement')
def test_resource_map_kvm(self, _metadata, _os_release, _relation_ids):
def test_resource_map_kvm(self, _metadata, _os_release, _relation_ids,
config):
"""Tests that compute_driver is set to LibvirtDriver for kvm
virt-type"""
config.side_effect = self.test_config.get
_metadata.return_value = (True, None)
self.relation_ids.return_value = []
self.os_release.return_value = 'wallaby'
@@ -1390,58 +1406,6 @@ class NovaComputeUtilsTests(CharmTestCase):
'/var/lib/nova/instances'
)
@patch.object(utils.os.environ, 'get')
def test_get_az_customize_with_env(self, os_environ_get_mock):
self.test_config.set('customize-failure-domain', True)
self.test_config.set('default-availability-zone', 'nova')
def os_environ_get_side_effect(key):
return {
'JUJU_AVAILABILITY_ZONE': 'az1',
}[key]
os_environ_get_mock.side_effect = os_environ_get_side_effect
az = utils.get_availability_zone()
self.assertEqual('az1', az)
@patch.object(utils.os.environ, 'get')
def test_get_az_customize_without_env(self, os_environ_get_mock):
self.test_config.set('customize-failure-domain', True)
self.test_config.set('default-availability-zone', 'mynova')
def os_environ_get_side_effect(key):
return {
'JUJU_AVAILABILITY_ZONE': '',
}[key]
os_environ_get_mock.side_effect = os_environ_get_side_effect
az = utils.get_availability_zone()
self.assertEqual('mynova', az)
@patch.object(utils.os.environ, 'get')
def test_get_az_no_customize_without_env(self, os_environ_get_mock):
self.test_config.set('customize-failure-domain', False)
self.test_config.set('default-availability-zone', 'nova')
def os_environ_get_side_effect(key):
return {
'JUJU_AVAILABILITY_ZONE': '',
}[key]
os_environ_get_mock.side_effect = os_environ_get_side_effect
az = utils.get_availability_zone()
self.assertEqual('nova', az)
@patch.object(utils.os.environ, 'get')
def test_get_az_no_customize_with_env(self, os_environ_get_mock):
self.test_config.set('customize-failure-domain', False)
self.test_config.set('default-availability-zone', 'nova')
def os_environ_get_side_effect(key):
return {
'JUJU_AVAILABILITY_ZONE': 'az1',
}[key]
os_environ_get_mock.side_effect = os_environ_get_side_effect
az = utils.get_availability_zone()
self.assertEqual('nova', az)
@patch.object(utils, "libvirt_daemon")
@patch.object(utils, "hook_name")
@patch.object(utils, "get_subordinate_services")