1
1
from fabric .api import *
2
+ from fabric import colors
2
3
from datetime import *
4
+ from time import sleep
3
5
import json
4
6
import re
5
- import time
6
7
7
8
today = date .today ().strftime ("%a %b %d" )
8
9
@@ -19,7 +20,10 @@ def mongo_command(command):
19
20
def run_mongo_command (command ):
20
21
response = run (mongo_command (command ))
21
22
22
- return json .loads (strip_dates (response ))
23
+ try :
24
+ return json .loads (strip_dates (response ))
25
+ except ValueError :
26
+ print response
23
27
24
28
@task (default = True )
25
29
@roles ('class-mongo' )
@@ -32,10 +36,35 @@ def find_primary():
32
36
"""Find which mongo node is the master"""
33
37
with hide ('output' ):
34
38
config = run_mongo_command ("rs.isMaster()" )
39
+ out = None
35
40
if 'primary' in config :
36
- print ( "Current primary is %s" % node_name (config ['primary' ]))
41
+ out = node_name (config ['primary' ]). split ( ':' )[ 0 ]
37
42
else :
38
- print ("No primary currently elected." )
43
+ out = "No primary currently elected."
44
+ print (out )
45
+ return out
46
+
47
+
48
+ def i_am_primary (primary = None ):
49
+ if primary is None :
50
+ primary = find_primary ()
51
+ if primary == 'No primary currently elected.' :
52
+ return False
53
+
54
+ backend_re = re .compile (r'^backend-(\d+).mongo$' )
55
+ if primary == env ['host_string' ]:
56
+ return True
57
+ elif env ['host_string' ].split ('.' )[0 ] == primary .split ('.' )[0 ]:
58
+ # lol licensify-mongo-n.licensify
59
+ return True
60
+ elif backend_re .match (primary ):
61
+ # lol mongo-n.backend
62
+ match = backend_re .match (primary )
63
+ real_primary = 'mongo-{}.backend' .format (match .group (1 ))
64
+ if match and real_primary == env ['host_string' ]:
65
+ return True
66
+ return False
67
+
39
68
40
69
@task
41
70
def status ():
@@ -56,14 +85,36 @@ def status():
56
85
for status in parsed_statuses :
57
86
print ("| {0:<22} | {1:<8} | {2:<10} | {3:<22} |" .format (status [0 ], status [1 ], status [2 ], status [3 ]))
58
87
88
+
59
89
@task
60
90
def step_down_primary (seconds = '100' ):
61
91
"""Step down as primary for a given number of seconds (default: 100)"""
62
92
# Mongo returns an exit code of 252 when the primary steps down, as well as disconnecting
63
93
# the current console session. We need to mark that as okay so that run() won't error.
64
- with hide ('output' ), settings (ok_ret_codes = [0 ,252 ]):
65
- result = run_mongo_command ("rs.stepDown(%s)" % seconds )
94
+ with hide ('output' ), settings (ok_ret_codes = [0 , 252 ]):
95
+ if i_am_primary ():
96
+ run_mongo_command ("rs.stepDown(%s)" % seconds )
97
+ if i_am_primary ():
98
+ print ("I am still the primary" )
99
+ else :
100
+ print ("I am no longer the primary" )
101
+ else :
102
+ print ("I am not the primary" )
103
+
104
+
105
+ @task
106
+ def safe_reboot ():
107
+ """Reboot a mongo machine, stepping down if it is the primary"""
108
+ import vm
109
+ primary = find_primary ()
110
+ if primary == 'No primary currently elected' :
111
+ return primary
112
+
113
+ for i in range (5 ):
114
+ if i_am_primary (primary ):
115
+ if i == 0 :
116
+ execute (step_down_primary , primary )
117
+ else :
118
+ sleep (1 )
66
119
67
- if 'ok' in result and result ['ok' ] == 0 :
68
- print ("Failed to step down: %s\n Try running mongo.find_primary" % result ['errmsg' ])
69
- return 0
120
+ execute (vm .reboot , hosts = [env ['host_string' ]])
0 commit comments