class SnapEbs::Plugin::MongoPlugin

Constants

WIRED_TIGER_KEY

Attributes

client[RW]

Public Instance Methods

after() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 53
def after
  unlock_or_start_mongo

  if carefully('check that mongo is still accessible') { client.command(serverStatus: 1).first }
    logger.info "Received status from mongo, everything appears to be ok"
  end
end
before() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 37
def before
  require 'mongo'
  Mongo::Logger.logger = logger
  return false unless carefully('check if we can operate safely') { safe_to_operate? }

  if wired_tiger?
    logger.info "Wired Tiger storage engine detected"
    carefully('stop mongo') { stop_mongo } if options.shutdown
  else
    logger.info "MMAPv1 storage engine detected"
    carefully('lock mongo') { lock_mongo }
  end

  true
end
default_options() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 22
def default_options
  {
    shutdown: false,
    command: "service mongod start",
    retry: 720,
    interval: 5,
    port: '27017',
    host: 'localhost',
    server_selection_timeout: 30,
    wait_queue_timeout: 1,
    connect_timeout: 5,
    socket_timeout: 5
  }
end
defined_options() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 5
def defined_options
  {
    shutdown: 'Shutdown mongodb server (this is required if your data and journal are on different volumes',
    command: 'Command to start mongodb if the server must be shut down (i.e. multi-volume Wired Tiger)',
    retry: 'How many times to retry starting or unlocking mongodb (default: 720)',
    interval: 'Interval (in seconds) to wait when retrying (default: 5)',
    user: 'Mongo user',
    password: 'Mongo password',
    port: 'Mongo port',
    host: 'Mongo host',
    server_selection_timeout: 'Timeout in seconds while choosing a server to connect to (default 30)',
    wait_queue_timeout: 'Timeout in seconds while waiting for a connection in the pool (default 1)',
    connect_timeout: 'Timeout in seconds to wait for a socket to connect (default 5)',
    socket_timeout: 'Timeout in seconds to wait for an operation to execute on a socket (default 5)'
  }
end
name() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 61
def name
  "Mongo"
end

Private Instance Methods

client_options() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 145
def client_options
  {
    connect: :direct,
    user: options.user,
    password: options.password,
    server_selection_timeout: options.server_selection_timeout.to_i,
    wait_queue_timeout: options.wait_queue_timeout.to_i,
    connect_timeout: options.connect_timeout.to_i,
    socket_timeout: options.socket_timeout.to_i
  }
end
lock_mongo() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 131
def lock_mongo
  logger.info "Locking mongo"
  client.command(fsync: 1, lock: true)
end
primary?() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 98
def primary?
  if @primary.nil?
    @primary = client.command(isMaster: 1).first['ismaster']
  end
  @primary
end
safe_to_operate?() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 81
def safe_to_operate?
  # we check for strict equality with booleans here, because nil means an
  # error occurred while checking, and it is unsafe to operate
  return true if (primary? == false) or (standalone? == true)
  logger.error "This appears to be a primary member, refusing to operate"
  false
end
standalone?() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 105
def standalone?
  # this will raise an error on a non-RS mongod
  client.command(replSetGetStatus: 1)
  false
rescue
  true
end
start_mongo() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 126
def start_mongo
  logger.info "Starting mongodb via '#{options[:command]}'"
  system options[:command]
end
stop_mongo() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 113
def stop_mongo
  logger.info 'Stopping mongodb'
  begin
    # this will always raise an exception after it completes
    client.command shutdown: 1
  rescue Mongo::Error::SocketError => e
    logger.debug "Received expected socket error after shutting down"
  end

  # we need a new connection now since the server has shut down
  @client = nil
end
unlock_mongo() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 136
def unlock_mongo
  logger.info "Unlocking mongo"
  client.database['$cmd.sys.unlock'].find().read
end
unlock_or_start_mongo() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 67
def unlock_or_start_mongo
  (options.retry.to_i + 1).times do
    if wired_tiger?
      return if options.shutdown && carefully('start mongo') { start_mongo }
    else
      return if carefully('unlock mongo') { unlock_mongo }
    end

    # otherwise we failed
    logger.warn "Failed to start MongoDB, retrying in #{options.interval} seconds"
    sleep options.interval.to_i
  end
end
wired_tiger?() click to toggle source
# File lib/plugins/mongo_plugin.rb, line 89
def wired_tiger?
  if @wired_tiger.nil?
    @wired_tiger = carefully 'detect mongodb\'s storage engine' do
      client.command(serverStatus: 1).first.has_key? WIRED_TIGER_KEY
    end
  end
  @wired_tiger
end