/usr/share/puppet/modules.available/puppetlabs-mongodb/lib/puppet/provider/mongodb_replset/mongo.rb is in puppet-module-puppetlabs-mongodb 0.7.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 132 133 134 135 136 137 138 | #
# Author: François Charlier <francois.charlier@enovance.com>
#
require 'json'
Puppet::Type.type(:mongodb_replset).provide(:mongo) do
desc "Manage hosts members for a replicaset."
commands :mongo => 'mongo'
def create
alive_members = members_present
hostsconf = alive_members.collect.each_with_index do |host, id|
"{ _id: #{id}, host: \"#{host}\" }"
end.join(',')
conf = "{ _id: \"#{@resource[:name]}\", members: [ #{hostsconf} ] }"
output = self.rs_initiate(conf, alive_members[0])
if output['ok'] == 0
raise Puppet::Error, "rs.initiate() failed for replicaset #{@resource[:name]}: #{output['errmsg']}"
end
end
def destroy
end
def exists?
failcount = 0
is_configured = false
@resource[:members].each do |host|
begin
debug "Checking replicaset member #{host} ..."
status = self.rs_status(host)
if status.has_key?('errmsg') and status['errmsg'] == 'not running with --replSet'
raise Puppet::Error, "Can't configure replicaset #{@resource[:name]}, host #{host} is not supposed to be part of a replicaset."
end
if status.has_key?('set')
if status['set'] != @resource[:name]
raise Puppet::Error, "Can't configure replicaset #{@resource[:name]}, host #{host} is already part of another replicaset."
end
is_configured = true
end
rescue Puppet::ExecutionFailure
debug "Can't connect to replicaset member #{host}."
failcount += 1
end
end
if failcount == @resource[:members].length
raise Puppet::Error, "Can't connect to any member of replicaset #{@resource[:name]}."
end
return is_configured
end
def members
if master = self.master_host()
self.db_ismaster(master)['hosts']
else
raise Puppet::Error, "Can't find master host for replicaset #{@resource[:name]}."
end
end
def members=(hosts)
if master = master_host()
current = self.db_ismaster(master)['hosts']
newhosts = hosts - current
newhosts.each do |host|
#TODO: check output (['ok'] == 0 should be sufficient)
self.rs_add(host, master)
end
else
raise Puppet::Error, "Can't find master host for replicaset #{@resource[:name]}."
end
end
def members_present
@resource[:members].select do |host|
begin
self.mongo('--host', host, '--quiet', '--eval', 'db.version()')
true
rescue Puppet::ExecutionFailure
false
end
end
end
def mongo_command(command, host, retries=4)
# Allow waiting for mongod to become ready
# Wait for 2 seconds initially and double the delay at each retry
wait = 2
begin
output = self.mongo('--quiet', '--host', host, '--eval', "printjson(#{command})")
rescue Puppet::ExecutionFailure => e
if e =~ /Error: couldn't connect to server/ and wait <= 2**max_wait
info("Waiting #{wait} seconds for mongod to become available")
sleep wait
wait *= 2
retry
else
raise
end
end
# Dirty hack to remove JavaScript objects
output.gsub!(/ISODate\((.+?)\)/, '\1 ')
output.gsub!(/Timestamp\((.+?)\)/, '[\1]')
JSON.parse(output)
end
def master_host
@resource[:members].each do |host|
status = self.db_ismaster(host)
if status.has_key?('primary')
return status['primary']
end
end
false
end
def db_ismaster(host)
self.mongo_command("db.isMaster()", host)
end
def rs_initiate(conf, host)
return self.mongo_command("rs.initiate(#{conf})", @resource[:members][0])
end
def rs_status(host)
self.mongo_command("rs.status()", host)
end
def rs_add(host, master)
self.mongo_command("rs.add(\"#{host}\")", master)
end
end
|