#!/usr/bin/ruby
#
# Dump all databases and slapd configurations (cn=config)
#
# Usage: puavo-dump-all-databases [options] --destination-directory DIR
#

require 'fileutils'
require 'optparse'
require 'puavo/execute'
require 'timeout'

options = { :verbose => false }

Timeout_seconds = 900

OptionParser.new do |opts|
  opts.banner = 'Usage: puavo-dump-all-databases [options]'

  opts.on('-d', '--destination-directory [DESTDIR]',
          'destination directory for dump files') do |dir|
    options[:destdir] = dir
  end

  opts.on('-v', '--[no-]verbose',
          'Run verbosely. Print STDERR of shell command (eg. slapcat)') do |v|
    options[:verbose] = v
  end

  opts.on_tail('-h', '--help', 'Show this message') do
    puts opts
    exit 0
  end
end.parse!

if options[:destdir].nil? then
  warn 'Missing argument --destination-directory'
  exit 1
end

FileUtils.mkdir_p(options[:destdir])

databases = []

Timeout::timeout(Timeout_seconds) do
  # Dump cn=config database
  config_ldif_path = File.join(options[:destdir], 'cn=config.ldif')
  puts "> dump cn=config to #{ config_ldif_path }"
  response = Puavo::Execute.run([
               '/usr/bin/timeout', '-k', '20', Timeout_seconds.to_s,
               '/usr/sbin/slapcat', '-b', 'cn=config', '-l', config_ldif_path ])
  warn response.stderr if options[:verbose]

  IO.readlines(config_ldif_path).each do |line|
    key, value = *line.split
    if key == 'olcSuffix:' then
      databases << value
    end
  end

  raise 'Can not find any databases' if databases.empty?
end

exitstatus = 0

# Backup all databases
databases.each do |ldap_base|
  begin
    Timeout::timeout(Timeout_seconds) do
      backup_file = File.join(options[:destdir], "#{ ldap_base }.ldif")

      puts "> dump #{ ldap_base } database to #{ backup_file } file"

      response = Puavo::Execute.run(
                   ['/usr/bin/timeout', '-k', '20', Timeout_seconds.to_s,
                    '/usr/sbin/slapcat',
                    '-b', ldap_base,
                    '-l', backup_file ])
      warn response.stderr if options[:verbose]
    end
  rescue Puavo::ExitStatusError => err
    warn ">> error when dumping #{ ldap_base }:"
    warn ">> slapcat returned error code #{ err.response.exit_status }"
    warn err.response.stderr unless err.response.stderr.empty?
    exitstatus = 1
  rescue StandardError => err
    warn ">> error when dumping #{ ldap_base }:"
    warn err.message
    exitstatus = 1
  end
end

exit(exitstatus)
