Pass on osd settings from clients to osd units
If a client application has requested particular osd settings then validate them and pass them on to the osd units. Change-Id: Iad7132b3e6b34038ecd9a61fbb9589b22117396d
This commit is contained in:
parent
544a0e0a38
commit
6afe8288a8
|
@ -80,7 +80,10 @@ from charmhelpers.core.sysctl import create as create_sysctl
|
|||
from charmhelpers.core.templating import render
|
||||
from charmhelpers.contrib.storage.linux.ceph import (
|
||||
CephConfContext,
|
||||
OSD_SETTING_EXCEPTIONS,
|
||||
enable_pg_autoscale,
|
||||
get_osd_settings,
|
||||
send_osd_settings,
|
||||
)
|
||||
from utils import (
|
||||
add_rbd_mirror_features,
|
||||
|
@ -682,6 +685,7 @@ def osd_relation(relid=None, unit=None):
|
|||
notify_radosgws()
|
||||
notify_client()
|
||||
notify_rbd_mirrors()
|
||||
send_osd_settings()
|
||||
else:
|
||||
log('mon cluster not in quorum - deferring fsid provision')
|
||||
|
||||
|
@ -853,6 +857,7 @@ def admin_relation_joined(relid=None):
|
|||
@hooks.hook('client-relation-changed')
|
||||
@hooks.hook('client-relation-joined')
|
||||
def client_relation(relid=None, unit=None):
|
||||
send_osd_settings()
|
||||
if ready_for_service():
|
||||
log('mon cluster in quorum and osds bootstrapped '
|
||||
'- providing client with keys, processing broker requests')
|
||||
|
@ -1020,6 +1025,12 @@ def assess_status():
|
|||
'``default-rbd-features``')
|
||||
return
|
||||
|
||||
try:
|
||||
get_osd_settings('client')
|
||||
except OSD_SETTING_EXCEPTIONS as e:
|
||||
status_set('blocked', str(e))
|
||||
return
|
||||
|
||||
# active - bootstrapped + quorum status check
|
||||
if ceph.is_bootstrapped() and ceph.is_quorum():
|
||||
expected_osd_count = config('expected-osd-count') or 3
|
||||
|
|
|
@ -36,7 +36,7 @@ from charmhelpers.contrib.network import ip
|
|||
from charmhelpers.core import unitdata
|
||||
|
||||
from charmhelpers.core.hookenv import (
|
||||
WL_STATES,
|
||||
WORKLOAD_STATES,
|
||||
action_fail,
|
||||
action_set,
|
||||
config,
|
||||
|
@ -1827,7 +1827,7 @@ def os_application_status_set(check_function):
|
|||
:type check_function: function
|
||||
"""
|
||||
state, message = check_function()
|
||||
status_set(state, message, application_status=True)
|
||||
status_set(state, message, application=True)
|
||||
|
||||
|
||||
def enable_memcache(source=None, release=None, package=None):
|
||||
|
@ -2295,7 +2295,7 @@ def check_api_unit_ready(check_db_ready=True):
|
|||
:rtype: (bool, str)
|
||||
"""
|
||||
unit_state, msg = get_api_unit_status(check_db_ready=check_db_ready)
|
||||
return unit_state == WL_STATES.ACTIVE, msg
|
||||
return unit_state == WORKLOAD_STATES.ACTIVE, msg
|
||||
|
||||
|
||||
def get_api_unit_status(check_db_ready=True):
|
||||
|
@ -2306,22 +2306,22 @@ def get_api_unit_status(check_db_ready=True):
|
|||
:returns: Workload state and message
|
||||
:rtype: (bool, str)
|
||||
"""
|
||||
unit_state = WL_STATES.ACTIVE
|
||||
unit_state = WORKLOAD_STATES.ACTIVE
|
||||
msg = 'Unit is ready'
|
||||
if is_db_maintenance_mode():
|
||||
unit_state = WL_STATES.MAINTENANCE
|
||||
unit_state = WORKLOAD_STATES.MAINTENANCE
|
||||
msg = 'Database in maintenance mode.'
|
||||
elif is_unit_paused_set():
|
||||
unit_state = WL_STATES.BLOCKED
|
||||
unit_state = WORKLOAD_STATES.BLOCKED
|
||||
msg = 'Unit paused.'
|
||||
elif check_db_ready and not is_db_ready():
|
||||
unit_state = WL_STATES.WAITING
|
||||
unit_state = WORKLOAD_STATES.WAITING
|
||||
msg = 'Allowed_units list provided but this unit not present'
|
||||
elif not is_db_initialised():
|
||||
unit_state = WL_STATES.WAITING
|
||||
unit_state = WORKLOAD_STATES.WAITING
|
||||
msg = 'Database not initialised'
|
||||
elif not is_expected_scale():
|
||||
unit_state = WL_STATES.WAITING
|
||||
unit_state = WORKLOAD_STATES.WAITING
|
||||
msg = 'Charm and its dependencies not yet at expected scale'
|
||||
juju_log(msg, 'DEBUG')
|
||||
return unit_state, msg
|
||||
|
@ -2334,7 +2334,7 @@ def check_api_application_ready():
|
|||
:rtype: (bool, str)
|
||||
"""
|
||||
app_state, msg = get_api_application_status()
|
||||
return app_state == WL_STATES.ACTIVE, msg
|
||||
return app_state == WORKLOAD_STATES.ACTIVE, msg
|
||||
|
||||
|
||||
def get_api_application_status():
|
||||
|
@ -2344,9 +2344,9 @@ def get_api_application_status():
|
|||
:rtype: (bool, str)
|
||||
"""
|
||||
app_state, msg = get_api_unit_status()
|
||||
if app_state == WL_STATES.ACTIVE:
|
||||
if app_state == WORKLOAD_STATES.ACTIVE:
|
||||
if are_peers_ready():
|
||||
return WL_STATES.ACTIVE, 'Application Ready'
|
||||
return WORKLOAD_STATES.ACTIVE, 'Application Ready'
|
||||
else:
|
||||
return WL_STATES.WAITING, 'Some units are not ready'
|
||||
return WORKLOAD_STATES.WAITING, 'Some units are not ready'
|
||||
return app_state, msg
|
||||
|
|
|
@ -59,7 +59,7 @@ RANGE_WARNING = ('Passing NO_PROXY string that includes a cidr. '
|
|||
'running in your shell.')
|
||||
|
||||
|
||||
class WL_STATES(Enum):
|
||||
class WORKLOAD_STATES(Enum):
|
||||
ACTIVE = 'active'
|
||||
BLOCKED = 'blocked'
|
||||
MAINTENANCE = 'maintenance'
|
||||
|
@ -1097,31 +1097,33 @@ def function_tag():
|
|||
return os.environ.get('JUJU_FUNCTION_TAG') or action_tag()
|
||||
|
||||
|
||||
def status_set(workload_state, message, application_status=False):
|
||||
def status_set(workload_state, message, application=False):
|
||||
"""Set the workload state with a message
|
||||
|
||||
Use status-set to set the workload state with a message which is visible
|
||||
to the user via juju status. If the status-set command is not found then
|
||||
assume this is juju < 1.23 and juju-log the message instead.
|
||||
|
||||
workload_state -- valid juju workload state. str or WL_STATES
|
||||
message -- status update message
|
||||
application_status -- Whether this is an application state set
|
||||
workload_state -- valid juju workload state. str or WORKLOAD_STATES
|
||||
message -- status update message
|
||||
application -- Whether this is an application state set
|
||||
"""
|
||||
# Extract the value if workload_state is an Enum
|
||||
try:
|
||||
workload_state = workload_state.value
|
||||
except AttributeError:
|
||||
pass
|
||||
workload_state = workload_state.lower()
|
||||
if workload_state not in [s.lower() for s in WL_STATES.__members__.keys()]:
|
||||
raise ValueError(
|
||||
'{!r} is not a valid workload state'.format(workload_state)
|
||||
)
|
||||
bad_state_msg = '{!r} is not a valid workload state'
|
||||
|
||||
if isinstance(workload_state, str):
|
||||
try:
|
||||
# Convert string to enum.
|
||||
workload_state = WORKLOAD_STATES[workload_state.upper()]
|
||||
except KeyError:
|
||||
raise ValueError(bad_state_msg.format(workload_state))
|
||||
|
||||
if workload_state not in WORKLOAD_STATES:
|
||||
raise ValueError(bad_state_msg.format(workload_state))
|
||||
|
||||
cmd = ['status-set']
|
||||
if application_status:
|
||||
if application:
|
||||
cmd.append('--application')
|
||||
cmd.extend([workload_state, message])
|
||||
cmd.extend([workload_state.value, message])
|
||||
try:
|
||||
ret = subprocess.call(cmd)
|
||||
if ret == 0:
|
||||
|
@ -1129,7 +1131,7 @@ def status_set(workload_state, message, application_status=False):
|
|||
except OSError as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
log_message = 'status-set failed: {} {}'.format(workload_state,
|
||||
log_message = 'status-set failed: {} {}'.format(workload_state.value,
|
||||
message)
|
||||
log(log_message, level='INFO')
|
||||
|
||||
|
|
|
@ -407,6 +407,7 @@ class RelatedUnitsTestCase(unittest.TestCase):
|
|||
call('osd:23')
|
||||
])
|
||||
|
||||
@patch.object(ceph_hooks, 'send_osd_settings')
|
||||
@patch.object(ceph_hooks, 'get_rbd_features')
|
||||
@patch.object(ceph_hooks, 'relation_set')
|
||||
@patch.object(ceph_hooks, 'handle_broker_request')
|
||||
|
@ -423,7 +424,8 @@ class RelatedUnitsTestCase(unittest.TestCase):
|
|||
_config,
|
||||
_handle_broker_request,
|
||||
_relation_set,
|
||||
_get_rbd_features):
|
||||
_get_rbd_features,
|
||||
_send_osd_settings):
|
||||
_remote_service_name.return_value = 'glance'
|
||||
config = copy.deepcopy(CHARM_CONFIG)
|
||||
_config.side_effect = lambda key: config[key]
|
||||
|
@ -431,6 +433,7 @@ class RelatedUnitsTestCase(unittest.TestCase):
|
|||
_get_rbd_features.return_value = None
|
||||
ceph_hooks.client_relation(relid='rel1', unit='glance/0')
|
||||
_ready_for_service.assert_called_once_with()
|
||||
_send_osd_settings.assert_called_once_with()
|
||||
_get_public_addr.assert_called_once_with()
|
||||
_get_named_key.assert_called_once_with('glance')
|
||||
_handle_broker_request.assert_called_once_with(
|
||||
|
@ -454,6 +457,7 @@ class RelatedUnitsTestCase(unittest.TestCase):
|
|||
'rbd-features': 42,
|
||||
})
|
||||
|
||||
@patch.object(ceph_hooks, 'send_osd_settings')
|
||||
@patch.object(ceph_hooks, 'get_rbd_features')
|
||||
@patch.object(ceph_hooks, 'config')
|
||||
@patch.object(ceph_hooks.ceph, 'get_named_key')
|
||||
|
@ -479,7 +483,8 @@ class RelatedUnitsTestCase(unittest.TestCase):
|
|||
get_public_addr,
|
||||
get_named_key,
|
||||
_config,
|
||||
_get_rbd_features):
|
||||
_get_rbd_features,
|
||||
_send_osd_settings):
|
||||
# Check for LP #1738154
|
||||
ready_for_service.return_value = True
|
||||
process_requests.return_value = 'AOK'
|
||||
|
@ -491,6 +496,7 @@ class RelatedUnitsTestCase(unittest.TestCase):
|
|||
_config.side_effect = lambda key: config[key]
|
||||
_get_rbd_features.return_value = None
|
||||
ceph_hooks.client_relation(relid='rel1', unit='glance/0')
|
||||
_send_osd_settings.assert_called_once_with()
|
||||
relation_set.assert_called_once_with(
|
||||
relation_id='rel1',
|
||||
relation_settings={
|
||||
|
|
|
@ -17,6 +17,8 @@ import sys
|
|||
|
||||
import test_utils
|
||||
|
||||
import charmhelpers.contrib.storage.linux.ceph as ch_ceph
|
||||
|
||||
# python-apt is not installed as part of test-requirements but is imported by
|
||||
# some charmhelpers modules so create a fake import.
|
||||
mock_apt = mock.MagicMock()
|
||||
|
@ -81,32 +83,56 @@ class ServiceStatusTestCase(test_utils.CharmTestCase):
|
|||
self.status_set.assert_called_with('waiting', mock.ANY)
|
||||
self.application_version_set.assert_called_with('10.2.2')
|
||||
|
||||
@mock.patch.object(hooks, 'get_osd_settings')
|
||||
@mock.patch.object(hooks, 'has_rbd_mirrors')
|
||||
@mock.patch.object(hooks, 'sufficient_osds')
|
||||
@mock.patch.object(hooks, 'get_peer_units')
|
||||
def test_assess_status_peers_complete_active(self, _peer_units,
|
||||
_sufficient_osds,
|
||||
_has_rbd_mirrors):
|
||||
_has_rbd_mirrors,
|
||||
_get_osd_settings):
|
||||
_peer_units.return_value = ENOUGH_PEERS_COMPLETE
|
||||
_sufficient_osds.return_value = True
|
||||
self.ceph.is_bootstrapped.return_value = True
|
||||
self.ceph.is_quorum.return_value = True
|
||||
_has_rbd_mirrors.return_value = False
|
||||
_get_osd_settings.return_value = {}
|
||||
hooks.assess_status()
|
||||
self.status_set.assert_called_with('active', mock.ANY)
|
||||
self.application_version_set.assert_called_with('10.2.2')
|
||||
|
||||
@mock.patch.object(hooks, 'get_osd_settings')
|
||||
@mock.patch.object(hooks, 'has_rbd_mirrors')
|
||||
@mock.patch.object(hooks, 'sufficient_osds')
|
||||
@mock.patch.object(hooks, 'get_peer_units')
|
||||
def test_assess_status_invalid_osd_settings(self, _peer_units,
|
||||
_sufficient_osds,
|
||||
_has_rbd_mirrors,
|
||||
_get_osd_settings):
|
||||
_peer_units.return_value = ENOUGH_PEERS_COMPLETE
|
||||
_sufficient_osds.return_value = True
|
||||
self.ceph.is_bootstrapped.return_value = True
|
||||
self.ceph.is_quorum.return_value = True
|
||||
_has_rbd_mirrors.return_value = False
|
||||
_get_osd_settings.side_effect = ch_ceph.OSDSettingConflict(
|
||||
'conflict in setting foo')
|
||||
hooks.assess_status()
|
||||
self.status_set.assert_called_with('blocked', mock.ANY)
|
||||
|
||||
@mock.patch.object(hooks, 'get_osd_settings')
|
||||
@mock.patch.object(hooks, 'has_rbd_mirrors')
|
||||
@mock.patch.object(hooks, 'sufficient_osds')
|
||||
@mock.patch.object(hooks, 'get_peer_units')
|
||||
def test_assess_status_peers_complete_down(self, _peer_units,
|
||||
_sufficient_osds,
|
||||
_has_rbd_mirrors):
|
||||
_has_rbd_mirrors,
|
||||
_get_osd_settings):
|
||||
_peer_units.return_value = ENOUGH_PEERS_COMPLETE
|
||||
_sufficient_osds.return_value = True
|
||||
self.ceph.is_bootstrapped.return_value = False
|
||||
self.ceph.is_quorum.return_value = False
|
||||
_has_rbd_mirrors.return_value = False
|
||||
_get_osd_settings.return_value = {}
|
||||
hooks.assess_status()
|
||||
self.status_set.assert_called_with('blocked', mock.ANY)
|
||||
self.application_version_set.assert_called_with('10.2.2')
|
||||
|
|
Loading…
Reference in New Issue