Revision d3509e63
Added by Lukas Zapletal over 10 years ago
config/settings.yml.example | ||
---|---|---|
# valid providers:
|
||
# nsupdate
|
||
# nsupdate_gss (for GSS-TSIG support)
|
||
# virsh (simple implementation for libvirt)
|
||
:dns_provider: nsupdate
|
||
#:dns_key: /etc/rndc.key
|
||
# use this setting if you are managing a dns server which is not localhost though this proxy
|
||
... | ... | |
|
||
# Enable DHCP management
|
||
:dhcp: false
|
||
# The vendor can be either isc or native_ms
|
||
# valid vendors:
|
||
# - isc
|
||
# - native_ms (Microsoft native implementation)
|
||
# - virsh (simple implementation for libvirt)
|
||
:dhcp_vendor: isc
|
||
# dhcp_subnets is a Native MS implementation setting. It restricts the subnets queried to a
|
||
# subset, so as to reduce the query time.
|
||
... | ... | |
#:dhcp_key_name: secret_key_name
|
||
#:dhcp_key_secret: secret_key
|
||
|
||
# shared options for virsh DNS/DHCP provider
|
||
:virsh_network: default
|
||
|
||
# enable PuppetCA management
|
||
:puppetca: false
|
||
#:ssldir: /var/lib/puppet/ssl
|
lib/dhcp_api.rb | ||
---|---|---|
when "native_ms"
|
||
require 'proxy/dhcp/server/native_ms'
|
||
@server = Proxy::DHCP::NativeMS.new(:server => SETTINGS.dhcp_server ? SETTINGS.dhcp_server : "127.0.0.1")
|
||
when "virsh"
|
||
require 'proxy/dhcp/server/virsh'
|
||
@server = Proxy::DHCP::Virsh.new(:virsh_network => SETTINGS.virsh_network)
|
||
else
|
||
log_halt 400, "Unrecognized or missing DHCP vendor type: #{SETTINGS.dhcp_vendor.nil? ? "MISSING" : SETTINGS.dhcp_vendor}"
|
||
end
|
lib/dns_api.rb | ||
---|---|---|
:tsig_keytab => SETTINGS.dns_tsig_keytab,
|
||
:tsig_principal => SETTINGS.dns_tsig_principal
|
||
))
|
||
when "virsh"
|
||
require 'proxy/dns/virsh'
|
||
@server = Proxy::DNS::Virsh.new(opts.merge(
|
||
:virsh_network => SETTINGS.virsh_network
|
||
))
|
||
else
|
||
log_halt 400, "Unrecognized or missing DNS provider: #{SETTINGS.dns_provider || "MISSING"}"
|
||
end
|
lib/proxy/dhcp/server/virsh.rb | ||
---|---|---|
require 'proxy/virsh'
|
||
require 'ipaddr'
|
||
|
||
module Proxy::DHCP
|
||
class Virsh < Server
|
||
include Proxy::Virsh
|
||
|
||
def initialize options
|
||
@network = options[:virsh_network]
|
||
raise "DNS virsh provider needs 'virsh_network' option" unless network
|
||
super(options)
|
||
end
|
||
|
||
# we support only one subnet
|
||
def loadSubnets
|
||
super
|
||
begin
|
||
doc = REXML::Document.new xml = dump_xml
|
||
doc.elements.each("network/ip") do |e|
|
||
next if e.attributes["family"] == "ipv6"
|
||
netmask = e.attributes["netmask"]
|
||
gateway = e.attributes["address"]
|
||
network = IPAddr.new(gateway).mask(netmask).to_s
|
||
subnet = Proxy::DHCP::Subnet.new(self, network, netmask)
|
||
end
|
||
rescue Exception => e
|
||
msg = "DHCP virsh provider error: unable to retrive virsh info: #{e}"
|
||
logger.error msg
|
||
logger.debug xml if defined?(xml)
|
||
raise Proxy::DHCP::Error, msg
|
||
end
|
||
end
|
||
|
||
def loadSubnetData subnet
|
||
super(subnet)
|
||
begin
|
||
doc = REXML::Document.new xml = dump_xml
|
||
REXML::XPath.each(doc, "//network/ip[not(@family) or @family='ipv4']/dhcp/host") do |e|
|
||
Proxy::DHCP::Record.new(:subnet => subnet,
|
||
:ip => e.attributes["ip"],
|
||
:mac => e.attributes["mac"])
|
||
end
|
||
rescue Exception => e
|
||
msg = "DHCP virsh provider error: unable to retrive virsh info: #{e}"
|
||
logger.error msg
|
||
logger.debug xml if defined?(xml)
|
||
raise Proxy::DHCP::Error, msg
|
||
end
|
||
end
|
||
|
||
def addRecord options={}
|
||
record = super(options)
|
||
virsh_update_dhcp 'add-last', record.mac, record.ip
|
||
record
|
||
end
|
||
|
||
def delRecord subnet, record
|
||
super(subnet, record)
|
||
virsh_update_dhcp 'delete', record.mac, record.ip
|
||
end
|
||
end
|
||
end
|
lib/proxy/dns/virsh.rb | ||
---|---|---|
require "proxy/dns"
|
||
require "proxy/virsh"
|
||
|
||
module Proxy::DNS
|
||
class Virsh < Record
|
||
include Proxy::Log
|
||
include Proxy::Util
|
||
include Proxy::Virsh
|
||
|
||
def initialize options = {}
|
||
@network = options[:virsh_network]
|
||
raise "DNS virsh provider needs 'virsh_network' option" unless network
|
||
super(options)
|
||
end
|
||
|
||
def create
|
||
if @type == 'A'
|
||
result = virsh_update_dns 'add-last', @fqdn, @value
|
||
if result =~ /^Updated/
|
||
return true
|
||
else
|
||
raise Proxy::DNS::Error.new("DNS update error: #{result}")
|
||
end
|
||
else
|
||
logger.warn "not creating #{@type} record for #{@fqdn} (unsupported)"
|
||
end
|
||
end
|
||
|
||
def remove
|
||
if @type == 'A'
|
||
result = virsh_update_dns 'delete', @fqdn, find_ip_for_host(@fqdn)
|
||
if result =~ /^Updated/
|
||
return true
|
||
else
|
||
raise Proxy::DNS::Error.new("DNS update error: #{result}")
|
||
end
|
||
else
|
||
logger.warn "not deleting #{@type} record for #{@fqdn} (unsupported)"
|
||
end
|
||
end
|
||
|
||
end
|
||
end
|
lib/proxy/virsh.rb | ||
---|---|---|
require 'rexml/document'
|
||
|
||
module Proxy::Virsh
|
||
include Proxy::Log
|
||
include Proxy::Util
|
||
|
||
attr_reader :network
|
||
|
||
def dump_xml
|
||
@xml_dump ||= virsh('net-dumpxml', network)
|
||
end
|
||
|
||
def find_ip_for_host host
|
||
doc = REXML::Document.new xml = dump_xml
|
||
doc.elements.each("network/dns/host/hostname") do |e|
|
||
if e.text == host
|
||
return e.parent.attributes["ip"]
|
||
end
|
||
end
|
||
raise Proxy::DNS::Error.new("Cannot find DNS entry for #{host}")
|
||
rescue Exception => e
|
||
msg = "DNS virsh provider error: unable to retrive virsh info: #{e}"
|
||
logger.error msg
|
||
logger.debug xml if defined?(xml)
|
||
raise Proxy::DNS::Error, msg
|
||
end
|
||
|
||
def virsh *params
|
||
unless sudo_cmd = which("sudo", "/usr/bin", "/usr/sbin")
|
||
raise "DNS virsh provider error: sudo binary was not found"
|
||
end
|
||
|
||
unless virsh_cmd = which("virsh", "/usr/bin", "/usr/sbin")
|
||
raise "DNS virsh provider error: virsh binary was not found"
|
||
end
|
||
|
||
logger.debug command = ([sudo_cmd, virsh_cmd] + params + ['2>&1']).join(' ')
|
||
stdout = `#{command}`
|
||
if $? == 0
|
||
return stdout
|
||
else
|
||
raise "DNS virsh provider error: virsh call failed (#{$?}) - #{stdout}"
|
||
end
|
||
end
|
||
|
||
def virsh_update_dns command, hostname, ip
|
||
hostname = escape_for_shell(hostname)
|
||
ip = escape_for_shell(ip)
|
||
net = escape_for_shell(network)
|
||
virsh "net-update", net, command, "dns-host",
|
||
"--xml", "'<host ip=\"#{ip}\"><hostname>#{hostname}</hostname></host>'",
|
||
"--live", "--config"
|
||
rescue Exception => e
|
||
raise Proxy::DNS::Error, "Failed to update DNS: #{e}"
|
||
end
|
||
|
||
def virsh_update_dhcp command, mac, ip
|
||
mac = escape_for_shell(mac)
|
||
ip = escape_for_shell(ip)
|
||
net = escape_for_shell(network)
|
||
virsh "net-update", net, command, "ip-dhcp-host",
|
||
"--xml", "'<host mac=\"#{mac}\" ip=\"#{ip}\"/>'",
|
||
"--live", "--config"
|
||
rescue Exception => e
|
||
raise Proxy::DHCP::Error, "Failed to update DNS: #{e}"
|
||
end
|
||
end
|
Also available in: Unified diff
fixes #3943 - add simple virsh providers for libvirt DNS/DHCP