From ed3ea84126991f3c9a513d1fb4cdb2b6fa939ce8 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Wed, 3 Apr 2019 15:43:01 +0000 Subject: [PATCH] Install libmaas for stonith plugin The libmaas stonith plugin uses libmaas which is supplied via python3-libmaas. python3-libmaas is available from bionic onwards so install it where possible. Also, drive by fix to precreate /etc/pacemaker dir if needed to fix trusty installs. Closes-Bug: #1823300 Closes-Bug: #1823302 Change-Id: Ib14146f7f667f9c52e11d222f950efcb7cb47a7f --- hooks/hooks.py | 10 ++++--- hooks/utils.py | 5 +++- unit_tests/test_hacluster_hooks.py | 43 ++++++++++++++++++++++++++++++ unit_tests/test_hacluster_utils.py | 18 ++++++++++--- 4 files changed, 69 insertions(+), 7 deletions(-) diff --git a/hooks/hooks.py b/hooks/hooks.py index ba65460..c22759b 100755 --- a/hooks/hooks.py +++ b/hooks/hooks.py @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import copy import glob import os import shutil @@ -131,15 +132,18 @@ DEPRECATED_TRANSPORT_VALUES = {"multicast": "udp", "unicast": "udpu"} @hooks.hook('install.real') def install(): + pkgs = copy.deepcopy(PACKAGES) ubuntu_release = lsb_release()['DISTRIB_CODENAME'].lower() # use libnagios on anything older than Xenial if CompareHostReleases(ubuntu_release) < 'xenial': - PACKAGES.remove('libmonitoring-plugin-perl') - PACKAGES.append('libnagios-plugin-perl') + pkgs.remove('libmonitoring-plugin-perl') + pkgs.append('libnagios-plugin-perl') + elif CompareHostReleases(ubuntu_release) >= 'bionic': + pkgs.append('python3-libmaas') # NOTE(dosaboy): we currently disallow upgrades due to bug #1382842. This # should be removed once the pacemaker package is fixed. status_set('maintenance', 'Installing apt packages') - apt_install(filter_installed_packages(PACKAGES), fatal=True) + apt_install(filter_installed_packages(pkgs), fatal=True) setup_ocf_files() diff --git a/hooks/utils.py b/hooks/utils.py index e4857f1..13e1bdf 100644 --- a/hooks/utils.py +++ b/hooks/utils.py @@ -94,7 +94,8 @@ COROSYNC_CONF_FILES = [ ] SUPPORTED_TRANSPORTS = ['udp', 'udpu', 'multicast', 'unicast'] -PCMKR_AUTHKEY = '/etc/pacemaker/authkey' +PCMKR_CONFIG_DIR = '/etc/pacemaker' +PCMKR_AUTHKEY = PCMKR_CONFIG_DIR + '/authkey' PCMKR_MAX_RETRIES = 3 PCMKR_SLEEP_SECS = 5 @@ -341,6 +342,8 @@ def get_pcmkr_key(): def emit_base_conf(): if not os.path.isdir(COROSYNC_HACLUSTER_ACL_DIR): os.mkdir(COROSYNC_HACLUSTER_ACL_DIR) + if not os.path.isdir(PCMKR_CONFIG_DIR): + os.mkdir(PCMKR_CONFIG_DIR) corosync_default_context = {'corosync_enabled': 'yes'} write_file(path=COROSYNC_DEFAULT, content=render_template('corosync', diff --git a/unit_tests/test_hacluster_hooks.py b/unit_tests/test_hacluster_hooks.py index 712e394..f1a8ee0 100644 --- a/unit_tests/test_hacluster_hooks.py +++ b/unit_tests/test_hacluster_hooks.py @@ -296,6 +296,49 @@ class TestHooks(test_utils.CharmTestCase): super(TestHooks, self).setUp(hooks, self.TO_PATCH) self.config.side_effect = self.test_config.get + @mock.patch.object(hooks, 'filter_installed_packages') + @mock.patch.object(hooks, 'setup_ocf_files') + @mock.patch.object(hooks, 'apt_install') + @mock.patch.object(hooks, 'status_set') + @mock.patch.object(hooks, 'lsb_release') + def test_install_xenial(self, lsb_release, status_set, apt_install, + setup_ocf_files, filter_installed_packages): + lsb_release.return_value = { + 'DISTRIB_CODENAME': 'xenial'} + filter_installed_packages.side_effect = lambda x: x + expected_pkgs = [ + 'crmsh', 'corosync', 'pacemaker', 'python-netaddr', 'ipmitool', + 'libmonitoring-plugin-perl', 'python3-requests-oauthlib'] + hooks.install() + status_set.assert_called_once_with( + 'maintenance', + 'Installing apt packages') + filter_installed_packages.assert_called_once_with(expected_pkgs) + apt_install.assert_called_once_with(expected_pkgs, fatal=True) + setup_ocf_files.assert_called_once_with() + + @mock.patch.object(hooks, 'filter_installed_packages') + @mock.patch.object(hooks, 'setup_ocf_files') + @mock.patch.object(hooks, 'apt_install') + @mock.patch.object(hooks, 'status_set') + @mock.patch.object(hooks, 'lsb_release') + def test_install_bionic(self, lsb_release, status_set, apt_install, + setup_ocf_files, filter_installed_packages): + lsb_release.return_value = { + 'DISTRIB_CODENAME': 'bionic'} + filter_installed_packages.side_effect = lambda x: x + expected_pkgs = [ + 'crmsh', 'corosync', 'pacemaker', 'python-netaddr', 'ipmitool', + 'libmonitoring-plugin-perl', 'python3-requests-oauthlib', + 'python3-libmaas'] + hooks.install() + status_set.assert_called_once_with( + 'maintenance', + 'Installing apt packages') + filter_installed_packages.assert_called_once_with(expected_pkgs) + apt_install.assert_called_once_with(expected_pkgs, fatal=True) + setup_ocf_files.assert_called_once_with() + @mock.patch.object(hooks, 'relation_ids') @mock.patch.object(hooks, 'hanode_relation_joined') @mock.patch.object(hooks, 'maintenance_mode') diff --git a/unit_tests/test_hacluster_utils.py b/unit_tests/test_hacluster_utils.py index 2895daf..a3779fd 100644 --- a/unit_tests/test_hacluster_utils.py +++ b/unit_tests/test_hacluster_utils.py @@ -487,10 +487,14 @@ class UtilsTestCase(unittest.TestCase): 'hacluster.acl', {}) ] + mkdir_calls = [ + mock.call('/etc/corosync/uidgid.d'), + mock.call('/etc/pacemaker'), + ] self.assertTrue(utils.emit_base_conf()) write_file.assert_has_calls(expect_write_calls) render_template.assert_has_calls(expect_render_calls) - mkdir.assert_called_once_with('/etc/corosync/uidgid.d') + mkdir.assert_has_calls(mkdir_calls) @mock.patch.object(utils, 'render_template') @mock.patch.object(utils.os.path, 'isdir') @@ -535,10 +539,14 @@ class UtilsTestCase(unittest.TestCase): 'hacluster.acl', {}) ] + mkdir_calls = [ + mock.call('/etc/corosync/uidgid.d'), + mock.call('/etc/pacemaker'), + ] self.assertTrue(utils.emit_base_conf()) write_file.assert_has_calls(expect_write_calls) render_template.assert_has_calls(expect_render_calls) - mkdir.assert_called_once_with('/etc/corosync/uidgid.d') + mkdir.assert_has_calls(mkdir_calls) @mock.patch.object(utils, 'render_template') @mock.patch.object(utils.os.path, 'isdir') @@ -572,10 +580,14 @@ class UtilsTestCase(unittest.TestCase): 'hacluster.acl', {}) ] + mkdir_calls = [ + mock.call('/etc/corosync/uidgid.d'), + mock.call('/etc/pacemaker'), + ] self.assertFalse(utils.emit_base_conf()) write_file.assert_has_calls(expect_write_calls) render_template.assert_has_calls(expect_render_calls) - mkdir.assert_called_once_with('/etc/corosync/uidgid.d') + mkdir.assert_has_calls(mkdir_calls) @mock.patch.object(utils, 'relation_get') @mock.patch.object(utils, 'related_units')