Add apply_osd_settings
Add apply_osd_settings for applying osd settings to running osd daemons. Change-Id: If8fa9020d9cbe2c8fcf981abd737653173926341
This commit is contained in:
parent
341b5c5bf4
commit
4fc32cc401
@ -3067,3 +3067,57 @@ def osd_noout(enable):
|
||||
except subprocess.CalledProcessError as e:
|
||||
log(e)
|
||||
raise
|
||||
|
||||
|
||||
class OSDConfigSetError(Exception):
|
||||
"""Error occured applying OSD settings."""
|
||||
pass
|
||||
|
||||
|
||||
def apply_osd_settings(settings):
|
||||
"""Applies the provided osd settings
|
||||
|
||||
Apply the provided settings to all local OSD unless settings are already
|
||||
present. Settings stop being applied on encountering an error.
|
||||
|
||||
:param settings: dict. Dictionary of settings to apply.
|
||||
:returns: bool. True if commands ran succesfully.
|
||||
:raises: OSDConfigSetError
|
||||
"""
|
||||
current_settings = {}
|
||||
base_cmd = 'ceph daemon osd.{osd_id} config --format=json'
|
||||
get_cmd = base_cmd + ' get {key}'
|
||||
set_cmd = base_cmd + ' set {key} {value}'
|
||||
|
||||
def _get_cli_key(key):
|
||||
return(key.replace(' ', '_'))
|
||||
# Retrieve the current values to check keys are correct and to make this a
|
||||
# noop if setting are already applied.
|
||||
for osd_id in get_local_osd_ids():
|
||||
for key, value in sorted(settings.items()):
|
||||
cli_key = _get_cli_key(key)
|
||||
cmd = get_cmd.format(osd_id=osd_id, key=cli_key)
|
||||
out = json.loads(
|
||||
subprocess.check_output(cmd.split()).decode('UTF-8'))
|
||||
if 'error' in out:
|
||||
log("Error retrieving osd setting: {}".format(out['error']),
|
||||
level=ERROR)
|
||||
return False
|
||||
current_settings[key] = out[cli_key]
|
||||
settings_diff = {
|
||||
k: v
|
||||
for k, v in settings.items()
|
||||
if str(v) != str(current_settings[k])}
|
||||
for key, value in sorted(settings_diff.items()):
|
||||
log("Setting {} to {}".format(key, value), level=DEBUG)
|
||||
cmd = set_cmd.format(
|
||||
osd_id=osd_id,
|
||||
key=_get_cli_key(key),
|
||||
value=value)
|
||||
out = json.loads(
|
||||
subprocess.check_output(cmd.split()).decode('UTF-8'))
|
||||
if 'error' in out:
|
||||
log("Error applying osd setting: {}".format(out['error']),
|
||||
level=ERROR)
|
||||
raise OSDConfigSetError
|
||||
return True
|
||||
|
@ -1101,6 +1101,109 @@ class CephTestCase(unittest.TestCase):
|
||||
})
|
||||
|
||||
|
||||
class CephApplyOSDSettingsTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(CephApplyOSDSettingsTestCase, self).setUp()
|
||||
self.base_cmd = 'ceph daemon osd.{osd_id} config --format=json'
|
||||
self.get_cmd = self.base_cmd + ' get {key}'
|
||||
self.set_cmd = self.base_cmd + ' set {key} {value}'
|
||||
self.grace = 'osd_heartbeat_grace'
|
||||
self.interval = 'osd_heartbeat_interval'
|
||||
|
||||
@patch.object(utils, 'get_local_osd_ids')
|
||||
@patch.object(utils.subprocess, 'check_output')
|
||||
def test_apply_osd_settings(self, _check_output, _get_local_osd_ids):
|
||||
_get_local_osd_ids.return_value = ['0']
|
||||
output = {
|
||||
self.get_cmd.format(osd_id=0, key=self.grace):
|
||||
b'{"osd_heartbeat_grace":"19"}',
|
||||
self.set_cmd.format(osd_id=0, key=self.grace, value='21'):
|
||||
b"""{"success":"osd_heartbeat_grace = '21'"}"""}
|
||||
_check_output.side_effect = lambda x: output[' '.join(x)]
|
||||
self.assertTrue(
|
||||
utils.apply_osd_settings({'osd heartbeat grace': '21'}))
|
||||
check_output_calls = [
|
||||
call(['ceph', 'daemon', 'osd.0', 'config', '--format=json', 'get',
|
||||
'osd_heartbeat_grace']),
|
||||
call(['ceph', 'daemon', 'osd.0', 'config', '--format=json', 'set',
|
||||
'osd_heartbeat_grace', '21'])]
|
||||
_check_output.assert_has_calls(check_output_calls)
|
||||
self.assertTrue(_check_output.call_count == len(check_output_calls))
|
||||
|
||||
@patch.object(utils, 'get_local_osd_ids')
|
||||
@patch.object(utils.subprocess, 'check_output')
|
||||
def test_apply_osd_settings_noop_on_one_osd(self, _check_output,
|
||||
_get_local_osd_ids):
|
||||
_get_local_osd_ids.return_value = ['0', '1']
|
||||
output = {
|
||||
self.get_cmd.format(osd_id=0, key=self.grace):
|
||||
b'{"osd_heartbeat_grace":"21"}',
|
||||
self.get_cmd.format(osd_id=1, key=self.grace):
|
||||
b'{"osd_heartbeat_grace":"20"}',
|
||||
self.set_cmd.format(osd_id=1, key=self.grace, value='21'):
|
||||
b"""{"success":"osd_heartbeat_interval = '2'"}"""}
|
||||
_check_output.side_effect = lambda x: output[' '.join(x)]
|
||||
self.assertTrue(
|
||||
utils.apply_osd_settings({'osd heartbeat grace': '21'}))
|
||||
check_output_calls = [
|
||||
call(['ceph', 'daemon', 'osd.0', 'config', '--format=json', 'get',
|
||||
'osd_heartbeat_grace']),
|
||||
call(['ceph', 'daemon', 'osd.1', 'config', '--format=json', 'get',
|
||||
'osd_heartbeat_grace']),
|
||||
call(['ceph', 'daemon', 'osd.1', 'config', '--format=json', 'set',
|
||||
'osd_heartbeat_grace', '21'])]
|
||||
_check_output.assert_has_calls(check_output_calls)
|
||||
self.assertTrue(_check_output.call_count == len(check_output_calls))
|
||||
|
||||
@patch.object(utils, 'get_local_osd_ids')
|
||||
@patch.object(utils.subprocess, 'check_output')
|
||||
def _test_apply_osd_settings_error(self, _check_output,
|
||||
_get_local_osd_ids):
|
||||
_get_local_osd_ids.return_value = ['0']
|
||||
output = {
|
||||
self.get_cmd.format(osd_id=0, key=self.grace):
|
||||
b"""{"error":"error setting 'osd_heartbeat_grace'"}"""}
|
||||
_check_output.side_effect = lambda x: output[' '.join(x)]
|
||||
self.assertFalse(
|
||||
utils.apply_osd_settings({'osd heartbeat grace': '21'}))
|
||||
check_output_calls = [
|
||||
call(['ceph', 'daemon', 'osd.0', 'config', '--format=json', 'get',
|
||||
'osd_heartbeat_grace'])]
|
||||
_check_output.assert_has_calls(check_output_calls)
|
||||
self.assertTrue(_check_output.call_count == len(check_output_calls))
|
||||
|
||||
@patch.object(utils, 'get_local_osd_ids')
|
||||
@patch.object(utils.subprocess, 'check_output')
|
||||
def test_apply_osd_settings_error(self, _check_output,
|
||||
_get_local_osd_ids):
|
||||
_get_local_osd_ids.return_value = ['0', '1']
|
||||
output = {
|
||||
self.get_cmd.format(osd_id=0, key=self.grace):
|
||||
b'{"osd_heartbeat_grace":"19"}',
|
||||
self.get_cmd.format(osd_id=0, key=self.interval):
|
||||
b'{"osd_heartbeat_interval":"3"}',
|
||||
self.set_cmd.format(osd_id=0, key=self.interval, value='2'):
|
||||
b"""{"success":"osd_heartbeat_interval = '2'"}""",
|
||||
self.set_cmd.format(osd_id=0, key=self.grace, value='21'):
|
||||
b"""{"error":"error setting 'osd_heartbeat_grace'"}"""}
|
||||
_check_output.side_effect = lambda x: output[' '.join(x)]
|
||||
check_output_calls = [
|
||||
call(['ceph', 'daemon', 'osd.0', 'config', '--format=json', 'get',
|
||||
'osd_heartbeat_grace']),
|
||||
call(['ceph', 'daemon', 'osd.0', 'config', '--format=json', 'get',
|
||||
'osd_heartbeat_interval']),
|
||||
call(['ceph', 'daemon', 'osd.0', 'config', '--format=json', 'set',
|
||||
'osd_heartbeat_grace', '21'])]
|
||||
with self.assertRaises(utils.OSDConfigSetError):
|
||||
utils.apply_osd_settings({
|
||||
'osd heartbeat grace': '21',
|
||||
'osd heartbeat interval': '2'})
|
||||
_check_output.assert_has_calls(check_output_calls)
|
||||
self.assertTrue(
|
||||
_check_output.call_count == len(check_output_calls))
|
||||
|
||||
|
||||
class CephVolumeSizeCalculatorTestCase(unittest.TestCase):
|
||||
|
||||
@patch.object(utils, 'get_conf')
|
||||
|
Loading…
Reference in New Issue
Block a user