Revision 168ee4e6
Added by Martin Matuska over 10 years ago
config/settings.yml.example | ||
---|---|---|
# Enable DNS management
|
||
:dns: false
|
||
# valid providers:
|
||
# dnscmd (Microsoft Windows native implementation)
|
||
# nsupdate
|
||
# nsupdate_gss (for GSS-TSIG support)
|
||
# virsh (simple implementation for libvirt)
|
lib/dns_api.rb | ||
---|---|---|
def dns_setup(opts)
|
||
raise "Smart Proxy is not configured to support DNS" unless SETTINGS.dns
|
||
case SETTINGS.dns_provider
|
||
when "dnscmd"
|
||
require 'proxy/dns/dnscmd'
|
||
@server = Proxy::DNS::Dnscmd.new(opts.merge(
|
||
:server => SETTINGS.dns_server,
|
||
:ttl => SETTINGS.dns_ttl
|
||
))
|
||
when "nsupdate"
|
||
require 'proxy/dns/nsupdate'
|
||
@server = Proxy::DNS::Nsupdate.new(opts.merge(
|
lib/proxy/dns/dnscmd.rb | ||
---|---|---|
require "proxy/dns"
|
||
require 'resolv'
|
||
require 'checks'
|
||
require 'rubygems' if USE_GEMS
|
||
require 'win32/open3'
|
||
|
||
module Proxy::DNS
|
||
class Dnscmd < Record
|
||
|
||
include Proxy::Log
|
||
include Proxy::Util
|
||
attr_reader :resolver
|
||
|
||
def initialize options = {}
|
||
super(options)
|
||
end
|
||
|
||
# create({ :fqdn => "node01.lab", :value => "192.168.100.2"}
|
||
# create({ :fqdn => "node01.lab", :value => "3.100.168.192.in-addr.arpa",
|
||
# :type => "PTR"}
|
||
def create
|
||
@resolver = Resolv::DNS.new(:nameserver => @server)
|
||
case @type
|
||
when "A"
|
||
if ip = dns_find(@fqdn)
|
||
raise(Proxy::DNS::Collision, "#{@fqdn} is already used by #{ip}") unless ip == @value
|
||
else
|
||
zone = @fqdn.sub(/[^.]+./,'')
|
||
msg = "Added DNS entry #{@fqdn} => #{@value}"
|
||
cmd = "/RecordAdd #{zone} #{@fqdn}. A #{@value}"
|
||
execute(cmd, msg)
|
||
end
|
||
when "PTR"
|
||
if name = dns_find(@value)
|
||
raise(Proxy::DNS::Collision, "#{@value} is already used by #{name}") unless name == @fqdn
|
||
else
|
||
# TODO: determine reverse zone names, #4025
|
||
return true
|
||
end
|
||
end
|
||
end
|
||
|
||
# remove({ :fqdn => "node01.lab", :value => "192.168.100.2"}
|
||
# remove({ :fqdn => "node01.lab", :value => "3.100.168.192.in-addr.arpa"}
|
||
def remove
|
||
case @type
|
||
when "A"
|
||
zone = @fqdn.sub(/[^.]+./,'')
|
||
msg = "Removed DNS entry #{@fqdn} => #{@value}"
|
||
cmd = "/RecordDelete #{zone} #{@fqdn}. A /f"
|
||
execute(cmd, msg)
|
||
when "PTR"
|
||
# TODO: determine reverse zone names, #4025
|
||
return true
|
||
end
|
||
end
|
||
|
||
private
|
||
|
||
def execute cmd, msg=nil, error_only=false
|
||
tsecs = 5
|
||
response = nil
|
||
interpreter = SETTINGS.x86_64 ? 'c:\windows\sysnative\cmd.exe' : 'c:\windows\system32\cmd.exe'
|
||
command = interpreter + ' /c c:\Windows\System32\dnscmd.exe ' + "#{@server} #{cmd}"
|
||
|
||
std_in = std_out = std_err = nil
|
||
begin
|
||
timeout(tsecs) do
|
||
logger.debug "executing: #{command}"
|
||
std_in, std_out, std_err = Open3.popen3(command)
|
||
response = std_out.readlines
|
||
response += std_err.readlines
|
||
end
|
||
rescue TimeoutError
|
||
raise Proxy::DNS::Error.new("dnscmd did not respond within #{tsecs} seconds")
|
||
ensure
|
||
std_in.close unless std_in.nil?
|
||
std_out.close unless std_in.nil?
|
||
std_err.close unless std_in.nil?
|
||
end
|
||
report msg, response, error_only
|
||
end
|
||
|
||
def report msg, response, error_only
|
||
if response.grep(/completed successfully/).empty?
|
||
logger.error "Dnscmd failed:\n" + response.join("\n")
|
||
msg.sub! /Removed/, "remove"
|
||
msg.sub! /Added/, "add"
|
||
match = ""
|
||
msg = "Failed to #{msg}"
|
||
raise Proxy::DNS::Error.new(msg)
|
||
else
|
||
logger.info msg unless error_only
|
||
end
|
||
rescue Proxy::DNS::Error
|
||
raise
|
||
rescue
|
||
logger.error "Dnscmd failed:\n" + (response.is_a?(Array) ? response.join("\n") : "Response was not an array! #{response}")
|
||
raise Proxy::DNS::Error.new("Unknown error while processing '#{msg}'")
|
||
end
|
||
|
||
def dns_find key
|
||
if match = key.match(/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/)
|
||
resolver.getname(match[1..4].reverse.join(".")).to_s
|
||
else
|
||
resolver.getaddress(key).to_s
|
||
end
|
||
rescue Resolv::ResolvError
|
||
false
|
||
end
|
||
end
|
||
end
|
Also available in: Unified diff
fixes #3991 - dnscmd provider for smart-proxy (Windows)