106
106
from pymongo .errors import ConnectionFailure
107
107
from pymongo .errors import OperationFailure
108
108
from pymongo .errors import ConfigurationError
109
+ from pymongo .errors import AutoReconnect
109
110
from pymongo import version as PyMongoVersion
110
111
from pymongo import MongoClient
111
112
from pymongo import MongoReplicaSetClient
@@ -145,48 +146,62 @@ def check_members(state, module, client, host_name, host_port, host_type):
145
146
if "{0}:{1}" .format (host_name , host_port ) not in member ['host' ] and member ['arbiterOnly' ]:
146
147
module .exit_json (changed = False , host_name = host_name , host_port = host_port , host_type = host_type )
147
148
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 )
190
205
191
206
def load_mongocnf ():
192
207
config = ConfigParser .RawConfigParser ()
@@ -203,6 +218,30 @@ def load_mongocnf():
203
218
204
219
return creds
205
220
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
+
206
245
def authenticate (client , login_user , login_password ):
207
246
if login_user is None and login_password is None :
208
247
mongocnf_creds = load_mongocnf ()
@@ -267,7 +306,7 @@ def main():
267
306
if state == 'present' :
268
307
config = { '_id' : "{0}" .format (replica_set ), 'members' : [{ '_id' : 0 , 'host' : "{0}:{1}" .format (host_name , host_port )}] }
269
308
client ['admin' ].command ('replSetInitiate' , config )
270
- time . sleep ( 3 )
309
+ wait_for_ok_and_master ( module , client )
271
310
replica_set_created = True
272
311
module .exit_json (changed = True , host_name = host_name , host_port = host_port , host_type = host_type )
273
312
except OperationFailure , e :
0 commit comments