From 43e7a3c691b91a5171f6ace4573a255ab6c67cd8 Mon Sep 17 00:00:00 2001 From: James Page Date: Wed, 5 Jul 2017 10:49:37 +0100 Subject: [PATCH] Call ceph-create-keys for >= Luminos Ceph Luminos removes the automatic call to ceph-create-keys on ceph-mon startup; deployment tools are required to call this after the monitors have been started to create the admin keyring across the cluster. ceph-create-keys still blocks until the cluster is in quorum, at which points keys are created and written out to the normal location in /etc/ceph. Change-Id: Ifc9b8aaf3dbce71cb62567ba03455d2196eaf29f --- .gitignore | 4 +++ ceph/__init__.py | 9 +++++ tox.ini | 5 ++- unit_tests/test_ceph.py | 77 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 17f8e6b..463840f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,7 @@ .tox *.sw[nop] *.pyc +*.egg-info +dist +.project +.pydevproject diff --git a/ceph/__init__.py b/ceph/__init__.py index ae5618f..51b717d 100644 --- a/ceph/__init__.py +++ b/ceph/__init__.py @@ -1299,6 +1299,15 @@ def bootstrap_monitor_cluster(secret): service_restart('ceph-mon') else: service_restart('ceph-mon-all') + + if cmp_pkgrevno('ceph', '12.0.0') >= 0: + # NOTE(jamespage): Later ceph releases require explicit + # call to ceph-create-keys to setup the + # admin keys for the cluster; this command + # will wait for quorum in the cluster before + # returning. + cmd = ['ceph-create-keys', '--id', hostname] + subprocess.check_call(cmd) except: raise finally: diff --git a/tox.ini b/tox.ini index 88fa4d9..b9a2be6 100644 --- a/tox.ini +++ b/tox.ini @@ -9,9 +9,12 @@ install_command = pip install --allow-unverified python-apt {opts} {packages} commands = find . -type f -name "*.py[c|o]" -delete find . -type d -name "__pycache__" -delete + rm -f .testrepository/times.dbm ostestr {posargs} sitepackages = False -whitelist_externals = find +whitelist_externals = + find + rm [testenv:py27] basepython = python2.7 diff --git a/unit_tests/test_ceph.py b/unit_tests/test_ceph.py index 2f9979b..faa3728 100644 --- a/unit_tests/test_ceph.py +++ b/unit_tests/test_ceph.py @@ -331,6 +331,83 @@ class CephTestCase(unittest.TestCase): mock_is_container.return_value = True self.assertFalse('ntp' in ceph.determine_packages()) + @mock.patch.object(ceph, 'chownr') + @mock.patch.object(ceph, 'cmp_pkgrevno') + @mock.patch.object(ceph, 'ceph_user') + @mock.patch.object(ceph, 'os') + @mock.patch.object(ceph, 'systemd') + @mock.patch.object(ceph, 'log') + @mock.patch.object(ceph, 'mkdir') + @mock.patch.object(ceph, 'subprocess') + @mock.patch.object(ceph, 'service_restart') + def _test_bootstrap_monitor_cluster(self, + mock_service_restart, + mock_subprocess, + mock_mkdir, + mock_log, + mock_systemd, + mock_os, + mock_ceph_user, + mock_cmp_pkgrevno, + mock_chownr, + luminos=False): + test_hostname = ceph.socket.gethostname() + test_secret = 'mysecret' + test_keyring = '/var/lib/ceph/tmp/{}.mon.keyring'.format(test_hostname) + test_path = '/var/lib/ceph/mon/ceph-{}'.format(test_hostname) + test_done = '{}/done'.format(test_path) + test_init_marker = '{}/systemd'.format(test_path) + + mock_os.path.exists.return_value = False + mock_systemd.return_value = True + mock_cmp_pkgrevno.return_value = 1 if luminos else -1 + mock_ceph_user.return_value = 'ceph' + + test_calls = [ + mock.call( + ['ceph-authtool', test_keyring, + '--create-keyring', '--name=mon.', + '--add-key={}'.format(test_secret), + '--cap', 'mon', 'allow *'] + ), + mock.call( + ['ceph-mon', '--mkfs', + '-i', test_hostname, + '--keyring', test_keyring] + ), + mock.call(['systemctl', 'enable', 'ceph-mon']), + ] + if luminos: + test_calls.append( + mock.call(['ceph-create-keys', '--id', test_hostname]) + ) + + mock_open = mock.mock_open() + with mock.patch('ceph.open', mock_open, create=True): + ceph.bootstrap_monitor_cluster(test_secret) + + self.assertEqual( + mock_subprocess.check_call.mock_calls, + test_calls + ) + mock_service_restart.assert_called_with('ceph-mon') + mock_mkdir.assert_has_calls([ + mock.call('/var/run/ceph', owner='ceph', + group='ceph', perms=0o755), + mock.call(test_path, owner='ceph', group='ceph'), + ]) + mock_open.assert_has_calls([ + mock.call(test_done, 'w'), + mock.call(test_init_marker, 'w'), + ], any_order=True) + mock_os.unlink.assert_called_with(test_keyring) + + def test_bootstrap_monitor_cluster(self): + self._test_bootstrap_monitor_cluster(luminos=False) + + def test_bootstrap_monitor_cluster_luminous(self): + self._test_bootstrap_monitor_cluster(luminos=True) + class CephVersionTestCase(unittest.TestCase): @mock.patch.object(ceph, 'get_os_codename_install_source')