Merge ~mariosplivalo/charm-mongodb:status-fix into ~mongodb-charmers/charm-mongodb:master

Proposed by Mario Splivalo
Status: Merged
Merged at revision: 8faa36725b36c34ca625ea88391420083b3a2934
Proposed branch: ~mariosplivalo/charm-mongodb:status-fix
Merge into: ~mongodb-charmers/charm-mongodb:master
Diff against target: 204 lines (+87/-4)
2 files modified
hooks/hooks.py (+86/-4)
hooks/update-status (+1/-0)
Reviewer Review Type Date Requested Status
Stuart Bishop (community) Approve
Review via email: mp+341289@code.launchpad.net

Description of the change

This will add update-status hook along with several utility functions that help display mongodb replicaset status in 'juju status', along with the workflow state.

It also calls status-set inside config-changed and replicaset-relation-changed hooks so that status is updated while replicaset is being formed and/or units added to replicaset.

To post a comment you must log in.
Revision history for this message
Stuart Bishop (stub) wrote :

Looks good.

get_replicaset_status() may return None if things are really screwed, but that is easily fixed. Commented on inline.

review: Approve
Revision history for this message
Mario Splivalo (mariosplivalo) :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/hooks/hooks.py b/hooks/hooks.py
2index d3774a7..c8fbece 100755
3--- a/hooks/hooks.py
4+++ b/hooks/hooks.py
5@@ -13,6 +13,7 @@ import socket
6 import subprocess
7 import sys
8 import time
9+import pprint
10
11 try:
12 import yaml # flake8: noqa
13@@ -58,7 +59,9 @@ from charmhelpers.core.hookenv import (
14 Hooks,
15 DEBUG,
16 WARNING,
17- is_leader
18+ is_leader,
19+ status_set,
20+ application_version_set,
21 )
22
23 from charmhelpers.core.hookenv import log as juju_log
24@@ -66,7 +69,6 @@ from charmhelpers.core.hookenv import log as juju_log
25 from charmhelpers.payload.execd import execd_preinstall
26
27 from charmhelpers.contrib.hahelpers.cluster import (
28- oldest_peer,
29 peer_units
30 )
31
32@@ -920,6 +922,7 @@ def arm64_trusty_quirk():
33 @hooks.hook('install.real')
34 def install_hook():
35 juju_log('Begin install hook.')
36+ status_set('maintenance', 'Installing packages')
37 execd_preinstall()
38 juju_log("Installing mongodb")
39 add_source(config('source'), config('key'))
40@@ -935,7 +938,7 @@ def install_hook():
41 @hooks.hook('config-changed')
42 def config_changed():
43 juju_log("Entering config_changed")
44- print "Entering config_changed"
45+ status_set('maintenance', 'Configuring unit')
46 config_data = config()
47 print "config_data: ", config_data
48 mongodb_config = open(default_mongodb_config).read()
49@@ -1009,6 +1012,7 @@ def config_changed():
50 write_logrotate_config(config_data)
51
52 # restart mongodb
53+ status_set('maintenance', 'Restarting mongod')
54 restart_mongod()
55
56 # attach to replSet ( if needed )
57@@ -1069,6 +1073,8 @@ def config_changed():
58 open_port(config_data['mongos_port'])
59
60 update_nrpe_config()
61+ application_version_set(get_mongod_version())
62+ update_status()
63
64 print "About to leave config_changed"
65 return(True)
66@@ -1148,6 +1154,7 @@ def replica_set_relation_joined():
67 if enable_replset(my_replset):
68 juju_log('Restarting mongodb after config change (enable replset)',
69 level=DEBUG)
70+ status_set('maintenance', 'Restarting mongod to enable replicaset')
71 restart_mongod()
72
73 relation_set(relation_id(), {
74@@ -1157,6 +1164,8 @@ def replica_set_relation_joined():
75 'install-order': my_install_order,
76 'type': 'replset',
77 })
78+
79+ update_status()
80 juju_log("replica_set_relation_joined-finish")
81
82
83@@ -1165,7 +1174,8 @@ def am_i_primary():
84 for i in xrange(10):
85 try:
86 r = run_admin_command(c, 'replSetGetStatus')
87- juju_log('am_i_primary: replSetGetStatus returned: %s' % str(r),
88+ pretty_r = pprint.pformat(r)
89+ juju_log('am_i_primary: replSetGetStatus returned: %s' % pretty_r,
90 level=DEBUG)
91 return r['myState'] == MONGO_PRIMARY
92 except OperationFailure as e:
93@@ -1191,6 +1201,42 @@ def am_i_primary():
94 raise TimeoutException('Unable to determine if local unit is primary')
95
96
97+def get_replicaset_status():
98+ """Connect to mongod and get the status of replicaset
99+ This function is used mainly within update_status() to display
100+ replicaset statue in 'juju status' output
101+
102+ :returns string: can be any of replicaset states
103+ (https://docs.mongodb.com/manual/reference/replica-states/)
104+ or can be the string of an exception while getting the status
105+ """
106+
107+ c = MongoClient('localhost')
108+ try:
109+ r = run_admin_command(c, 'replSetGetStatus')
110+ r_pretty = pprint.pformat(r)
111+ juju_log('get_replicaset_status() failed to get replicaset state:' +
112+ r_pretty, 'WARN')
113+ for member in r['members']:
114+ if 'self' in member:
115+ return member['stateStr']
116+ return 'Unknown'
117+
118+ except OperationFailure as e:
119+ if 'not running with --replSet' in str(e):
120+ return 'not in replicaset'
121+ else:
122+ return str(e)
123+
124+def get_mongod_version():
125+ """ Connects to mongod and get the db.version() output
126+ Mainly used for application_set_version in config-changed hook
127+ """
128+
129+ c = MongoClient('localhost')
130+ return c.server_info()['version']
131+
132+
133 @hooks.hook('replica-set-relation-changed')
134 def replica_set_relation_changed():
135 private_address = unit_get('private-address')
136@@ -1208,6 +1254,7 @@ def replica_set_relation_changed():
137 # Initialize the replicaset - we do this only on the leader!
138 if is_leader():
139 juju_log('Initializing replicaset')
140+ status_set('maintenance', 'Initializing replicaset')
141 init_replset()
142
143 unit = "%s:%s" % (private_address, config('port'))
144@@ -1217,10 +1264,14 @@ def replica_set_relation_changed():
145 if am_i_primary():
146 juju_log('Adding new secondary... %s' % unit_remote, level=DEBUG)
147 join_replset(unit, unit_remote)
148+
149+ while update_status <> 'active':
150+ time.sleep(5)
151
152 juju_log('replica_set_relation_changed-finish')
153
154
155+
156 @hooks.hook('replica-set-relation-departed')
157 def replica_set_relation_departed():
158 juju_log('replica_set_relation_departed-start')
159@@ -1437,6 +1488,37 @@ def uprade_charm():
160 remove_replset_from_upstart()
161 juju_log('upgrade-charm: removing --rest from upstart script')
162 remove_rest_from_upstart()
163+
164+
165+@hooks.hook('update-status')
166+def update_status():
167+ """
168+ Returns: workload_state (so that some hooks know they need to re-run
169+ update_status if needed)
170+ """
171+
172+ juju_log('$$$ update_status()', 'DEBUG')
173+
174+ mongo_status = get_replicaset_status()
175+ if mongo_status in ('PRIMARY', 'SECONDARY'):
176+ print ' ## mongo_status in PRI/SEC'
177+ workload = 'active'
178+ status = 'Unit is ready as ' + mongo_status
179+ elif mongo_status in ('not in replicaset',):
180+ print ' ## mongo_status in "not in replicaset"'
181+ workload = 'active'
182+ status = 'Unit is ready, ' + mongo_status
183+ else:
184+ workload = 'maintenance'
185+ status = mongo_status
186+ print ' ## mongo_status something else: ', status
187+ print ' #> forcing "return False" for update_status()'
188+
189+ juju_log(' $ status:' + status, 'DEBUG')
190+ juju_log(' $ workload: ' + workload, 'DEBUG')
191+
192+ return workload
193+
194
195
196 def run(command, exit_on_error=True):
197diff --git a/hooks/update-status b/hooks/update-status
198new file mode 120000
199index 0000000..9416ca6
200--- /dev/null
201+++ b/hooks/update-status
202@@ -0,0 +1 @@
203+hooks.py
204\ No newline at end of file

Subscribers

People subscribed via source and target branches

to status/vote changes: