Merge "Add apply_osd_settings"
This commit is contained in:
commit
cc06e5010f
@ -3070,3 +3070,57 @@ def osd_noout(enable):
|
|||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
log(e)
|
log(e)
|
||||||
raise
|
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
|
||||||
|
@ -1102,6 +1102,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):
|
class CephVolumeSizeCalculatorTestCase(unittest.TestCase):
|
||||||
|
|
||||||
@patch.object(utils, 'get_conf')
|
@patch.object(utils, 'get_conf')
|
||||||
|
Loading…
Reference in New Issue
Block a user