Skip to content

Commit c9b2612

Browse files
author
Sergei Antipov
committed
Changes in mongodb_replication module
1 parent 4f126cc commit c9b2612

File tree

1 file changed

+82
-43
lines changed

1 file changed

+82
-43
lines changed

library/mongodb_replication.py

Lines changed: 82 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
from pymongo.errors import ConnectionFailure
107107
from pymongo.errors import OperationFailure
108108
from pymongo.errors import ConfigurationError
109+
from pymongo.errors import AutoReconnect
109110
from pymongo import version as PyMongoVersion
110111
from pymongo import MongoClient
111112
from pymongo import MongoReplicaSetClient
@@ -145,48 +146,62 @@ def check_members(state, module, client, host_name, host_port, host_type):
145146
if "{0}:{1}".format(host_name, host_port) not in member['host'] and member['arbiterOnly']:
146147
module.exit_json(changed=False, host_name=host_name, host_port=host_port, host_type=host_type)
147148

148-
def add_host(module, client, host_name, host_port, host_type):
149-
admin_db = client['admin']
150-
local_db = client['local']
151-
152-
if local_db.system.replset.count() > 1:
153-
module.fail_json(msg='local.system.replset has unexpected contents')
154-
155-
cfg = local_db.system.replset.find_one()
156-
if not cfg:
157-
module.fail_json(msg='no config object retrievable from local.system.replset')
158-
159-
cfg['version'] += 1
160-
max_id = max(cfg['members'], key=lambda x:x['_id'])
161-
new_host = { '_id': max_id['_id'] + 1, 'host': "{0}:{1}".format(host_name, host_port) }
162-
if host_type == 'arbiter':
163-
new_host['arbiterOnly'] = True
164-
165-
cfg['members'].append(new_host)
166-
admin_db.command('replSetReconfig', cfg)
167-
168-
def remove_host(module, client, host_name):
169-
admin_db = client['admin']
170-
local_db = client['local']
171-
172-
if local_db.system.replset.count() > 1:
173-
module.fail_json(msg='local.system.replset has unexpected contents')
174-
175-
cfg = local_db.system.replset.find_one()
176-
if not cfg:
177-
module.fail_json(msg='no config object retrievable from local.system.replset')
178-
179-
cfg['version'] += 1
180-
181-
if len(cfg['members']) == 1:
182-
module.fail_json(msg="You can't delete last member of replica set")
183-
for member in cfg['members']:
184-
if host_name in member['host']:
185-
cfg['members'].remove(member)
186-
else:
187-
fail_msg = "couldn't find member with hostname: {0} in replica set members list".format(host_name)
188-
module.fail_json(msg=fail_msg)
189-
admin_db.command('replSetReconfig', cfg)
149+
def add_host(module, client, host_name, host_port, host_type, timeout=180):
150+
while True:
151+
try:
152+
admin_db = client['admin']
153+
local_db = client['local']
154+
155+
if local_db.system.replset.count() > 1:
156+
module.fail_json(msg='local.system.replset has unexpected contents')
157+
158+
cfg = local_db.system.replset.find_one()
159+
if not cfg:
160+
module.fail_json(msg='no config object retrievable from local.system.replset')
161+
162+
cfg['version'] += 1
163+
max_id = max(cfg['members'], key=lambda x:x['_id'])
164+
new_host = { '_id': max_id['_id'] + 1, 'host': "{0}:{1}".format(host_name, host_port) }
165+
if host_type == 'arbiter':
166+
new_host['arbiterOnly'] = True
167+
168+
cfg['members'].append(new_host)
169+
admin_db.command('replSetReconfig', cfg)
170+
return
171+
except (OperationFailure, AutoReconnect) as e:
172+
timeout = timeout - 5
173+
if timeout <= 0:
174+
module.fail_json(msg='reached timeout while waiting for rs.reconfig(): %s' % str(e))
175+
time.sleep(5)
176+
177+
def remove_host(module, client, host_name, timeout=180):
178+
while True:
179+
try:
180+
admin_db = client['admin']
181+
local_db = client['local']
182+
183+
if local_db.system.replset.count() > 1:
184+
module.fail_json(msg='local.system.replset has unexpected contents')
185+
186+
cfg = local_db.system.replset.find_one()
187+
if not cfg:
188+
module.fail_json(msg='no config object retrievable from local.system.replset')
189+
190+
cfg['version'] += 1
191+
192+
if len(cfg['members']) == 1:
193+
module.fail_json(msg="You can't delete last member of replica set")
194+
for member in cfg['members']:
195+
if host_name in member['host']:
196+
cfg['members'].remove(member)
197+
else:
198+
fail_msg = "couldn't find member with hostname: {0} in replica set members list".format(host_name)
199+
module.fail_json(msg=fail_msg)
200+
except (OperationFailure, AutoReconnect) as e:
201+
timeout = timeout - 5
202+
if timeout <= 0:
203+
module.fail_json(msg='reached timeout while waiting for rs.reconfig(): %s' % str(e))
204+
time.sleep(5)
190205

191206
def load_mongocnf():
192207
config = ConfigParser.RawConfigParser()
@@ -203,6 +218,30 @@ def load_mongocnf():
203218

204219
return creds
205220

221+
def wait_for_ok_and_master(module, client, timeout = 60):
222+
while True:
223+
status = client.admin.command('replSetGetStatus', check=False)
224+
if status['ok'] == 1 and status['myState'] == 1:
225+
return
226+
227+
timeout = timeout - 1
228+
if timeout == 0:
229+
module.fail_json(msg='reached timeout while waiting for rs.status() to become ok=1')
230+
231+
time.sleep(1)
232+
233+
def reconfigure(module,client, rs_config, timeout = 180):
234+
while True:
235+
try:
236+
client['admin'].command('replSetReconfig', rs_config)
237+
return
238+
except (OperationFailure, AutoReconnect) as e:
239+
print e
240+
timeout = timeout - 5
241+
if timeout <= 0:
242+
module.fail_json(msg='reached timeout while waiting for rs.reconfig()')
243+
time.sleep(5)
244+
206245
def authenticate(client, login_user, login_password):
207246
if login_user is None and login_password is None:
208247
mongocnf_creds = load_mongocnf()
@@ -267,7 +306,7 @@ def main():
267306
if state == 'present':
268307
config = { '_id': "{0}".format(replica_set), 'members': [{ '_id': 0, 'host': "{0}:{1}".format(host_name, host_port)}] }
269308
client['admin'].command('replSetInitiate', config)
270-
time.sleep(3)
309+
wait_for_ok_and_master(module, client)
271310
replica_set_created = True
272311
module.exit_json(changed=True, host_name=host_name, host_port=host_port, host_type=host_type)
273312
except OperationFailure, e:

0 commit comments

Comments
 (0)