Quantcast
Channel: Programming – PMA Media Group
Viewing all articles
Browse latest Browse all 10

Setting PowerDNS To Ignore Records For Downed Web Sites

$
0
0

If you are using PowerDNS for round robin on multiple websites, you can set it up so that it will return only the records for sites that are up. I set up a Ruby daemon to monitor sites and connect to the PowerDNS MySQL table used by PowerDNS on Rails. You can use any language or system you like. It just needs to be able to access your PowerDNS database.

First add the following line to /etc/powerdns/pdns.conf:

 gmysql-any-query=select content,ttl,prio,type,domain_id,name from records where name='%s' and (prio<>-1 or prio is null)

Thats the trickiest part. If you mess up on the sql query, PowerDNS may not return any results for your domain.
Then restart pdns. I use CentOS so I type

service pdns restart

Now you just need a daemon to monitor your websites. Something like the following might work for you:

#!/usr/bin/env ruby
require 'net/http'
require 'rubygems'
require 'activerecord'

SITE_ADDRESSES = %w( www.yourdomain.com www.example.com )
SITE_THAT_IS_ALWAYS_UP = "" # some well known site that is always up

class Record < ActiveRecord::Base
  ActiveRecord::Base.establish_connection(:adapter => "mysql",
    :encoding => "utf8", :database => "powerdns_production",
    :username => "your_mysql_username", :password => "your_secret_password_here",
    :host => "ns1.your_isp.com")
  set_inheritance_column :ruby_type
end

$running = true

def signal_trap_exit(signal_name)
  puts "#{Time.now} received #{signal_name} signal"
  $running = false
end

our_exit_signals = ["TERM", "INT", "KILL", "HUP"]
for exit_signal_name in our_exit_signals
  Signal.trap(exit_signal_name, "signal_trap_exit('#{exit_signal_name}')")
end

def check_internet
  begin
    Timeout::timeout(5) do
      Net::HTTP.get_response(SITE_THAT_IS_ALWAYS_UP, "/", 80) do |response|
        return response.code.match(/2|3\d{2}/)
      end
    end
  rescue => e
    puts "#{Time.now} Error connecting to internet: #{e}"
    return false
  end
end

def get_site_ip_addresses
  begin
    Record.find(:all, :conditions => ["type = ? and name in (?)", "A", SITE_ADDRESSES])
  rescue => e
    puts "#{Time.now} Error finding all records: #{e}"
    return []
  end
end

def make_inactive(ip_record)
  Record.update_all("prio=-1", "name='#{ip_record.name}' and content='#{ip_record.content}'")
end

def make_active(ip_record)
  Record.update_all("prio=1", "name='#{ip_record.name}' and content='#{ip_record.content}'")
end

while($running) do
  get_site_ip_addresses.each do |ip_address|
    begin
      Timeout::timeout(5) do
        Net::HTTP.get_response(ip_address.content.to_s, "/", 80) do |response|
          puts "#{Time.now} Response code for #{ip_address.content.to_s}: #{response.code}"
          make_active(ip_address) if ip_address.prio == -1
        end
      end
    rescue => e
      puts "#{Time.now} Error connecting to #{ip_address.content.to_s}: #{e}"
      if check_internet
        make_inactive(ip_address) unless ip_address.prio == -1
      end
    end
  end
 
  sleep 15 if $running
end

Viewing all articles
Browse latest Browse all 10

Trending Articles