Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c81feb8

Browse files
committed
Merge pull request alphagov#73 from alphagov/safe-reboot-mongo
Safe reboot mongo
2 parents e22a605 + 70bd0ac commit c81feb8

File tree

1 file changed

+60
-9
lines changed

1 file changed

+60
-9
lines changed

mongo.py

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from fabric.api import *
2+
from fabric import colors
23
from datetime import *
4+
from time import sleep
35
import json
46
import re
5-
import time
67

78
today = date.today().strftime("%a %b %d")
89

@@ -19,7 +20,10 @@ def mongo_command(command):
1920
def run_mongo_command(command):
2021
response = run(mongo_command(command))
2122

22-
return json.loads(strip_dates(response))
23+
try:
24+
return json.loads(strip_dates(response))
25+
except ValueError:
26+
print response
2327

2428
@task(default=True)
2529
@roles('class-mongo')
@@ -32,10 +36,35 @@ def find_primary():
3236
"""Find which mongo node is the master"""
3337
with hide('output'):
3438
config = run_mongo_command("rs.isMaster()")
39+
out = None
3540
if 'primary' in config:
36-
print("Current primary is %s" % node_name(config['primary']))
41+
out = node_name(config['primary']).split(':')[0]
3742
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+
3968

4069
@task
4170
def status():
@@ -56,14 +85,36 @@ def status():
5685
for status in parsed_statuses:
5786
print("| {0:<22} | {1:<8} | {2:<10} | {3:<22} |".format(status[0], status[1], status[2], status[3]))
5887

88+
5989
@task
6090
def step_down_primary(seconds='100'):
6191
"""Step down as primary for a given number of seconds (default: 100)"""
6292
# Mongo returns an exit code of 252 when the primary steps down, as well as disconnecting
6393
# 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)
66119

67-
if 'ok' in result and result['ok'] == 0:
68-
print("Failed to step down: %s\nTry running mongo.find_primary" % result['errmsg'])
69-
return 0
120+
execute(vm.reboot, hosts=[env['host_string']])

0 commit comments

Comments
 (0)