This repository was archived by the owner on Nov 16, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathmongo.py
131 lines (96 loc) · 3.7 KB
/
mongo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from fabric.api import task, runs_once
from fabric.api import run, sudo, hide, settings, abort, execute, puts, env
from fabric import colors
from time import sleep
import json
import re
def _strip_bson(raw_output):
stripped = re.sub(r'(ISODate|ObjectId|NumberLong)\((.*?)\)', r'\2', raw_output)
return re.sub(r'Timestamp\((.*?)\)', r'"\1"', stripped)
def _run_mongo_command(command):
response = run("mongo --quiet --eval 'printjson(%s)'" % command)
try:
return json.loads(_strip_bson(response))
except ValueError:
print response
def _i_am_primary(primary=None):
return _run_mongo_command("rs.isMaster()")["ismaster"]
def _wait_for_ok():
while True:
if _cluster_is_ok():
return
sleep(5)
print("Waiting for cluster to be okay")
def _cluster_is_ok():
member_statuses = _run_mongo_command("rs.status()")["members"]
health_ok = all(s['health'] == 1 for s in member_statuses)
state_ok = all(s['stateStr'] in ['PRIMARY', 'SECONDARY']
for s in member_statuses)
one_primary = len([s for s in member_statuses
if s['stateStr'] == 'PRIMARY']) == 1
return health_ok and state_ok and one_primary
@task
def force_resync():
"""Force a mongo secondary to resync by removing all its data."""
if len(env.hosts) > 1:
abort("This task should only be run on one host at a time")
if _i_am_primary():
abort(colors.red("Refusing to force resync on primary", bold=True))
execute("puppet.disable", "Forcing mongodb resync")
execute("app.stop", "mongodb")
# wait for mongod process to stop
while run("ps -C mongod", quiet=True).return_code == 0:
puts("Waiting for mongod to stop")
sleep(1)
sudo("rm -rf /var/lib/mongodb/*")
execute("app.start", "mongodb")
execute("puppet.enable")
@task
def find_primary():
"""Find which mongo node is the master"""
with hide("everything"):
if _i_am_primary():
print(colors.blue("%s is primary" % env["host_string"], bold=True))
@task
@runs_once
def status():
"""Check the status of the mongo cluster"""
with hide("everything"):
if _cluster_is_ok():
print(colors.blue("Cluster is OK", bold=True))
return
print(colors.blue("db.printReplicationInfo()", bold=True))
print(_run_mongo_command("db.printReplicationInfo()"))
print(colors.blue("db.printSlaveReplicationInfo()", bold=True))
print(_run_mongo_command("db.printSlaveReplicationInfo()"))
print(colors.blue("rs.status()", bold=True))
print(json.dumps(_run_mongo_command("rs.status()"), indent=4))
@task
def step_down_primary(seconds='100'):
"""Step down as primary for a given number of seconds (default: 100)"""
# Mongo returns an exit code of 252 when the primary steps down, as well
# as disconnecting the current console session. We need to mark that as
# okay so that run() won't error.
with hide('output'), settings(ok_ret_codes=[0, 252]):
if _i_am_primary():
_run_mongo_command("rs.stepDown(%s)" % seconds)
if _i_am_primary():
print("I am still the primary")
else:
print("I am no longer the primary")
else:
print("I am not the primary")
@task
def safe_reboot():
"""Reboot a mongo machine, stepping down if it is the primary"""
import vm
if not vm.reboot_required():
print("No reboot required")
return
with hide("everything"):
_wait_for_ok()
if _i_am_primary():
execute(step_down_primary)
with hide("everything"):
_wait_for_ok()
execute(vm.reboot, hosts=[env['host_string']])