Add support for status
This commit is contained in:
commit
463f8ebc01
|
@ -5,6 +5,7 @@ import sys
|
|||
|
||||
from charmhelpers.core.host import service_pause, service_resume
|
||||
from charmhelpers.core.hookenv import action_fail, status_set
|
||||
from percona_utils import assess_status
|
||||
|
||||
|
||||
MYSQL_SERVICE = "mysql"
|
||||
|
@ -18,7 +19,8 @@ def pause(args):
|
|||
if not service_pause(MYSQL_SERVICE):
|
||||
raise Exception("Failed to pause MySQL service.")
|
||||
status_set(
|
||||
"maintenance", "Paused. Use 'resume' action to resume normal service.")
|
||||
"maintenance",
|
||||
"Unit paused - use 'resume' action to resume normal service")
|
||||
|
||||
|
||||
def resume(args):
|
||||
|
@ -27,7 +29,7 @@ def resume(args):
|
|||
@raises Exception should the service fail to start."""
|
||||
if not service_resume(MYSQL_SERVICE):
|
||||
raise Exception("Failed to resume MySQL service.")
|
||||
status_set("active", "")
|
||||
assess_status()
|
||||
|
||||
|
||||
# A dictionary of all the defined actions to callables (which take
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../hooks/percona_utils.py
|
|
@ -61,6 +61,7 @@ from percona_utils import (
|
|||
notify_bootstrapped,
|
||||
is_bootstrapped,
|
||||
get_wsrep_value,
|
||||
assess_status,
|
||||
)
|
||||
from charmhelpers.contrib.database.mysql import (
|
||||
PerconaClusterHelper,
|
||||
|
@ -625,6 +626,7 @@ def main():
|
|||
hooks.execute(sys.argv)
|
||||
except UnregisteredHookError as e:
|
||||
log('Unknown hook {} - skipping.'.format(e))
|
||||
assess_status()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -25,6 +25,7 @@ from charmhelpers.core.hookenv import (
|
|||
INFO,
|
||||
WARNING,
|
||||
ERROR,
|
||||
status_set,
|
||||
)
|
||||
from charmhelpers.fetch import (
|
||||
apt_install,
|
||||
|
@ -360,3 +361,36 @@ def notify_bootstrapped(cluster_rid=None, cluster_uuid=None):
|
|||
(cluster_uuid), DEBUG)
|
||||
for rid in rids:
|
||||
relation_set(relation_id=rid, **{'bootstrap-uuid': cluster_uuid})
|
||||
|
||||
|
||||
def cluster_in_sync():
|
||||
'''
|
||||
Determines whether the current unit is in sync
|
||||
with the rest of the cluster
|
||||
'''
|
||||
ready = get_wsrep_value('wsrep_ready') or False
|
||||
sync_status = get_wsrep_value('wsrep_local_state') or 0
|
||||
if ready and int(sync_status) in [2, 4]:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def assess_status():
|
||||
'''Assess the status of the current unit'''
|
||||
min_size = config('min-cluster-size')
|
||||
# Ensure that number of peers > cluster size configuration
|
||||
if not is_sufficient_peers():
|
||||
status_set('blocked', 'Insufficient peers to bootstrap cluster')
|
||||
return
|
||||
|
||||
if min_size and int(min_size) > 1:
|
||||
# Once running, ensure that cluster is in sync
|
||||
# and has the required peers
|
||||
if not is_bootstrapped():
|
||||
status_set('waiting', 'Unit waiting for cluster bootstrap')
|
||||
elif is_bootstrapped() and cluster_in_sync():
|
||||
status_set('active', 'Unit is ready and clustered')
|
||||
else:
|
||||
status_set('blocked', 'Unit is not in sync')
|
||||
else:
|
||||
status_set('active', 'Unit is ready')
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
percona_hooks.py
|
|
@ -14,7 +14,7 @@ class PauseResume(basic_deployment.BasicDeployment):
|
|||
uid = 'percona-cluster/0'
|
||||
unit = self.d.sentry.unit[uid]
|
||||
assert self.is_mysqld_running(unit), 'mysql not running: %s' % uid
|
||||
assert utils.status_get(unit)[0] == "unknown"
|
||||
assert utils.status_get(unit)[0] == "active"
|
||||
|
||||
action_id = utils.run_action(unit, "pause")
|
||||
assert utils.wait_on_action(action_id), "Pause action failed."
|
||||
|
|
|
@ -11,7 +11,9 @@ TO_PATCH = ['log', 'config',
|
|||
'relation_set',
|
||||
'update_nrpe_config',
|
||||
'get_iface_for_address',
|
||||
'get_netmask_for_address']
|
||||
'get_netmask_for_address',
|
||||
'is_bootstrapped',
|
||||
'is_sufficient_peers']
|
||||
|
||||
|
||||
class TestHaRelation(CharmTestCase):
|
||||
|
|
|
@ -7,6 +7,8 @@ import sys
|
|||
sys.modules['MySQLdb'] = mock.Mock()
|
||||
import percona_utils
|
||||
|
||||
from test_utils import CharmTestCase
|
||||
|
||||
|
||||
class UtilsTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
@ -160,3 +162,72 @@ class UtilsTests(unittest.TestCase):
|
|||
self.assertEqual(percona_utils.determine_packages(),
|
||||
['percona-xtradb-cluster-server-5.5',
|
||||
'percona-xtradb-cluster-client-5.5'])
|
||||
|
||||
@mock.patch.object(percona_utils, 'get_wsrep_value')
|
||||
def test_cluster_in_sync_not_ready(self, _wsrep_value):
|
||||
_wsrep_value.side_effect = [None, None]
|
||||
self.assertFalse(percona_utils.cluster_in_sync())
|
||||
|
||||
@mock.patch.object(percona_utils, 'get_wsrep_value')
|
||||
def test_cluster_in_sync_ready_syncing(self, _wsrep_value):
|
||||
_wsrep_value.side_effect = [True, None]
|
||||
self.assertFalse(percona_utils.cluster_in_sync())
|
||||
|
||||
@mock.patch.object(percona_utils, 'get_wsrep_value')
|
||||
def test_cluster_in_sync_ready_sync(self, _wsrep_value):
|
||||
_wsrep_value.side_effect = [True, 4]
|
||||
self.assertTrue(percona_utils.cluster_in_sync())
|
||||
|
||||
@mock.patch.object(percona_utils, 'get_wsrep_value')
|
||||
def test_cluster_in_sync_ready_sync_donor(self, _wsrep_value):
|
||||
_wsrep_value.side_effect = [True, 2]
|
||||
self.assertTrue(percona_utils.cluster_in_sync())
|
||||
|
||||
|
||||
TO_PATCH = [
|
||||
'status_set',
|
||||
'is_sufficient_peers',
|
||||
'is_bootstrapped',
|
||||
'config',
|
||||
'cluster_in_sync',
|
||||
]
|
||||
|
||||
|
||||
class TestAssessStatus(CharmTestCase):
|
||||
def setUp(self):
|
||||
CharmTestCase.setUp(self, percona_utils, TO_PATCH)
|
||||
|
||||
def test_single_unit(self):
|
||||
self.config.return_value = None
|
||||
self.is_sufficient_peers.return_value = True
|
||||
percona_utils.assess_status()
|
||||
self.status_set.assert_called_with('active', mock.ANY)
|
||||
|
||||
def test_insufficient_peers(self):
|
||||
self.config.return_value = 3
|
||||
self.is_sufficient_peers.return_value = False
|
||||
percona_utils.assess_status()
|
||||
self.status_set.assert_called_with('blocked', mock.ANY)
|
||||
|
||||
def test_not_bootstrapped(self):
|
||||
self.config.return_value = 3
|
||||
self.is_sufficient_peers.return_value = True
|
||||
self.is_bootstrapped.return_value = False
|
||||
percona_utils.assess_status()
|
||||
self.status_set.assert_called_with('waiting', mock.ANY)
|
||||
|
||||
def test_bootstrapped_in_sync(self):
|
||||
self.config.return_value = 3
|
||||
self.is_sufficient_peers.return_value = True
|
||||
self.is_bootstrapped.return_value = True
|
||||
self.cluster_in_sync.return_value = True
|
||||
percona_utils.assess_status()
|
||||
self.status_set.assert_called_with('active', mock.ANY)
|
||||
|
||||
def test_bootstrapped_not_in_sync(self):
|
||||
self.config.return_value = 3
|
||||
self.is_sufficient_peers.return_value = True
|
||||
self.is_bootstrapped.return_value = True
|
||||
self.cluster_in_sync.return_value = False
|
||||
percona_utils.assess_status()
|
||||
self.status_set.assert_called_with('blocked', mock.ANY)
|
||||
|
|
Loading…
Reference in New Issue