1515 false
1616 end
1717
18- commands :mongo => 'mongo'
19-
2018 mk_resource_methods
2119
2220 def initialize ( resource = { } )
@@ -67,31 +65,43 @@ def flush
6765 private
6866
6967 def db_ismaster ( host )
70- mongo_command ( " db.isMaster()" , host )
68+ mongo_command ( ' db.isMaster()' , host )
7169 end
7270
7371 def rs_initiate ( conf , master )
74- return mongo_command ( "rs.initiate(#{ conf } )" , master )
72+ if auth_enabled
73+ return mongo_command ( "rs.initiate(#{ conf } )" , initialize_host )
74+ else
75+ return mongo_command ( "rs.initiate(#{ conf } )" , master )
76+ end
7577 end
7678
7779 def rs_status ( host )
78- mongo_command ( " rs.status()" , host )
80+ mongo_command ( ' rs.status()' , host )
7981 end
8082
8183 def rs_add ( host , master )
82- mongo_command ( "rs.add(\" #{ host } \" )" , master )
84+ mongo_command ( "rs.add(' #{ host } ' )" , master )
8385 end
8486
8587 def rs_remove ( host , master )
86- mongo_command ( "rs.remove(\" #{ host } \" )" , master )
88+ mongo_command ( "rs.remove(' #{ host } ' )" , master )
8789 end
8890
8991 def rs_arbiter
9092 @resource [ :arbiter ]
9193 end
9294
9395 def rs_add_arbiter ( host , master )
94- mongo_command ( "rs.addArb(\" #{ host } \" )" , master )
96+ mongo_command ( "rs.addArb('#{ host } ')" , master )
97+ end
98+
99+ def auth_enabled
100+ self . class . auth_enabled
101+ end
102+
103+ def initialize_host
104+ @resource [ :initialize_host ]
95105 end
96106
97107 def master_host ( hosts )
@@ -104,17 +114,7 @@ def master_host(hosts)
104114 false
105115 end
106116
107- def self . get_mongod_conf_file
108- if File . exists? '/etc/mongod.conf'
109- file = '/etc/mongod.conf'
110- else
111- file = '/etc/mongodb.conf'
112- end
113- file
114- end
115-
116117 def self . get_replset_properties
117-
118118 conn_string = get_conn_string
119119 output = mongo_command ( 'rs.conf()' , conn_string )
120120 if output [ 'members' ]
@@ -135,31 +135,37 @@ def self.get_replset_properties
135135 end
136136
137137 def alive_members ( hosts )
138+ alive = [ ]
138139 hosts . select do |host |
139140 begin
140141 Puppet . debug "Checking replicaset member #{ host } ..."
141142 status = rs_status ( host )
142143 if status . has_key? ( 'errmsg' ) and status [ 'errmsg' ] == 'not running with --replSet'
143144 raise Puppet ::Error , "Can't configure replicaset #{ self . name } , host #{ host } is not supposed to be part of a replicaset."
144145 end
146+
147+ if auth_enabled and status . has_key? ( 'errmsg' ) and ( status [ 'errmsg' ] . include? "unauthorized" or status [ 'errmsg' ] . include? "not authorized" )
148+ Puppet . warning "Host #{ host } is available, but you are unauthorized because of authentication is enabled: #{ auth_enabled } "
149+ alive . push ( host )
150+ end
151+
145152 if status . has_key? ( 'set' )
146153 if status [ 'set' ] != self . name
147154 raise Puppet ::Error , "Can't configure replicaset #{ self . name } , host #{ host } is already part of another replicaset."
148155 end
149156
150157 # This node is alive and supposed to be a member of our set
151158 Puppet . debug "Host #{ host } is available for replset #{ status [ 'set' ] } "
152- true
159+ alive . push ( host )
153160 elsif status . has_key? ( 'info' )
154161 Puppet . debug "Host #{ host } is alive but unconfigured: #{ status [ 'info' ] } "
155- true
162+ alive . push ( host )
156163 end
157164 rescue Puppet ::ExecutionFailure
158165 Puppet . warning "Can't connect to replicaset member #{ host } ."
159-
160- false
161166 end
162167 end
168+ return alive
163169 end
164170
165171 def set_members
@@ -176,14 +182,14 @@ def set_members
176182 # Find the alive members so we don't try to add dead members to the replset
177183 alive_hosts = alive_members ( @property_flush [ :members ] )
178184 dead_hosts = @property_flush [ :members ] - alive_hosts
179- raise Puppet ::Error , "Can't connect to any member of replicaset #{ self . name } ." if alive_hosts . empty?
180185 Puppet . debug "Alive members: #{ alive_hosts . inspect } "
181186 Puppet . debug "Dead members: #{ dead_hosts . inspect } " unless dead_hosts . empty?
187+ raise Puppet ::Error , "Can't connect to any member of replicaset #{ self . name } ." if alive_hosts . empty?
182188 else
183189 alive_hosts = [ ]
184190 end
185191
186- if @property_flush [ :ensure ] == :present and @property_hash [ :ensure ] != :present
192+ if @property_flush [ :ensure ] == :present and @property_hash [ :ensure ] != :present and ! master_host ( alive_hosts )
187193 Puppet . debug "Initializing the replset #{ self . name } "
188194
189195 # Create a replset configuration
@@ -201,12 +207,35 @@ def set_members
201207 if output [ 'ok' ] == 0
202208 raise Puppet ::Error , "rs.initiate() failed for replicaset #{ self . name } : #{ output [ 'errmsg' ] } "
203209 end
210+
211+ # Check that the replicaset has finished initialization
212+ retry_limit = 10
213+ retry_sleep = 3
214+
215+ retry_limit . times do |n |
216+ begin
217+ if db_ismaster ( alive_hosts [ 0 ] ) [ 'ismaster' ]
218+ Puppet . debug 'Replica set initialization has successfully ended'
219+ return
220+ else
221+ Puppet . debug "Wainting for replica initialization. Retry: #{ n } "
222+ sleep retry_sleep
223+ next
224+ end
225+ end
226+ end
227+ raise Puppet ::Error , "rs.initiate() failed for replicaset #{ self . name } : host #{ alive_hosts [ 0 ] } didn't become master"
228+
204229 else
205230 # Add members to an existing replset
231+ Puppet . debug "Adding member to existing replset #{ self . name } "
206232 if master = master_host ( alive_hosts )
207- current_hosts = db_ismaster ( master ) [ 'hosts' ]
233+ master_data = db_ismaster ( master )
234+ current_hosts = master_data [ 'hosts' ]
235+ current_hosts = current_hosts + master_data [ 'arbiters' ] if master_data . has_key? ( 'arbiters' )
208236 Puppet . debug "Current Hosts are: #{ current_hosts . inspect } "
209237 newhosts = alive_hosts - current_hosts
238+ Puppet . debug "New Hosts are: #{ newhosts . inspect } "
210239 newhosts . each do |host |
211240 output = { }
212241 if rs_arbiter == host
@@ -225,39 +254,27 @@ def set_members
225254 end
226255
227256 def mongo_command ( command , host , retries = 4 )
228- self . class . mongo_command ( command , host , retries )
257+ self . class . mongo_command ( command , host , retries )
229258 end
230259
231260 def self . mongo_command ( command , host = nil , retries = 4 )
232- # Allow waiting for mongod to become ready
233- # Wait for 2 seconds initially and double the delay at each retry
234- wait = 2
235261 begin
236- args = Array . new
237- args << '--quiet'
238- args << [ '--host' , host ] if host
239- args << [ '--eval' , "printjson(#{ command } )" ]
240- output = mongo ( args . flatten )
262+ output = mongo_eval ( "printjson(#{ command } )" , 'admin' , retries , host )
241263 rescue Puppet ::ExecutionFailure => e
242- if e =~ /Error: couldn't connect to server/ and wait <= 2 **max_wait
243- info ( "Waiting #{ wait } seconds for mongod to become available" )
244- sleep wait
245- wait *= 2
246- retry
247- else
248- raise
249- end
264+ Puppet . debug "Got an exception: #{ e } "
265+ raise
250266 end
251267
252268 # Dirty hack to remove JavaScript objects
253269 output . gsub! ( /ISODate\( (.+?)\) / , '\1 ' )
254270 output . gsub! ( /Timestamp\( (.+?)\) / , '[\1]' )
255- output . gsub! ( /ObjectId\( ([^)]*)\) / , '\1' )
256271
257272 #Hack to avoid non-json empty sets
258273 output = "{}" if output == "null\n "
259274
275+ # Parse the JSON output and return
260276 JSON . parse ( output )
277+
261278 end
262279
263280end
0 commit comments