module Cryptic
This allows redirecting user sites and querying them. You can pass the following options into the various methods:
:master_site - the site ID (aav, mca, etc.) of the master site :grok_master - the URL of the Grok master host
Copyright (C) 2013-2015 OL2, Inc. All Rights Reserved.
Constants
- BASE_PORT
- DEFAULT_OPTIONS
- SELECT_TIMEOUT
Default timeout for queries: 10 minutes
Public Instance Methods
dont_redirect_user_sites!(master_options = {})
click to toggle source
# File lib/cryptic/hoffa.rb, line 78 def dont_redirect_user_sites!(master_options = {}) @already_redirected_user_sites = true end
master_connection(options = {})
click to toggle source
# File lib/cryptic/hoffa.rb, line 70 def master_connection(options = {}) @master_conn ||= Mysql2::Client.new(DEFAULT_OPTIONS.merge(:host => master_host(options)).merge(options)) end
master_host(options = {})
click to toggle source
# File lib/cryptic/hoffa.rb, line 50 def master_host(options = {}) if options[:grok_master] options[:grok_master] else site = master_site(options) site ? "grok-master.#{site}.onlive.net" : "grok-master" end end
master_site(options = {})
click to toggle source
# File lib/cryptic/hoffa.rb, line 36 def master_site(options = {}) return ENV['CRYPTIC_MASTER_SITE'] if ENV['CRYPTIC_MASTER_SITE'] return options[:master_site] if options[:master_site] reference_site = options[:grok_master] || `hostname -f`.chomp onlive_user_site = reference_site.split(".")[1] if onlive_user_site && (onlive_user_site =~ /^[A-Za-z]{3}$/ || onlive_user_site == "prod") nil # Use local else "aav" end end
query_on_user_sites(query, sites = nil, master_options = {}, &block)
click to toggle source
# File lib/cryptic/hoffa.rb, line 140 def query_on_user_sites(query, sites = nil, master_options = {}, &block) redirect_user_sites!(sites, master_options) sites = user_sites(master_options) unless sites conns = sites.map { |site| user_site_connection(site, master_options) } results = {} threads = [] sites.zip(conns).each do |site, conn| t = nil begin t = Thread.new do # Global Interpreter Lock means we don't need to synchronize this results[site] = conn.query(query) block.call(results[site]) if block end rescue STDERR.puts "Errors on query for site #{site}:\n#{query}\n\n" STDERR.puts "Backtrace:\n#{$!.backtrace.join("\n")}\n" end threads.push(t) end threads.each(&:join) results end
redirect_user_sites!(sites = nil, master_options = {})
click to toggle source
# File lib/cryptic/hoffa.rb, line 82 def redirect_user_sites!(sites = nil, master_options = {}) return if @already_redirected_user_sites @already_redirected_user_sites = true sites = user_sites(master_options) unless sites user = `whoami`.chomp sites.each do |site| local_port = redirected_database_port_for_user_site(site, master_options) process = `pgrep -f #{local_port}` # TODO: use slaves where available (currently not for user sites) hostname = "grok.#{site}" ms = master_site(master_options) master_domain = ms ? "#{ms}.onlive.net" : "" cmd = "ssh -Nf -L#{local_port}:#{hostname}:3306 -o \"StrictHostKeyChecking no\" #{user}@shell.#{master_domain}" if process && !process.strip.empty? # Redirection already active process.strip.split("\n").each do |p| pid = p.to_i cur_cmd = `ps -p #{pid}`.split("\n")[1].split(/\s+/, 4)[3] # If this same command was issued then we're already redirecting the site to the right port number. # But the double-quotes go away in the ps output. if cur_cmd != cmd.gsub('"', "") Process.kill("INT", pid) STDERR.puts "Remapping port #{local_port} for site #{site}. Command: #{cmd} / Old Command: #{cur_cmd}" system(cmd) || raise("Failed port-map for site #{site}, port #{local_port}!") end end else STDERR.puts "Mapping port #{local_port} for site #{site}. Command: #{cmd}" system(cmd) || raise("Failed port-map for site #{site}, port #{local_port}!") end end end
redirected_database_port_for_user_site(site, master_options = {})
click to toggle source
# File lib/cryptic/hoffa.rb, line 120 def redirected_database_port_for_user_site(site, master_options = {}) user_sites(master_options) unless @user_sites index = @user_sites[site] raise "No index for site #{site.inspect}!" unless index BASE_PORT + index end
sites_in_maintenance()
click to toggle source
TODO: figure out how to do this outside prod
# File lib/cryptic/hoffa.rb, line 168 def sites_in_maintenance begin stat = `curl http://mastermon.mca.onlive.net/glustats/glustats.json 2>/dev/null` glustat = JSON.parse(stat) sites = glustat.keys sites = sites.select do |site| glustat[site].is_a?(Hash) && glustat[site]["drain_state"] == "drain" end return sites rescue STDERR.puts "Error querying sites in maint: #{$!.message}\n#{$!.backtrace.join "\n"}" return [] end end
slave_connection(options = {})
click to toggle source
# File lib/cryptic/hoffa.rb, line 74 def slave_connection(options = {}) @master_conn ||= Mysql2::Client.new(DEFAULT_OPTIONS.merge(:host => slave_host(options)).merge(options)) end
slave_host(options = {})
click to toggle source
# File lib/cryptic/hoffa.rb, line 60 def slave_host(options = {}) if options[:grok_slave] options[:grok_slave] else site = master_site(options) # There's not a separate "slave site" - just master & slave in the same master site. site ? "grokdbro.#{site}.onlive.net" : "grokdbro" end end
user_site_connection(site = nil, master_options = {})
click to toggle source
# File lib/cryptic/hoffa.rb, line 127 def user_site_connection(site = nil, master_options = {}) @user_site_connections ||= {} return @user_site_connections[site] if @user_site_connections[site] local_port = redirected_database_port_for_user_site(site) @user_site_connections[site] = Mysql2::Client.new DEFAULT_OPTIONS.merge(:port => local_port) @user_site_connections[site] end
user_sites(master_options = {})
click to toggle source
# File lib/cryptic/hoffa.rb, line 27 def user_sites(master_options = {}) return @user_sites.keys if @user_sites conn = slave_connection master_options # @user_sites maps site name to grok-master DB ID in the etl_control table. This ensures consistent local port mappings. @user_sites = {} conn.query("SELECT id, site FROM etl_control WHERE level = 'user' AND status = 'up'").each { |row| @user_sites[row["site"]] = row["id"] } @user_sites.keys end