125
125
EXAMPLES = '''
126
126
# Add 'mongo1.dev:27017' host into replica set as replica (Replica will be initiated if it not exists)
127
127
- mongodb_replication: replica_set=replSet host_name=mongo1.dev host_port=27017 state=present
128
-
129
128
# Add 'mongo2.dev:30000' host into replica set as arbiter
130
129
- mongodb_replication: replica_set=replSet host_name=mongo2.dev host_port=30000 host_type=arbiter state=present
131
-
132
130
# Add 'mongo3.dev:27017' host into replica set as replica and authorization params
133
131
- mongodb_replication: replica_set=replSet login_host=mongo1.dev login_user=siteRootAdmin login_password=123456 host_name=mongo3.dev host_port=27017 state=present
134
-
135
132
# Add 'mongo4.dev:27017' host into replica set as replica via SSL
136
133
- mongodb_replication: replica_set=replSet host_name=mongo4.dev host_port=27017 ssl=True state=present
137
-
138
134
# Remove 'mongo4.dev:27017' host from the replica set
139
135
- mongodb_replication: replica_set=replSet host_name=mongo4.dev host_port=27017 state=absent
140
136
'''
@@ -204,6 +200,7 @@ def check_members(state, module, client, host_name, host_port, host_type):
204
200
if not cfg :
205
201
module .fail_json (msg = 'no config object retrievable from local.system.replset' )
206
202
203
+ found_on_remove = False
207
204
for member in cfg ['members' ]:
208
205
if state == 'present' :
209
206
if host_type == 'replica' :
@@ -212,13 +209,17 @@ def check_members(state, module, client, host_name, host_port, host_type):
212
209
else :
213
210
if "{0}:{1}" .format (host_name , host_port ) in member ['host' ] and member ['arbiterOnly' ]:
214
211
module .exit_json (changed = False , host_name = host_name , host_port = host_port , host_type = host_type )
215
- else :
212
+
213
+ if state == 'absent' :
216
214
if host_type == 'replica' :
217
- if "{0}:{1}" .format (host_name , host_port ) not in member ['host' ]:
218
- module . exit_json ( changed = False , host_name = host_name , host_port = host_port , host_type = host_type )
215
+ if "{0}:{1}" .format (host_name , host_port ) in member ['host' ]:
216
+ found_on_remove = True
219
217
else :
220
- if "{0}:{1}" .format (host_name , host_port ) not in member ['host' ] and member ['arbiterOnly' ]:
221
- module .exit_json (changed = False , host_name = host_name , host_port = host_port , host_type = host_type )
218
+ if "{0}:{1}" .format (host_name , host_port ) in member ['host' ] and member ['arbiterOnly' ]:
219
+ found_on_remove = True
220
+ if not found_on_remove and state == 'absent' :
221
+ module .exit_json (changed = False , host_name = host_name , host_port = host_port , host_type = host_type )
222
+
222
223
223
224
def add_host (module , client , host_name , host_port , host_type , timeout = 180 , ** kwargs ):
224
225
start_time = dtdatetime .now ()
@@ -257,13 +258,14 @@ def add_host(module, client, host_name, host_port, host_type, timeout=180, **kwa
257
258
258
259
cfg ['members' ].append (new_host )
259
260
admin_db .command ('replSetReconfig' , cfg )
261
+ module .exit_json (changed = True , host_name = host_name , host_port = host_port , host_type = host_type )
260
262
return
261
263
except (OperationFailure , AutoReconnect ) as e :
262
264
if (dtdatetime .now () - start_time ).seconds > timeout :
263
265
module .fail_json (msg = 'reached timeout while waiting for rs.reconfig(): %s' % str (e ))
264
266
time .sleep (5 )
265
267
266
- def remove_host (module , client , host_name , timeout = 180 ):
268
+ def remove_host (module , client , host_name , host_port , timeout = 180 ):
267
269
start_time = dtdatetime .now ()
268
270
while True :
269
271
try :
@@ -281,12 +283,21 @@ def remove_host(module, client, host_name, timeout=180):
281
283
282
284
if len (cfg ['members' ]) == 1 :
283
285
module .fail_json (msg = "You can't delete last member of replica set" )
286
+
287
+ removed_host = False
284
288
for member in cfg ['members' ]:
285
- if host_name in member ['host' ]:
289
+ if host_name + ":" + host_port in member ['host' ]:
286
290
cfg ['members' ].remove (member )
287
- else :
288
- fail_msg = "couldn't find member with hostname: {0} in replica set members list" .format (host_name )
289
- module .fail_json (msg = fail_msg )
291
+
292
+ if remove_host :
293
+ cfg ['version' ] += 1
294
+ admin_db .command ('replSetReconfig' , cfg )
295
+ module .exit_json (changed = True , host_name = host_name , host_port = host_port )
296
+
297
+ if not removed_host :
298
+ fail_msg = "couldn't find member with hostname: {0} in replica set members list" .format (host_name )
299
+ module .fail_json (msg = fail_msg )
300
+
290
301
except (OperationFailure , AutoReconnect ) as e :
291
302
if (dtdatetime .now () - start_time ).seconds > timeout :
292
303
module .fail_json (msg = 'reached timeout while waiting for rs.reconfig(): %s' % str (e ))
@@ -382,9 +393,10 @@ def main():
382
393
ssl = module .params ['ssl' ]
383
394
state = module .params ['state' ]
384
395
priority = float (module .params ['priority' ])
385
-
396
+ hidden = module .params ['hidden' ]
397
+ votes = module .params ['votes' ]
386
398
replica_set_created = False
387
-
399
+
388
400
try :
389
401
if replica_set is None :
390
402
module .fail_json (msg = 'replica_set parameter is required' )
@@ -398,7 +410,6 @@ def main():
398
410
"serverselectiontimeoutms" : 5000 ,
399
411
"replicaset" : replica_set ,
400
412
}
401
-
402
413
if ssl :
403
414
connection_params ["ssl" ] = ssl
404
415
connection_params ["ssl_cert_reqs" ] = getattr (ssl_lib , module .params ['ssl_cert_reqs' ])
@@ -407,6 +418,38 @@ def main():
407
418
authenticate (client , login_user , login_password )
408
419
client ['admin' ].command ('replSetGetStatus' )
409
420
421
+ # Successful RS connection
422
+ repl_set_status = None
423
+ current_host_found = False
424
+ try :
425
+ repl_set_status = client ['admin' ].command ('replSetGetStatus' )
426
+ current_host_found = host_name + ":" + host_port in [x ["name" ] for x in repl_set_status ["members" ]]
427
+ except Exception as e :
428
+ if not "no replset config has been received" in str (e ):
429
+ raise e
430
+
431
+ if current_host_found and state == 'present' :
432
+ requires_changes = False
433
+ current_config = client ['admin' ].command ('replSetGetConfig' )
434
+ for this_host in current_config ['config' ]['members' ]:
435
+ if this_host ['host' ] == host_name + ":" + host_port :
436
+ if priority != this_host ['priority' ]:
437
+ requires_changes = True
438
+ this_host ['priority' ] = priority
439
+ if hidden != this_host ['hidden' ]:
440
+ requires_changes = True
441
+ this_host ['hidden' ] = hidden
442
+ if votes != this_host ['votes' ]:
443
+ requires_changes = True
444
+ this_host ['votes' ] = votes
445
+ if requires_changes :
446
+ current_config ['config' ]['version' ] += 1
447
+ client ['admin' ].command ('replSetReconfig' , current_config ['config' ])
448
+ module .exit_json (changed = True , host_name = host_name , host_port = host_port , host_type = host_type )
449
+ if not requires_changes :
450
+ module .exit_json (changed = False , host_name = host_name , host_port = host_port , host_type = host_type )
451
+
452
+
410
453
except ServerSelectionTimeoutError :
411
454
try :
412
455
connection_params = {
@@ -433,7 +476,8 @@ def main():
433
476
wait_for_ok_and_master (module , connection_params )
434
477
replica_set_created = True
435
478
module .exit_json (changed = True , host_name = host_name , host_port = host_port , host_type = host_type )
436
- except OperationFailure as e :
479
+
480
+ except OperationFailure as e :
437
481
module .fail_json (msg = 'Unable to initiate replica set: %s' % str (e ))
438
482
except ConnectionFailure as e :
439
483
module .fail_json (msg = 'unable to connect to database: %s' % str (e ))
@@ -461,12 +505,13 @@ def main():
461
505
462
506
elif state == 'absent' :
463
507
try :
464
- remove_host (module , client , host_name )
508
+ remove_host (module , client , host_name , host_port )
465
509
except OperationFailure as e :
466
510
module .fail_json (msg = 'Unable to remove member of replica set: %s' % str (e ))
467
511
468
- module .exit_json (changed = True , host_name = host_name , host_port = host_port , host_type = host_type )
512
+ module .fail_json (msg = 'Operation error' )
513
+
469
514
470
515
# import module snippets
471
516
from ansible .module_utils .basic import *
472
- main ()
517
+ main ()
0 commit comments