charm-nova-compute/unit_tests/test_nova_compute_utils.py
Liam Young cb04103e08 Do not manage subordinate service restarts
The subordinate charms should manage the services that
they deploys and configure, not the principle they are related to.
This change switches the approach for restarting services
from having the nova-compute charm doing it directly to having
nova-compute triggering the restart by request a restart down
the existing relations.

Closes-Bug: #1947585

Change-Id: I7419e39d68c70d21a11d03deeff9699421b0571e
2023-03-02 13:54:15 +00:00

1453 lines
59 KiB
Python

# Copyright 2016-2021 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.
import configparser
import os
import tempfile
import charmhelpers.contrib.openstack.utils as os_utils
import charmhelpers.contrib.openstack.templating as os_templating
import nova_compute_context as compute_context
import nova_compute_utils as utils
from unittest.mock import (
patch,
MagicMock,
call
)
from test_utils import (
CharmTestCase,
patch_open,
TestKV,
)
VIRSH_NET_LIST = """ Name State Autostart Persistent
----------------------------------------------------------
somenet active yes yes
default active yes yes
altnet active yes yes
"""
TO_PATCH = [
'apt_install',
'apt_update',
'apt_purge',
'apt_autoremove',
'apt_mark',
'filter_missing_packages',
'config',
'os_release',
'log',
'related_units',
'relation_ids',
'relation_get',
'service_restart',
'mkdir',
'install_alternative',
'MetadataServiceContext',
'lsb_release',
'charm_dir',
'hugepage_support',
'rsync',
'Fstab',
'os_application_version_set',
'lsb_release',
'storage_list',
'storage_get',
'vaultlocker',
'kv',
'check_call',
'mkfs_xfs',
'is_block_device',
'is_device_mounted',
'fstab_add',
'mount',
]
class NovaComputeUtilsTests(CharmTestCase):
def setUp(self):
super(NovaComputeUtilsTests, self).setUp(utils, TO_PATCH)
self.config.side_effect = self.test_config.get
self.charm_dir.return_value = 'mycharm'
self.lsb_release.return_value = {'DISTRIB_CODENAME': 'precise'}
self.test_kv = TestKV()
self.kv.return_value = self.test_kv
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'network_manager')
@patch('platform.machine')
def test_determine_packages_nova_network(
self, machine, net_man, en_meta,
mock_get_subordinate_release_packages):
self.os_release.return_value = 'icehouse'
en_meta.return_value = (False, None)
net_man.return_value = 'flatdhcpmanager'
machine.return_value = 'x86_64'
self.relation_ids.return_value = []
mock_get_subordinate_release_packages.return_value = \
os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
ex = utils.BASE_PACKAGES + [
'nova-api',
'nova-network',
'nova-compute-kvm'
]
self.assertTrue(ex.sort() == result.sort())
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
def test_determine_packages_swtpm_victoria(self, en_meta, sub_pkgs):
"""Tests that on a version less than Wallaby, the swtpm libraries are
not installed."""
self.os_release.return_value = 'victoria'
en_meta.return_value = (False, None)
self.relation_ids.return_value = []
sub_pkgs.return_value = os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
self.assertTrue(utils.BASE_PACKAGES.sort() == result.sort())
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
def test_determine_packages_swtpm_wallaby(self, en_meta, sub_pkgs):
"""Tests that on a version equal to Wallaby, the swtpm libraries are
not installed."""
self.os_release.return_value = 'wallaby'
en_meta.return_value = (False, None)
self.relation_ids.return_value = []
sub_pkgs.return_value = os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
ex = utils.BASE_PACKAGES + utils.SWTPM_PACKAGES
self.assertTrue(ex.sort() == result.sort())
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
def test_determine_packages_swtpm_disabled_w(self, en_meta, sub_pkgs):
"""Tests that on a version equal to Wallaby, with vtpm disabled the
packages are not selected for installation"""
self.os_release.return_value = 'wallaby'
en_meta.return_value = (False, None)
self.test_config.set('enable-vtpm', False)
self.relation_ids.return_value = []
sub_pkgs.return_value = os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
ex = utils.BASE_PACKAGES + utils.SWTPM_PACKAGES
self.assertTrue(ex.sort() == result.sort())
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
def test_determine_packages_ironic(self, en_meta,
mock_get_subordinate_release_packages):
self.os_release.return_value = 'victoria'
self.test_config.set('virt-type', 'ironic')
en_meta.return_value = (False, None)
self.relation_ids.return_value = []
mock_get_subordinate_release_packages.return_value = \
os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
ex = utils.BASE_PACKAGES + [
'nova-compute-ironic'
]
self.assertTrue(ex.sort() == result.sort())
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
def test_determine_packages_ironic_pre_victoria(
self, en_meta, mock_get_subordinate_release_packages):
self.os_release.return_value = 'train'
self.test_config.set('virt-type', 'ironic')
en_meta.return_value = (False, None)
self.relation_ids.return_value = []
mock_get_subordinate_release_packages.return_value = \
os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
ex = utils.BASE_PACKAGES + [
'nova-compute-vmware',
'python3-ironicclient'
]
self.assertTrue(ex.sort() == result.sort())
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'network_manager')
@patch('platform.machine')
def test_determine_packages_nova_network_ocata(
self, machine, net_man, en_meta,
mock_get_subordinate_release_packages):
self.os_release.return_value = 'ocata'
en_meta.return_value = (False, None)
net_man.return_value = 'flatdhcpmanager'
machine.return_value = 'x86_64'
self.relation_ids.return_value = []
mock_get_subordinate_release_packages.return_value = \
os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
ex = utils.BASE_PACKAGES + [
'nova-compute-kvm'
]
self.assertTrue(ex.sort() == result.sort())
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'neutron_plugin')
@patch.object(utils, 'network_manager')
@patch('platform.machine')
def test_determine_packages_neutron(
self, machine, net_man, n_plugin, en_meta,
mock_get_subordinate_release_packages):
self.os_release.return_value = 'ocata'
en_meta.return_value = (False, None)
net_man.return_value = 'neutron'
n_plugin.return_value = 'ovs'
machine.return_value = 'x86_64'
self.relation_ids.return_value = []
mock_get_subordinate_release_packages.return_value = \
os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
ex = utils.BASE_PACKAGES + ['nova-compute-kvm']
self.assertTrue(ex.sort() == result.sort())
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'neutron_plugin')
@patch.object(utils, 'network_manager')
@patch('platform.machine')
def test_determine_packages_neutron_rocky(
self, machine, net_man, n_plugin, en_meta,
mock_get_subordinate_release_packages):
self.os_release.return_value = 'rocky'
en_meta.return_value = (False, None)
net_man.return_value = 'neutron'
n_plugin.return_value = 'ovs'
machine.return_value = 'x86_64'
self.relation_ids.return_value = []
mock_get_subordinate_release_packages.return_value = \
os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
ex = (
[p for p in utils.BASE_PACKAGES
if not p.startswith('python-')] +
['nova-compute-kvm'] +
utils.PY3_PACKAGES +
['python3-ceilometer', 'python3-neutron', 'python3-neutron-fwaas']
)
self.assertTrue(ex.sort() == result.sort())
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'neutron_plugin')
@patch.object(utils, 'network_manager')
@patch('platform.machine')
def test_determine_packages_neutron_aarch64_xenial(
self, machine, net_man, n_plugin, en_meta,
mock_get_subordinate_release_packages):
self.os_release.return_value = 'ocata'
self.lsb_release.return_value = {
'DISTRIB_CODENAME': 'xenial'
}
en_meta.return_value = (False, None)
net_man.return_value = 'neutron'
n_plugin.return_value = 'ovs'
machine.return_value = 'aarch64'
self.relation_ids.return_value = []
mock_get_subordinate_release_packages.return_value = \
os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
ex = utils.BASE_PACKAGES + ['nova-compute-kvm', 'qemu-efi']
self.assertTrue(ex.sort() == result.sort())
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'neutron_plugin')
@patch.object(utils, 'network_manager')
@patch('platform.machine')
def test_determine_packages_neutron_aarch64_trusty(
self, machine, net_man, n_plugin, en_meta,
mock_get_subordinate_release_packages):
self.os_release.return_value = 'ocata'
self.lsb_release.return_value = {
'DISTRIB_CODENAME': 'trusty'
}
en_meta.return_value = (False, None)
net_man.return_value = 'neutron'
n_plugin.return_value = 'ovs'
machine.return_value = 'aarch64'
self.relation_ids.return_value = []
mock_get_subordinate_release_packages.return_value = \
os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
ex = utils.BASE_PACKAGES + ['nova-compute-kvm']
self.assertTrue(ex.sort() == result.sort())
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'neutron_plugin')
@patch.object(utils, 'network_manager')
@patch('platform.machine')
def test_determine_packages_neutron_ceph(
self, machine, net_man, n_plugin, en_meta,
mock_get_subordinate_release_packages):
self.os_release.return_value = 'ocata'
en_meta.return_value = (False, None)
net_man.return_value = 'neutron'
n_plugin.return_value = 'ovs'
machine.return_value = 'x86_64'
self.relation_ids.return_value = ['ceph:0']
mock_get_subordinate_release_packages.return_value = \
os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
ex = (utils.BASE_PACKAGES + ['ceph-common', 'nova-compute-kvm'])
self.assertTrue(ex.sort() == result.sort())
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'neutron_plugin')
@patch.object(utils, 'network_manager')
def test_determine_packages_metadata(
self, net_man, n_plugin, en_meta,
mock_get_subordinate_release_packages):
self.os_release.return_value = 'ocata'
en_meta.return_value = (True, None)
net_man.return_value = 'bob'
n_plugin.return_value = 'ovs'
self.relation_ids.return_value = []
mock_get_subordinate_release_packages.return_value = \
os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
self.assertTrue('nova-api-metadata' in result)
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'neutron_plugin')
@patch.object(utils, 'network_manager')
def test_determine_packages_use_multipath(
self, net_man, n_plugin, en_meta,
mock_get_subordinate_release_packages):
self.os_release.return_value = 'ocata'
en_meta.return_value = (False, None)
net_man.return_value = 'bob'
self.test_config.set('use-multipath', True)
self.relation_ids.return_value = []
mock_get_subordinate_release_packages.return_value = \
os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
for pkg in utils.MULTIPATH_PACKAGES:
self.assertTrue(pkg in result)
@patch.object(utils, 'get_subordinate_release_packages')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'neutron_plugin')
@patch.object(utils, 'network_manager')
def test_determine_packages_no_multipath(
self, net_man, n_plugin, en_meta,
mock_get_subordinate_release_packages):
self.os_release.return_value = 'ocata'
en_meta.return_value = (False, None)
net_man.return_value = 'bob'
self.test_config.set('use-multipath', False)
self.relation_ids.return_value = []
mock_get_subordinate_release_packages.return_value = \
os_utils.SubordinatePackages(set(), set())
result = utils.determine_packages()
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')
def test_resource_map_nova_network_no_multihost(self, net_man, en_meta,
_os):
self.os_release.return_value = 'icehouse'
self.test_config.set('multi-host', 'no')
en_meta.return_value = (False, None)
net_man.return_value = 'flatdhcpmanager'
_os.path.exists.return_value = True
result = utils.resource_map()
ex = {
'/etc/default/libvirt-bin': {
'contexts': [],
'services': ['libvirt-bin']
},
'/etc/libvirt/qemu.conf': {
'contexts': [],
'services': ['libvirt-bin']
},
'/etc/nova/nova.conf': {
'contexts': [],
'services': ['nova-compute']
},
'/etc/nova/vendor_data.json': {
'contexts': [],
'services': []
},
'/etc/ceph/secret.xml': {
'contexts': [],
'services': []
},
'/var/lib/charm/nova_compute/ceph.conf': {
'contexts': [],
'services': ['nova-compute']
},
'/etc/default/qemu-kvm': {
'contexts': [],
'services': ['qemu-kvm']
},
'/etc/init/libvirt-bin.override': {
'contexts': [],
'services': ['libvirt-bin']
},
'/etc/libvirt/libvirtd.conf': {
'contexts': [],
'services': ['libvirt-bin']
},
'/etc/apparmor.d/usr.bin.nova-compute': {
'contexts': [],
'services': ['nova-compute']
},
}
# Mocking contexts is tricky but we can still test that
# the correct files are monitored and the correct services
# will be started
self.assertEqual(set(ex.keys()), set(result.keys()))
for k in ex.keys():
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')
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'
exists.return_value = False
result = utils.resource_map()
ex = {
'/etc/default/libvirt-bin': {
'contexts': [],
'services': ['libvirtd']
},
'/etc/libvirt/qemu.conf': {
'contexts': [],
'services': ['libvirtd']
},
'/etc/nova/nova.conf': {
'contexts': [],
'services': ['nova-compute']
},
'/etc/nova/vendor_data.json': {
'contexts': [],
'services': []
},
'/etc/ceph/secret.xml': {
'contexts': [],
'services': []
},
'/var/lib/charm/nova_compute/ceph.conf': {
'contexts': [],
'services': ['nova-compute']
},
'/etc/default/qemu-kvm': {
'contexts': [],
'services': ['qemu-kvm']
},
'/etc/libvirt/libvirtd.conf': {
'contexts': [],
'services': ['libvirtd']
},
'/etc/apparmor.d/usr.bin.nova-compute': {
'contexts': [],
'services': ['nova-compute']
},
}
# Mocking contexts is tricky but we can still test that
# the correct files are monitored and the correct services
# will be started
self.assertEqual(set(ex.keys()), set(result.keys()))
for k in ex.keys():
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')
def test_resource_map_nova_network(self, net_man, en_meta, _os):
self.os_release.return_value = 'icehouse'
en_meta.return_value = (False, None)
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 = {
'/etc/default/libvirt-bin': {
'contexts': [],
'services': ['libvirt-bin']
},
'/etc/libvirt/qemu.conf': {
'contexts': [],
'services': ['libvirt-bin']
},
'/etc/nova/nova.conf': {
'contexts': [],
'services': ['nova-compute', 'nova-api', 'nova-network']
},
'/etc/nova/vendor_data.json': {
'contexts': [],
'services': []
},
'/etc/ceph/secret.xml': {
'contexts': [],
'services': []
},
'/var/lib/charm/nova_compute/ceph.conf': {
'contexts': [],
'services': ['nova-compute']
},
'/etc/default/qemu-kvm': {
'contexts': [],
'services': ['qemu-kvm']
},
'/etc/init/libvirt-bin.override': {
'contexts': [],
'services': ['libvirt-bin']
},
'/etc/libvirt/libvirtd.conf': {
'contexts': [],
'services': ['libvirt-bin']
},
'/etc/apparmor.d/usr.bin.nova-network': {
'contexts': [],
'services': ['nova-network']
},
'/etc/apparmor.d/usr.bin.nova-compute': {
'contexts': [],
'services': ['nova-compute']
},
'/etc/apparmor.d/usr.bin.nova-api': {
'contexts': [],
'services': ['nova-api']
},
}
# Mocking contexts is tricky but we can still test that
# the correct files are monitored and the correct services
# will be started
self.assertEqual(set(ex.keys()), set(result.keys()))
for k in ex.keys():
self.assertEqual(set(ex[k]['services']),
set(result[k]['services']))
def _test_resource_map_neutron(self, net_man, en_meta,
libvirt_daemon):
en_meta.return_value = (False, None)
self.test_config.set('multi-host', 'yes')
net_man.return_value = 'neutron'
result = utils.resource_map()
ex = {
'/etc/default/libvirt-bin': {
'contexts': [],
'services': [libvirt_daemon]
},
'/etc/libvirt/qemu.conf': {
'contexts': [],
'services': [libvirt_daemon]
},
'/etc/nova/nova.conf': {
'contexts': [],
'services': ['nova-compute']
},
'/etc/nova/vendor_data.json': {
'contexts': [],
'services': []
},
'/etc/ceph/secret.xml': {
'contexts': [],
'services': []
},
'/var/lib/charm/nova_compute/ceph.conf': {
'contexts': [],
'services': ['nova-compute']
},
'/etc/default/qemu-kvm': {
'contexts': [],
'services': ['qemu-kvm']
},
'/etc/init/libvirt-bin.override': {
'contexts': [],
'services': [libvirt_daemon]
},
'/etc/libvirt/libvirtd.conf': {
'contexts': [],
'services': [libvirt_daemon]
},
'/etc/apparmor.d/usr.bin.nova-compute': {
'contexts': [],
'services': ['nova-compute']
},
}
# Mocking contexts is tricky but we can still test that
# the correct files are monitored and the correct services
# will be started
self.assertEqual(set(ex.keys()), set(result.keys()))
for k in ex.keys():
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')
def test_resource_map_neutron(self, net_man, en_meta, exists):
exists.return_value = True
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')
def test_resource_map_neutron_yakkety(self, net_man, en_meta, exists):
exists.return_value = True
self.lsb_release.return_value = {'DISTRIB_CODENAME': 'yakkety'}
self.os_release.return_value = 'diablo'
self._test_resource_map_neutron(net_man, en_meta, 'libvirtd')
@patch.object(utils, 'nova_metadata_requirement')
@patch.object(utils, 'neutron_plugin')
@patch.object(utils, 'network_manager')
def test_resource_map_metadata(self, net_man, _plugin, _metadata):
_metadata.return_value = (True, None)
net_man.return_value = 'bob'
_plugin.return_value = 'ovs'
self.relation_ids.return_value = []
self.os_release.return_value = 'diablo'
result = utils.resource_map()['/etc/nova/nova.conf']['services']
self.assertTrue('nova-api-metadata' in result)
@patch.object(compute_context, 'os_release')
def _get_rendered_template(self, template, resource_map, _os_release):
_os_release.return_value = self.os_release.return_value
# Validate the template written is configured for the IronicDriver
renderer = os_templating.OSConfigRenderer(
templates_dir=utils.TEMPLATES,
openstack_release=self.os_release()
)
renderer.register(template, resource_map[template]['contexts'])
return renderer.render(template)
def _get_rendered_config(self, template, resource_map):
content = self._get_rendered_template(template, resource_map)
rendered_config = configparser.ConfigParser()
rendered_config.read_string(content)
return rendered_config
@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_train(self, _metadata, _os_release,
_relation_ids, cctxt_config):
_metadata.return_value = (True, None)
self.relation_ids.return_value = []
self.os_release.return_value = 'train'
_os_release.return_value = 'train'
self.test_config.set('virt-type', 'ironic')
cctxt_config.side_effect = self.test_config.get
result = utils.resource_map()
self.assertTrue(utils.NOVA_COMPUTE_CONF in result)
self.assertFalse(utils.QEMU_CONF in result)
nova_config = self._get_rendered_config(utils.NOVA_COMPUTE_CONF,
result)
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, config):
config.side_effect = self.test_config.get
_metadata.return_value = (True, None)
self.relation_ids.return_value = []
self.os_release.return_value = 'wallaby'
_os_release.return_value = 'wallaby'
self.test_config.set('virt-type', 'ironic')
result = utils.resource_map()
self.assertTrue(utils.NOVA_COMPUTE_CONF in result)
self.assertFalse(utils.QEMU_CONF in result)
nova_config = self._get_rendered_config(utils.NOVA_COMPUTE_CONF,
result)
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_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'
_os_release.return_value = 'wallaby'
self.test_config.set('virt-type', 'kvm')
result = utils.resource_map()
self.assertTrue(utils.NOVA_COMPUTE_CONF in result)
qemu_contexts = [type(c) for c in result[utils.QEMU_CONF]['contexts']]
self.assertNotIn(
compute_context.NovaComputeLibvirtContext,
qemu_contexts)
nova_config = self._get_rendered_config(utils.NOVA_COMPUTE_CONF,
result)
driver = nova_config.get('DEFAULT', 'compute_driver')
self.assertEqual(driver, 'libvirt.LibvirtDriver')
@patch.object(compute_context, 'relation_ids')
@patch.object(compute_context, 'config')
@patch.object(compute_context, 'os_release')
@patch.object(utils, 'nova_metadata_requirement')
def test_resource_map_vtpm_enabled(self, _metadata, _os_release, _config,
_relation_ids):
"""Tests that the proper config values are set in nova-compute when
vtpm is enabled."""
_metadata.return_value = (True, None)
_config.side_effect = self.test_config.get
self.relation_ids.return_value = []
self.os_release.return_value = 'wallaby'
_os_release.return_value = 'wallaby'
self.test_config.set('enable-vtpm', True)
result = utils.resource_map()
self.assertTrue(utils.NOVA_COMPUTE_CONF in result)
self.assertTrue(utils.QEMU_CONF in result)
# By default, swtpm should be enabled with the proper swtpm_user and
# swtpm_group configured for the Ubuntu packages.
nova_config = self._get_rendered_config(utils.NOVA_COMPUTE_CONF,
result)
self.assertTrue(nova_config.get('libvirt', 'swtpm_enabled'))
self.assertEqual(nova_config.get('libvirt', 'swtpm_user'), 'swtpm')
self.assertEqual(nova_config.get('libvirt', 'swtpm_group'), 'swtpm')
# Also, when vtpm is enabled the qemu.conf file renders the
# swtpm_user and swtpm_group information.
qemu_conf = self._get_rendered_template(utils.QEMU_CONF, result)
self.assertTrue(qemu_conf.find('swtpm_user = "swtpm"\n') >= 0)
self.assertTrue(qemu_conf.find('swtpm_group = "swtpm"\n') >= 0)
@patch.object(compute_context, 'relation_ids')
@patch.object(compute_context, 'config')
@patch.object(compute_context, 'os_release')
@patch.object(utils, 'nova_metadata_requirement')
def test_resource_map_vtpm_disabled(self, _metadata, _os_release, _config,
_relation_ids):
"""Tests that the proper config values are set in nova-compute when
vtpm is not enabled."""
_metadata.return_value = (True, None)
_config.side_effect = self.test_config.get
self.relation_ids.return_value = []
self.os_release.return_value = 'wallaby'
_os_release.return_value = 'wallaby'
# Now, test the rendered files when vtpm is disabled
self.test_config.set('enable-vtpm', False)
result = utils.resource_map()
self.assertTrue(utils.NOVA_COMPUTE_CONF in result)
self.assertTrue(utils.QEMU_CONF in result)
# By default, swtpm should be enabled with the proper swtpm_user and
# swtpm_group configured for the Ubuntu packages.
nova_config = self._get_rendered_config(utils.NOVA_COMPUTE_CONF,
result)
self.assertFalse(nova_config.has_option('libvirt', 'swtpm_enabled'))
self.assertFalse(nova_config.has_option('libvirt', 'swtpm_user'))
self.assertFalse(nova_config.has_option('libvirt', 'swtpm_group'))
# Also, the qemu.conf file should not have the swtpm_user/group anymore
qemu_conf = self._get_rendered_template(utils.QEMU_CONF, result)
self.assertFalse(qemu_conf.find('swtpm_user = "swtpm"\n') >= 0)
self.assertFalse(qemu_conf.find('swtpm_group = "swtpm"\n') >= 0)
def fake_user(self, username='foo'):
user = MagicMock()
user.pw_dir = '/home/' + username
return user
@patch('builtins.open')
@patch('pwd.getpwnam')
def test_public_ssh_key_not_found(self, getpwnam, _open):
_open.side_effect = OSError
getpwnam.return_value = self.fake_user('foo')
self.assertEqual(None, utils.public_ssh_key())
@patch('pwd.getpwnam')
def test_public_ssh_key(self, getpwnam):
getpwnam.return_value = self.fake_user('foo')
with patch_open() as (_open, _file):
_file.read.return_value = 'mypubkey'
result = utils.public_ssh_key('foo')
self.assertEqual(result, 'mypubkey')
def test_import_authorized_keys_missing_data(self):
self.relation_get.return_value = None
with patch_open() as (_open, _file):
utils.import_authorized_keys(user='foo')
self.assertFalse(_open.called)
@patch('pwd.getpwnam')
def _test_import_authorized_keys_base(self, getpwnam, prefix=None,
auth_key_path='/home/foo/.ssh/'
'authorized_keys'):
getpwnam.return_value = self.fake_user('foo')
d = {
'known_hosts_max_index': 3,
'known_hosts_0': 'k_h_0',
'known_hosts_1': 'k_h_1',
'known_hosts_2': 'k_h_2',
'authorized_keys_max_index': 3,
'authorized_keys_0': 'auth_0',
'authorized_keys_1': 'auth_1',
'authorized_keys_2': 'auth_2',
}
if prefix:
for k, v in d.copy().items():
d["{}_{}".format(prefix, k)] = v
def _relation_get(scope=None, *args, **kwargs):
if scope is not None:
return d.get(scope, None)
return d
self.relation_get.side_effect = _relation_get
ex_open = [
call('/home/foo/.ssh/known_hosts', 'wt'),
call(auth_key_path, 'wt')
]
ex_write = [
call('k_h_0\n'),
call('k_h_1\n'),
call('k_h_2\n'),
call('auth_0\n'),
call('auth_1\n'),
call('auth_2\n')
]
# we only have to verify that the files are written as expected as this
# implicitly checks that the relation_get calls have occurred.
with patch_open() as (_open, _file):
utils.import_authorized_keys(user='foo', prefix=prefix)
self.assertEqual(ex_open, _open.call_args_list)
self.assertEqual(ex_write, _file.write.call_args_list)
def test_import_authorized_keys_noprefix(self):
self._test_import_authorized_keys_base()
def test_import_authorized_keys_prefix(self):
self._test_import_authorized_keys_base(prefix='bar')
def test_import_authorized_keys_authkeypath(self):
nonstandard_path = '/etc/ssh/user-authorized-keys/{username}'
self.test_config.set('authorized-keys-path', nonstandard_path)
self._test_import_authorized_keys_base(
auth_key_path='/etc/ssh/user-authorized-keys/foo')
@patch('subprocess.check_call')
def test_import_keystone_cert_missing_data(self, check_call):
self.relation_get.return_value = None
with patch_open() as (_open, _file):
utils.import_keystone_ca_cert()
self.assertFalse(_open.called)
self.assertFalse(check_call.called)
@patch.object(utils, 'check_call')
def test_import_keystone_cert(self, check_call):
self.relation_get.return_value = 'Zm9vX2NlcnQK'
with patch_open() as (_open, _file):
utils.import_keystone_ca_cert()
_open.assert_called_with(utils.CA_CERT_PATH, 'wb')
_file.write.assert_called_with(b'foo_cert\n')
check_call.assert_called_with(['update-ca-certificates'])
@patch.object(utils, 'ceph_config_file')
@patch('charmhelpers.contrib.openstack.templating.OSConfigRenderer')
@patch.object(utils, 'resource_map')
def test_register_configs(self, resource_map, renderer,
mock_ceph_config_file):
self.os_release.return_value = 'havana'
fake_renderer = MagicMock()
fake_renderer.register = MagicMock()
renderer.return_value = fake_renderer
ctxt1 = MagicMock()
ctxt2 = MagicMock()
rsc_map = {
'/etc/nova/nova.conf': {
'services': ['nova-compute'],
'contexts': [ctxt1],
},
'/etc/nova/nova-compute.conf': {
'services': ['nova-compute'],
'contexts': [ctxt2],
},
}
resource_map.return_value = rsc_map
with tempfile.NamedTemporaryFile() as tmpfile:
mock_ceph_config_file.return_value = tmpfile.name
utils.register_configs()
renderer.assert_called_with(
openstack_release='havana', templates_dir='templates/')
ex_reg = [
call('/etc/nova/nova.conf', [ctxt1]),
call('/etc/nova/nova-compute.conf', [ctxt2]),
]
fake_renderer.register.assert_has_calls(ex_reg, any_order=True)
@patch.object(utils, 'check_call')
def test_enable_shell(self, _check_call):
utils.enable_shell('dummy')
_check_call.assert_called_with(['usermod', '-s', '/bin/bash', 'dummy'])
@patch.object(utils, 'check_call')
def test_disable_shell(self, _check_call):
utils.disable_shell('dummy')
_check_call.assert_called_with(['usermod', '-s', '/bin/false',
'dummy'])
@patch.object(utils, 'check_call')
def test_configure_subuid(self, _check_call):
utils.configure_subuid('dummy')
_check_call.assert_called_with(['usermod', '-v', '100000-200000',
'-w', '100000-200000', 'dummy'])
@patch.object(utils, 'check_call')
@patch.object(utils, 'check_output')
def test_create_libvirt_key(self, _check_output, _check_call):
key = 'AQCR2dRUaFQSOxAAC5fr79sLL3d7wVvpbbRFMg=='
self.test_config.set('virt-type', 'kvm')
utils.create_libvirt_secret(utils.CEPH_SECRET,
compute_context.CEPH_SECRET_UUID, key)
_check_output.assert_called_with(['virsh', '-c',
utils.LIBVIRT_URIS['kvm'],
'secret-list'])
_check_call.assert_called_with(['virsh', '-c',
utils.LIBVIRT_URIS['kvm'],
'secret-set-value', '--secret',
compute_context.CEPH_SECRET_UUID,
'--base64', key])
@patch.object(utils, 'check_call')
@patch.object(utils, 'check_output')
def test_create_libvirt_key_existing(self, _check_output, _check_call):
key = 'AQCR2dRUaFQSOxAAC5fr79sLL3d7wVvpbbRFMg=='
old_key = 'AQCR2dRUaFQSOxAAC5fr79sLL3d7wVvpbbRFMg==\n'
self.test_config.set('virt-type', 'kvm')
_check_output.side_effect = [
compute_context.CEPH_SECRET_UUID.encode(),
old_key.encode()]
utils.create_libvirt_secret(utils.CEPH_SECRET,
compute_context.CEPH_SECRET_UUID, key)
expected = [call(['virsh', '-c',
utils.LIBVIRT_URIS['kvm'], 'secret-list']),
call(['virsh', '-c',
utils.LIBVIRT_URIS['kvm'], 'secret-get-value',
compute_context.CEPH_SECRET_UUID])]
_check_output.assert_has_calls(expected)
self.assertFalse(_check_call.called)
@patch.object(utils, 'check_call')
@patch.object(utils, 'check_output')
def test_create_libvirt_key_stale(self, _check_output, _check_call):
key = 'AQCR2dRUaFQSOxAAC5fr79sLL3d7wVvpbbRFMg=='
old_key = 'CCCCCdRUaFQSOxAAC5fr79sLL3d7wVvpbbRFMg=='
self.test_config.set('virt-type', 'kvm')
_check_output.side_effect = [
compute_context.CEPH_SECRET_UUID.encode(),
old_key.encode()]
utils.create_libvirt_secret(utils.CEPH_SECRET,
compute_context.CEPH_SECRET_UUID, key)
expected = [call(['virsh', '-c',
utils.LIBVIRT_URIS['kvm'], 'secret-list']),
call(['virsh', '-c',
utils.LIBVIRT_URIS['kvm'], 'secret-get-value',
compute_context.CEPH_SECRET_UUID])]
_check_output.assert_has_calls(expected)
_check_call.assert_any_call(['virsh', '-c',
utils.LIBVIRT_URIS['kvm'],
'secret-set-value', '--secret',
compute_context.CEPH_SECRET_UUID,
'--base64', key])
@patch.object(utils, 'lxc_list')
@patch.object(utils, 'configure_subuid')
def test_configure_lxd_vivid(self, _configure_subuid, _lxc_list):
self.lsb_release.return_value = {
'DISTRIB_CODENAME': 'vivid'
}
utils.configure_lxd('nova')
_configure_subuid.assert_called_with('nova')
_lxc_list.assert_called_with('nova')
@patch.object(utils, 'lxc_list')
@patch.object(utils, 'configure_subuid')
def test_configure_lxd_pre_vivid(self, _configure_subuid, _lxc_list):
self.lsb_release.return_value = {
'DISTRIB_CODENAME': 'trusty'
}
with self.assertRaises(Exception):
utils.configure_lxd('nova')
self.assertFalse(_configure_subuid.called)
@patch('psutil.virtual_memory')
@patch('subprocess.check_call')
@patch('subprocess.call')
def test_install_hugepages(self, _call, _check_call, _virt_mem):
class mem(object):
def __init__(self):
self.total = 10000000 * 1024
self.test_config.set('hugepages', '10%')
_virt_mem.side_effect = mem
_call.return_value = 1
utils.install_hugepages()
self.hugepage_support.assert_called_with(
'nova',
mnt_point='/run/hugepages/kvm',
group='root',
nr_hugepages=488,
mount=False,
set_shmmax=True,
)
check_call_calls = [
call('/etc/init.d/qemu-hugefsdir'),
call(['update-rc.d', 'qemu-hugefsdir', 'defaults']),
]
_check_call.assert_has_calls(check_call_calls)
self.Fstab.remove_by_mountpoint.assert_called_with(
'/run/hugepages/kvm')
@patch('psutil.virtual_memory')
@patch('subprocess.check_call')
@patch('subprocess.call')
def test_install_hugepages_explicit_size(self, _call, _check_call,
_virt_mem):
self.test_config.set('hugepages', '2048')
utils.install_hugepages()
self.hugepage_support.assert_called_with(
'nova',
mnt_point='/run/hugepages/kvm',
group='root',
nr_hugepages=2048,
mount=False,
set_shmmax=True,
)
@patch.object(utils, 'is_unit_paused_set')
@patch.object(utils, 'services')
def test_assess_status(self, services, mock_is_paused):
services.return_value = 's1'
mock_is_paused.return_value = False
with patch.object(utils, 'assess_status_func') as asf:
callee = MagicMock()
asf.return_value = callee
utils.assess_status('test-config')
asf.assert_called_once_with('test-config', 's1')
callee.assert_called_once_with()
self.os_application_version_set.assert_called_with(
utils.VERSION_PACKAGE
)
@patch.object(utils, 'os_release')
@patch.object(utils, 'is_unit_paused_set')
@patch.object(utils, 'services')
def test_assess_status_paused(self, services, mock_is_paused,
mock_os_release):
services.return_value = ['qemu-kvm', 'libvirtd', 'nova-compute']
mock_is_paused.return_value = True
mock_os_release.return_value = 'pike'
with patch.object(utils, 'assess_status_func') as asf:
callee = MagicMock()
asf.return_value = callee
utils.assess_status('test-config')
asf.assert_called_once_with('test-config',
['qemu-kvm', 'nova-compute'])
callee.assert_called_once_with()
self.os_application_version_set.assert_called_with(
utils.VERSION_PACKAGE
)
@patch.object(utils, 'REQUIRED_INTERFACES')
@patch.object(utils, 'services')
@patch.object(utils, 'make_assess_status_func')
@patch.object(utils, 'get_optional_relations')
def test_assess_status_func(self,
get_optional_relations,
make_assess_status_func,
services,
REQUIRED_INTERFACES):
services.return_value = ['s1']
REQUIRED_INTERFACES.copy.return_value = {'test-interface': True}
get_optional_relations.return_value = {'optional': False}
test_interfaces = {
'test-interface': True,
'optional': False,
}
utils.assess_status_func('test-config')
# ports=None whilst port checks are disabled.
make_assess_status_func.assert_called_once_with(
'test-config', test_interfaces,
charm_func=utils.check_optional_config_and_relations,
services=['s1'], ports=None)
def test_pause_unit_helper(self):
with patch.object(utils, '_pause_resume_helper') as prh:
utils.pause_unit_helper('random-config')
prh.assert_called_once_with(utils.pause_unit, 'random-config')
with patch.object(utils, '_pause_resume_helper') as prh:
utils.resume_unit_helper('random-config')
prh.assert_called_once_with(utils.resume_unit, 'random-config')
@patch.object(utils, 'os_release')
@patch.object(utils, 'is_unit_paused_set')
@patch.object(utils, 'services')
def test_pause_resume_helper(self, services, mock_is_paused,
mock_os_release):
f = MagicMock()
services.return_value = ['s1']
mock_is_paused.return_value = False
mock_os_release.return_value = 'queens'
with patch.object(utils, 'assess_status_func') as asf:
asf.return_value = 'assessor'
utils._pause_resume_helper(f, 'some-config')
asf.assert_called_once_with('some-config', ['s1'])
# ports=None whilst port checks are disabled.
f.assert_called_once_with('assessor', services=['s1'], ports=None)
@patch.object(utils, 'check_call')
@patch.object(utils, 'check_output')
def test_remove_libvirt_network(self, mock_check_output, mock_check_call):
mock_check_output.return_value = VIRSH_NET_LIST.encode()
utils.remove_libvirt_network('default')
cmd = ['virsh', 'net-destroy', 'default']
mock_check_call.assert_has_calls([call(cmd)])
@patch.object(utils, 'check_call')
@patch.object(utils, 'check_output')
def test_remove_libvirt_network_no_exist(self, mock_check_output,
mock_check_call):
mock_check_output.return_value = VIRSH_NET_LIST.encode()
utils.remove_libvirt_network('defaultX')
self.assertFalse(mock_check_call.called)
@patch.object(utils, 'check_call')
@patch.object(utils, 'check_output')
def test_remove_libvirt_network_no_virsh(self, mock_check_output,
mock_check_call):
mock_check_output.side_effect = OSError(2, 'No such file')
utils.remove_libvirt_network('default')
@patch.object(utils, 'check_call')
@patch.object(utils, 'check_output')
def test_remove_libvirt_network_no_virsh_unknown_error(self,
mock_check_output,
mock_check_call):
mock_check_output.side_effect = OSError(100, 'Break things')
with self.assertRaises(OSError):
utils.remove_libvirt_network('default')
def test_libvirt_daemon_yakkety(self):
self.lsb_release.return_value = {
'DISTRIB_CODENAME': 'yakkety'
}
self.assertEqual(utils.libvirt_daemon(), utils.LIBVIRTD_DAEMON)
def test_libvirt_daemon_preyakkety(self):
self.os_release.return_value = 'diablo'
self.lsb_release.return_value = {
'DISTRIB_CODENAME': 'xenial'
}
self.assertEqual(utils.libvirt_daemon(), utils.LIBVIRT_BIN_DAEMON)
@patch.object(utils, 'os')
def test_determine_block_device(self, mock_os):
self.test_config.set('ephemeral-device', '/dev/sdd')
mock_os.path.exists.return_value = True
self.assertEqual(utils.determine_block_device(), '/dev/sdd')
self.config.assert_called_with('ephemeral-device')
def test_determine_block_device_storage(self):
_test_devices = {
'a': '/dev/bcache0'
}
self.storage_list.side_effect = _test_devices.keys()
self.storage_get.side_effect = lambda _, key: _test_devices.get(key)
self.assertEqual(utils.determine_block_device(), '/dev/bcache0')
self.config.assert_called_with('ephemeral-device')
self.storage_get.assert_called_with('location', 'a')
self.storage_list.assert_called_with('ephemeral-device')
def test_determine_block_device_none(self):
self.storage_list.return_value = []
self.assertEqual(utils.determine_block_device(), None)
self.config.assert_called_with('ephemeral-device')
self.storage_list.assert_called_with('ephemeral-device')
@patch.object(utils, 'install_mount_override')
@patch.object(utils, 'filter_installed_packages')
@patch.object(utils, 'uuid')
@patch.object(utils, 'determine_block_device')
def test_configure_local_ephemeral_storage_encrypted(
self,
determine_block_device,
uuid,
filter_installed_packages,
install_mount_override):
filter_installed_packages.return_value = []
determine_block_device.return_value = '/dev/sdb'
uuid.uuid4.return_value = 'test'
mock_context = MagicMock()
mock_context.complete = True
mock_context.return_value = 'test_context'
self.test_config.set('encrypt', True)
self.vaultlocker.VaultKVContext.return_value = mock_context
self.is_block_device.return_value = True
self.is_device_mounted.return_value = False
utils.configure_local_ephemeral_storage()
self.mkfs_xfs.assert_called_with(
'/dev/mapper/crypt-test',
force=True
)
self.check_call.assert_has_calls([
call(['vaultlocker', 'encrypt',
'--uuid', 'test', '/dev/sdb']),
call(['chown', '-R', 'nova:nova',
'/var/lib/nova/instances']),
call(['chmod', '-R', '0755',
'/var/lib/nova/instances'])
])
self.mount.assert_called_with(
'/dev/mapper/crypt-test',
'/var/lib/nova/instances',
filesystem='xfs')
self.fstab_add.assert_called_with(
'/dev/mapper/crypt-test',
'/var/lib/nova/instances',
'xfs',
options='defaults,nofail,'
'x-systemd.requires=vaultlocker-decrypt@test.service,'
'comment=vaultlocker'
)
install_mount_override.assert_called_with(
'/var/lib/nova/instances'
)
self.assertTrue(self.test_kv.get('storage-configured'))
self.vaultlocker.write_vaultlocker_conf.assert_called_with(
'test_context',
priority=80
)
@patch.object(utils, 'install_mount_override')
@patch.object(utils, 'uuid')
@patch.object(utils, 'determine_block_device')
def test_configure_local_ephemeral_storage(self,
determine_block_device,
uuid,
install_mount_override):
determine_block_device.return_value = '/dev/sdb'
uuid.uuid4.return_value = 'test'
mock_context = MagicMock()
mock_context.complete = False
mock_context.return_value = {}
self.test_config.set('encrypt', False)
self.vaultlocker.VaultKVContext.return_value = mock_context
self.is_block_device.return_value = True
self.is_device_mounted.return_value = False
utils.configure_local_ephemeral_storage()
self.mkfs_xfs.assert_called_with(
'/dev/sdb',
force=True
)
self.check_call.assert_has_calls([
call(['chown', '-R', 'nova:nova',
'/var/lib/nova/instances']),
call(['chmod', '-R', '0755',
'/var/lib/nova/instances'])
])
self.mount.assert_called_with(
'/dev/sdb',
'/var/lib/nova/instances',
filesystem='xfs')
self.fstab_add.assert_called_with(
'/dev/sdb',
'/var/lib/nova/instances',
'xfs',
options=None
)
install_mount_override.assert_called_with(
'/var/lib/nova/instances'
)
self.assertTrue(self.test_kv.get('storage-configured'))
self.vaultlocker.write_vaultlocker_conf.assert_not_called()
@patch.object(utils, 'install_mount_override')
@patch.object(utils, 'uuid')
@patch.object(utils, 'determine_block_device')
def test_configure_local_ephemeral_storage_ip_set(self,
determine_block_device,
uuid,
install_mount_override):
determine_block_device.return_value = '/dev/sdb'
uuid.uuid4.return_value = 'test'
mock_context = MagicMock()
mock_context.complete = False
mock_context.return_value = {}
self.test_config.set('encrypt', False)
self.test_config.set('instances-path', '/srv/instances')
self.vaultlocker.VaultKVContext.return_value = mock_context
self.is_block_device.return_value = True
self.is_device_mounted.return_value = False
utils.configure_local_ephemeral_storage()
self.mkfs_xfs.assert_called_with(
'/dev/sdb',
force=True
)
self.check_call.assert_has_calls([
call(['chown', '-R', 'nova:nova',
'/srv/instances']),
call(['chmod', '-R', '0755',
'/srv/instances'])
])
self.mount.assert_called_with(
'/dev/sdb',
'/srv/instances',
filesystem='xfs')
self.fstab_add.assert_called_with(
'/dev/sdb',
'/srv/instances',
'xfs',
options=None
)
install_mount_override.assert_called_with(
'/srv/instances'
)
self.assertTrue(self.test_kv.get('storage-configured'))
self.vaultlocker.write_vaultlocker_conf.assert_not_called()
@patch.object(utils, 'install_mount_override')
@patch.object(utils, 'filter_installed_packages')
def test_configure_local_ephemeral_storage_done(self,
filter_installed_packages,
install_mount_override):
filter_installed_packages.return_value = []
self.test_kv.set('storage-configured', True)
mock_context = MagicMock()
mock_context.complete = True
mock_context.return_value = 'test_context'
self.test_config.set('encrypt', True)
self.vaultlocker.VaultKVContext.return_value = mock_context
utils.configure_local_ephemeral_storage()
# NOTE: vaultlocker conf should always be re-written to
# pickup any changes to secret_id over time.
self.vaultlocker.write_vaultlocker_conf.assert_called_with(
'test_context',
priority=80
)
self.is_block_device.assert_not_called()
# NOTE: called to deal with charm upgrades
install_mount_override.assert_called_with(
'/var/lib/nova/instances'
)
@patch.object(utils, "libvirt_daemon")
@patch.object(utils, "hook_name")
@patch.object(utils, "get_subordinate_services")
@patch.object(utils, 'nova_metadata_requirement')
def test_services_to_pause_or_resume(
self, _en_meta, _subordinate_services, _hook_name,
_libvirt_daemon):
_en_meta.return_value = (False, None)
_subordinate_services.return_value = set(["ceilometer-agent-compute"])
_libvirt_daemon.return_value = "libvirtd"
self.os_release.return_value = 'victoria'
self.relation_ids.return_value = []
# WARNING(lourot): In the following test expectations, the order of
# the services is important. Principal services have to come before
# the subordinate services. See nova_compute_utils.services() for more
# details.
expected_last_service = "ceilometer-agent-compute"
_hook_name.return_value = "config-changed"
expected_service_set = set(["qemu-kvm", "nova-compute",
"ceilometer-agent-compute"])
actual_service_list = utils.services_to_pause_or_resume()
self.assertEqual(expected_service_set, set(actual_service_list))
self.assertEqual(expected_last_service, actual_service_list[-1])
_hook_name.return_value = "post-series-upgrade"
expected_service_set = set(["qemu-kvm", "nova-compute", "libvirtd",
"ceilometer-agent-compute"])
actual_service_list = utils.services_to_pause_or_resume()
self.assertEqual(expected_service_set, set(actual_service_list))
self.assertEqual(expected_last_service, actual_service_list[-1])
@patch.object(utils, 'render')
def test_install_mount_override(self, render):
utils.install_mount_override('/srv/test')
render.assert_called_once_with(
utils.MOUNT_DEPENDENCY_OVERRIDE,
os.path.join(utils.NOVA_COMPUTE_OVERRIDE_DIR,
utils.MOUNT_DEPENDENCY_OVERRIDE),
{'mount_point': 'srv-test'},
perms=0o644,
)