set :source_machine, "mothercompiler"
set :install_dir,  "/opt/hypertable"
set :hypertable_version, "0.9.6.5"
set :default_pkg, "/tmp/hypertable-0.9.6.5-linux-x86_64.deb"
set :default_dfs, "hadoop"
set :default_config, "/opt/hypertable/dev-hypertable.cfg"

role :source, "mothercompiler"
role :master, "mothercompiler"
role :hyperspace, "mothercompiler", "motherlode000", "motherlode001"
role :slave,  "motherlode000", "motherlode001", "motherlode002", "motherlode003", "motherlode004", "
motherlode005", "motherlode006", "motherlode007", "motherlode008"
role :localhost, "mothercompiler"
role :thriftbroker,  "thrift001", "thrift002", "thrift003", "thrift004", "thrift005"
role :spare, "spare000", "spare001"

######################### END OF USER CONFIGURATION ############################
set :prompt_stop, 1
set :prompt_clean, 1

#ssh_options[:forward_agent] = true

def supported_pkgs
  {"bz2"=>1, "deb"=>1, "rpm"=>1}
end

def pkg_regex
  '.*\.(bz2|deb|rpm)$'
end

set(:pkg) do
  "#{default_pkg}"
end unless exists?(:pkg)

set(:dfs) do
  "#{default_dfs}"
end unless exists?(:dfs)

set(:config) do
  "#{default_config}"
end unless exists?(:config)

set :config_file, "#{config}".split('/')[-1]
set :config_option, \
    "--config=#{install_dir}/#{hypertable_version}/conf/#{config_file}"

set(:thriftbroker_args) do
  ""
end unless exists?(:thriftbroker_args)

 desc <<-DESC
    Copies config file to installation on localhost.
    This task runs on localhost and copies the config file specified \
    by the variable 'config' (default=#{config}) \
    to the installation directory specified by the variable 'install_dir' \
    (default-#{install_dir})
 DESC
task :copy_config_local, :roles => :localhost do
  run("rsync -e \"ssh -o StrictHostKeyChecking=no\" #{config} #{install_dir}/#{hypertable_version}/conf")
end
 
 desc <<-DESC
    Copies config file to installation on all servers in cluster.
    This task copies the dir\
    #{source_machine}:#{install_dir}/{#hypertable_version}/conf
    to all machines in the cluster    
 DESC
task :push_config_all do
   run <<-CMD
     rsync -av -e "ssh -o StrictHostKeyChecking=no" --exclude=log --exclude=run --exclude=demo --exclude=fs --exclude=hyperspace #{source_machine}:#{install_dir}/#{hypertable_version}/conf/ #{install_dir}/#{hypertable_version}/conf 
  CMD
end

 desc <<-DESC
    Copies config file to installation dir on localhost.\ 
    Then copies entire conf fir to all servers in cluster.
 DESC
task :push_config do
  copy_config_local
  push_config_all 
end

 desc <<-DESC
    rsyncs installation directory to cluster.  For each machine in the \
    cluster, his commannd  rsyncs the installation from the source \
    installation machine specified by the variable 'source_machine' \
    (default=#{source_machine})
 DESC
task :rsync do
  run <<-CMD
     rsync -av -e "ssh -o StrictHostKeyChecking=no" --exclude=log --exclude=run --exclude=demo --exclude=fs --exclude=conf --exclude=hyperspace #{source_machine}:#{install_dir}/#{hypertable_version} #{install_dir} &&
     rsync -av -e "ssh -o StrictHostKeyChecking=no" --exclude=log --exclude=run --exclude=demo --exclude=fs --exclude=hyperspace #{source_machine}:#{install_dir}/#{hypertable_version}/conf/ #{install_dir}/#{hypertable_version}/conf 
  CMD
end

 desc <<-DESC
    sets up the symbolic link 'current' in the installation area \
    to point to the directory of the current version
    (default=#{hypertable_version})
 DESC
task :set_current, :roles => [:master, :hyperspace, :slave, :thriftbroker, :spare] do
  run <<-CMD
   cd #{install_dir} &&
   rm -f current &&
   ln -s #{hypertable_version} current
  CMD
end

 desc <<-DESC
   Distributes installation.  This task rsyncs everything under\
   #{source_machine}:#{install_dir}/#{hypertable_version} to #{install_dir}\
   on all machines in the cluster
 DESC
task :dist do
  transaction do
    rsync
  end
end

 desc <<-DESC
   Alias for install_package command 
 DESC
task :install_pkg do
  install_package
end

 desc <<-DESC
    rsyncs binary packages and installs on each machine in the cluster
 DESC
task :install_package, :roles => [:master, :hyperspace, :slave, :thriftbroker, :spare] do
  pkg_basename = File.basename(pkg)
  pkg_basename =~ /#{pkg_regex}/
  pkg_type = $1
  
  if (!supported_pkgs.has_key?(pkg_type))
    raise "Package file #{pkg} is of unsupported type. Expected one of #{supported_pkgs.keys.inspect}"
  end
  if (/-#{hypertable_version}-/ =~ pkg_basename).nil?
    raise "Package #{pkg} doesn't match version #{hypertable_version}"
  end

  run("rsync -e \"ssh -o StrictHostKeyChecking=no\" #{source_machine}:#{pkg} #{install_dir}/")
   
  if (pkg_type == "deb")
    run("dpkg -i #{install_dir}/#{pkg_basename} && rm #{install_dir}/#{pkg_basename}") 
  elsif (pkg_type == "rpm")
    run("rpm -ivh --replacepkgs --nomd5 #{install_dir}/#{pkg_basename} && rm #{install_dir}/#{pkg_basename}")
  else
    ext_index = pkg_basename.index(".tar.bz2")
    if ext_index.nil?
      raise "Package #{pkg} is not a .tar.bz2 archive"
    end
    dir_basename = pkg_basename[0..ext_index-1]
    run("tar -xjv -f #{install_dir}/#{pkg_basename} -C #{install_dir}")
    run("mv #{install_dir}/#{dir_basename}/opt/hypertable/#{hypertable_version} #{install_dir}");
    run("/bin/rm -rf #{install_dir}/#{dir_basename}");
  end
end

 desc <<-DESC
    fhsize's the installations
 DESC
task :fhsize do
  transaction do 
    run <<-CMD
      #{install_dir}/#{hypertable_version}/bin/fhsize.sh
    CMD
  end
end

 desc <<-DESC
    Upgrades installation.  Checks upgrade, fhsizes if needed 
    then copies hyperspace and the rangeserver
    state in the run/ directory to new installation
 DESC
task :upgrade do 
  transaction do
    qualify_upgrade
    upgrade_all
    set_current
  end
end

 desc <<-DESC
   Verify that upgrade is OK.
 DESC
task :qualify_upgrade, :roles => :source do
  run <<-CMD
    #{install_dir}/#{hypertable_version}/bin/upgrade-ok.sh \
        #{install_dir}/current #{hypertable_version}
  CMD
end

 desc <<-DESC
    Upgrades (copies or uses previous symlink) for "hyperspace", "conf", "run", "log" 
    and "fs" dirs from the current installation to
    installation specified by the hypertable_version
    (#{hypertable_version})
DESC
task :upgrade_all, :roles => [:master, :hyperspace, :slave, :thriftbroker, :spare] do
  run <<-CMD
    #{install_dir}/#{hypertable_version}/bin/upgrade.sh \
        #{install_dir}/current #{hypertable_version}
  CMD
end

desc "Starts all processes."
task :start do
  transaction do
    start_hyperspace
    start_master
    start_slaves
    start_master_thriftbroker
  end
end

desc "Starts hyperspace processes."
task :start_hyperspace, :roles => :hyperspace do
  run <<-CMD
   #{install_dir}/current/bin/start-hyperspace.sh \
      #{config_option}
  CMD
end

desc "Starts master processes."
task :start_master, :roles => :master do
  run <<-CMD
   #{install_dir}/current/bin/start-dfsbroker.sh #{dfs} \
      #{config_option} &&
   #{install_dir}/current/bin/start-master.sh #{config_option} &&
   #{install_dir}/current/bin/start-monitoring.sh
  CMD
end

desc "Starts monitoring server."
task :start_monitoring, :roles => :master do
  #{install_dir}/current/bin/start-monitoring.sh
end

desc "Starts ThriftBroker on master."
task :start_master_thriftbroker, :roles => :master do
  run <<-CMD
   #{install_dir}/current/bin/start-thriftbroker.sh \
      #{config_option} #{thriftbroker_args}
  CMD
end

desc "Starts slave processes."
task :start_slaves, :roles => :slave do
  run <<-CMD
   #{install_dir}/current/bin/random-wait.sh 5 &&
   #{install_dir}/current/bin/start-dfsbroker.sh #{dfs} \
      #{config_option} &&
   #{install_dir}/current/bin/start-rangeserver.sh \
      #{config_option} &&
   #{install_dir}/current/bin/start-thriftbroker.sh \
      #{config_option} #{thriftbroker_args}
  CMD
end

desc "Starts ThriftBroker processes."
task :start_thriftbrokers, :roles => :thriftbroker do
  run <<-CMD
   #{install_dir}/current/bin/random-wait.sh 5 &&
   #{install_dir}/current/bin/start-dfsbroker.sh #{dfs} \
      #{config_option} &&
   #{install_dir}/current/bin/start-thriftbroker.sh \
      #{config_option} #{thriftbroker_args}
  CMD
end


desc "Starts DFS brokers."
task :start_dfsbrokers, :roles => [:master, :slave] do
  run "#{install_dir}/current/bin/start-dfsbroker.sh #{dfs} \
      #{config_option}"
end

desc "Stops all servers."
task :stop do
   
  if (prompt_stop == 1)
    puts "This will STOP ALL SERVERS in the Hypertable instance with MASTER='#{roles[:master].first}'. Proceed? ('yes' to proceed)"
    value = STDIN.gets.chomp rescue nil
    exit unless value == "yes"
  end
 
  transaction do
    stop_master
    stop_slaves
    stop_hyperspace
    stop_dfsbrokers
  end
end

desc "Stops DFS brokers."
task :stop_dfsbrokers, :roles => [:master, :slave] do
  run <<-CMD
  #{install_dir}/current/bin/stop-servers.sh
  CMD
end

desc "Stops slave processes."
task :stop_slaves, :roles => :slave do
  run <<-CMD
  #{install_dir}/current/bin/stop-servers.sh --no-hyperspace --no-master --no-dfsbroker
  CMD
end

desc "Stops master processes."
task :stop_master, :roles => :master do
  run <<-CMD
  #{install_dir}/current/bin/stop-servers.sh --no-hyperspace --no-rangeserver --no-dfsbroker &&
  #{install_dir}/current/bin/stop-monitoring.sh
  CMD
end

desc "Stops monitoring server."
task :stop_monitoring, :roles => :master do
  #{install_dir}/current/bin/stop-monitoring.sh
end

desc "Stops hyperspace processes."
task :stop_hyperspace, :roles => :hyperspace do
  run <<-CMD 
  #{install_dir}/current/bin/stop-hyperspace.sh
  CMD
end

desc "Stops ThriftBroker processes."
task :stop_thriftbrokers, :roles => :thriftbroker do
  run <<-CMD 
  #{install_dir}/current/bin/stop-servers.sh --no-hyperspace --no-master --no-rangeserver
  CMD
end

desc "Destroys the database, removing all tables."
task :cleandb do
  
  if prompt_clean == 1
    puts "This will DELETE ALL DATA stored in the Hypertable instance with MASTER='#{roles[:master].first}'. ARE YOU SURE you want to proceed? ('Yes' to proceed)"
    value = STDIN.gets.chomp rescue nil
    exit unless value == "Yes"
  end

  transaction do
    clean_master
    clean_hyperspace
    clean_slaves
  end  
end

desc "Cleans master state but not hyperspace."
task :clean_master, :roles => :master do
  run <<-CMD
   #{install_dir}/current/bin/start-dfsbroker.sh #{dfs} \
      #{config_option} && \
   #{install_dir}/current/bin/clean-database.sh #{config_option} && \ 
   #{install_dir}/current/bin/stop-monitoring.sh ;
  CMD
end

desc "Cleans hyperspace."
task :clean_hyperspace, :roles => :hyperspace do
  run <<-CMD
   #{install_dir}/current/bin/clean-hyperspace.sh
  CMD
end

desc "Cleans rangeservers and master state but not hyperspace."
task :clean_slaves, :roles => :slave do
  run <<-CMD
   #{install_dir}/current/bin/stop-servers.sh --no-hyperspace --no-master &&
   rm -rf #{install_dir}/current/run/*
  CMD
end

desc "Reports status for all processes."
task :status do
  transaction do
    dfs_status
    master_status
    hyperspace_status
    rangeserver_status
  end
end

desc "Get status for dfs processes."
task :dfs_status, :roles => [:master, :slave] do
  run <<-CMD
   #{install_dir}/current/bin/ht serverup dfsbroker
  CMD
end

desc "Get status for Hypertable.Master process."
task :master_status, :roles => [:master] do
  run <<-CMD
   #{install_dir}/current/bin/ht serverup master
  CMD
end

desc "Get status for Hyperspace.Master process."
task :hyperspace_status, :roles => [:hyperspace] do
  srand
  sleep(rand(4))
  run <<-CMD
   #{install_dir}/current/bin/ht serverup hyperspace
  CMD
end

desc "Get status for rangeserver processes."
task :rangeserver_status, :roles => [:slave] do
  run <<-CMD
   #{install_dir}/current/bin/ht serverup rangeserver
  CMD
end

set :default_dumpfile, "/tmp/rsdump.txt"

set(:dumpfile) do
  "#{default_dumpfile}"
end unless exists?(:dumpfile)

desc "Run dump command on each rangeserver"
task :rangeserver_dump, :roles => [:slave] do
  run <<-CMD
   echo "dump NOKEYS '#{dumpfile}';" | #{install_dir}/current/bin/ht ht_rsclient --batch #{config_option}
  CMD
end
