Revision 8fcaacd6
Added by Marc Dequènes about 14 years ago
- ID 8fcaacd6b9f666dcfb94138e296b2c320fe9799f
bin/mapmaker | ||
---|---|---|
|
||
require 'cyborghood/cyborg'
|
||
require 'cyborghood/cyborg/server'
|
||
require 'cyborghood/services/dns'
|
||
|
||
|
||
module CyborgHood
|
||
... | ... | |
include CyborgServerInterface
|
||
include CyborgServerDefaultInterface
|
||
|
||
class DNS
|
||
class DNS < Services::DNS
|
||
include CyborgServerInterface
|
||
|
||
def zone_exists?(data)
|
||
pp data
|
||
"coucou"
|
||
export_parent_methods
|
||
unexport_method :zones
|
||
|
||
def test(data)
|
||
"coucou: " + data.inspect
|
||
end
|
||
|
||
class Zones
|
||
include CyborgServerInterface
|
||
|
||
def initialize
|
||
@dns = Services::DNS.new
|
||
end
|
||
|
||
def api_methods
|
||
@dns.zones
|
||
end
|
||
|
||
def method_missing(method_name, *args)
|
||
if api_methods.include?(method_name.to_s)
|
||
Zone.new(method_name.to_s)
|
||
else
|
||
super
|
||
end
|
||
end
|
||
|
||
class Zone < Services::Zone
|
||
include CyborgServerEmbededInterface
|
||
end
|
||
end
|
||
end
|
||
end
|
data/cyborghood/default_config/mapmaker.yaml | ||
---|---|---|
---
|
||
dns: {}
|
||
dns:
|
||
software: bind
|
data/cyborghood/schema/mapmaker.yaml | ||
---|---|---|
"dns":
|
||
type: map
|
||
mapping:
|
||
"software": {type: str, enum: [bind]}
|
||
"master_zone_pattern": {type: str, required: yes, name: MasterZonePattern}
|
lib/cyborghood/base/lang_additions.rb | ||
---|---|---|
def human_name
|
||
self.class.human_name
|
||
end
|
||
|
||
def singleton_class
|
||
class << self; self; end
|
||
end
|
||
end
|
||
|
||
class String
|
||
... | ... | |
Float self rescue false
|
||
end
|
||
end
|
||
|
lib/cyborghood/cyborg/interface.rb | ||
---|---|---|
module CyborgHood
|
||
module CyborgServerInterface
|
||
def self.included(base)
|
||
base.class_eval("include CyborgServerInterfaceBase")
|
||
base.class_eval("include Singleton")
|
||
end
|
||
end
|
||
|
||
module CyborgServerEmbededInterface
|
||
def self.included(base)
|
||
base.class_eval("include CyborgServerInterfaceBase")
|
||
base.export_parent_methods
|
||
end
|
||
end
|
||
|
||
module CyborgServerInterfaceBase
|
||
NODE_PATTERN = "([a-zA-Z0-9._]+(?:\/[a-zA-Z0-9._]+)*[?=]?)"
|
||
|
||
def self.included(base)
|
||
base.extend(ClassMethods)
|
||
end
|
||
|
||
... | ... | |
self.exported_methods ||= []
|
||
self.exported_methods += syms.collect{|m| m.to_s }
|
||
end
|
||
|
||
def unexport_method(syms)
|
||
syms = [syms] unless syms.is_a? Array
|
||
self.exported_methods ||= []
|
||
self.exported_methods -= syms.collect{|m| m.to_s }
|
||
end
|
||
|
||
def export_parent_methods
|
||
self.export_method self.superclass.public_instance_methods(false)
|
||
end
|
||
end
|
||
|
||
def initialize
|
||
def initialize(*args)
|
||
super(*args)
|
||
|
||
@config = Config.instance
|
||
|
||
self.class.exported_methods ||= []
|
||
... | ... | |
def api_klasses
|
||
list = self.class.constants.collect do |c|
|
||
cc = self.class.const_get(c)
|
||
(cc.class == Class and cc.ancestors.include? CyborgServerInterface) ? [c, cc] : nil
|
||
(cc.class == Class and cc.ancestors.include? CyborgHood::CyborgServerInterfaceBase) ? [c, cc] : nil
|
||
end.compact
|
||
Hash[list]
|
||
end
|
||
... | ... | |
end
|
||
|
||
def find_node_action(node_name)
|
||
next_node_name, other_nodes_names = node_name.split('.', 2)
|
||
next_node_name, other_nodes_names = node_name.split('/', 2)
|
||
|
||
next_node_klass = api_klasses[next_node_name]
|
||
# inner class or method ?
|
||
if next_node_klass.nil?
|
||
# method is declared ?
|
||
if api_methods.include? next_node_name
|
||
next_node_method = self.method(next_node_name)
|
||
return next_node_method if other_nodes_names.nil?
|
||
next_node = next_node_method.call
|
||
# final node ?
|
||
if other_nodes_names.nil?
|
||
# cannot use method(), as this method may not exist at all (but still
|
||
# be usuable through metaprogramming
|
||
return lambda do |*args|
|
||
r = self.send(next_node_name, *args)
|
||
# dynamic tree construction: method may return a node
|
||
if r.class.ancestors.include? CyborgHood::CyborgServerInterfaceBase
|
||
r.api_nodes
|
||
else
|
||
r
|
||
end
|
||
end
|
||
end
|
||
next_node = self.send(next_node_name)
|
||
else
|
||
# unknown method
|
||
return
|
||
end
|
||
else
|
||
next_node = next_node_klass.instance
|
||
# final node ?
|
||
return next_node.method('api_nodes') if other_nodes_names.nil?
|
||
end
|
||
|
||
next_node.find_node_action(other_nodes_names)
|
||
# search deeper
|
||
if next_node.class.ancestors.include? CyborgHood::CyborgServerInterfaceBase
|
||
next_node.find_node_action(other_nodes_names)
|
||
else
|
||
# it is not a node, so there are no children
|
||
return
|
||
end
|
||
end
|
||
|
||
def has_node?(cmd)
|
lib/cyborghood/cyborg/server.rb | ||
---|---|---|
MaxLineLength = 16*1024
|
||
|
||
EOD = "\033[0J"
|
||
NODE_PATTERN = /^([a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*[?=]?)(?: ([+?]+))?$/
|
||
COMMAND_PATTERN = "^#{CyborgServerInterfaceBase::NODE_PATTERN}(?: ([+?]+))?$"
|
||
|
||
def initialize(interface)
|
||
@interface = interface
|
||
... | ... | |
else
|
||
logger.debug "Received data [#{identifier}]: #{data}"
|
||
|
||
unless data =~ NODE_PATTERN
|
||
unless data =~ Regexp.new(COMMAND_PATTERN)
|
||
logger.error "Error [#{identifier}]: syntax error"
|
||
send_line "552 syntax error in command"
|
||
return
|
||
end
|
||
cmd = $1
|
||
flags = $2 || ""
|
||
pp "GROK"
|
||
pp cmd
|
||
pp flags
|
||
|
||
if flags.index '?'
|
||
send_line "250+ ok"
|
lib/cyborghood/services/dns.rb | ||
---|---|---|
|
||
require 'fileutils'
|
||
|
||
# ensure we can find the needed programs (should be handled somewhere else)
|
||
ENV['PATH'] = (ENV['PATH'].split(":") + ["/sbin", "/usr/sbin", "/usr/local/sbin"]).uniq.join(":")
|
||
|
||
module CyborgHood
|
||
module Services
|
||
class DNS
|
||
def initialize
|
||
@config = Config.instance
|
||
|
||
@zone_files_pattern = @config.dns.master_zone_pattern.gsub("#ZONE#", "*")
|
||
@zone_files_regex = Regexp.new("^" + @config.dns.master_zone_pattern.gsub("#ZONE#", "(.*)") + "$")
|
||
end
|
||
|
||
def zones(zone = nil)
|
||
if zone.nil?
|
||
Dir.glob(@zone_files_pattern).collect do |file|
|
||
$1 if file =~ @zone_files_regex
|
||
end
|
||
else
|
||
Zone.new(zone)
|
||
end
|
||
end
|
||
end
|
||
|
||
class Zone
|
||
attr_reader :zone
|
||
attr_accessor :content
|
||
|
||
... | ... | |
@content = nil
|
||
|
||
@filename = @config.dns.master_zone_pattern.gsub("#ZONE#", @zone)
|
||
|
||
# ensure we can find the needed programs (should be handled somewhere else)
|
||
ENV['PATH'] = (ENV['PATH'].split(":") + ["/sbin", "/usr/sbin", "/usr/local/sbin"]).uniq.join(":")
|
||
end
|
||
|
||
def read_zone
|
||
... | ... | |
end
|
||
|
||
def serial
|
||
case @config.dns.nameserver || :bind
|
||
when :bind
|
||
case @config.dns.software
|
||
when 'bind'
|
||
output = []
|
||
begin
|
||
IO.popen("named-checkzone -i none '#{@zone}' #{@filename}") do |fp|
|
||
output << fp.gets.chomp! until fp.eof?
|
||
end
|
||
rescue
|
||
raise CyberError.new(:unrecoverable, "services/dns", "zone serial for '#{@zone}' could not be found")
|
||
raise CyberError.new(:unrecoverable, "services/dns", "zone serial for '#{@zone}' could not be found (I/O error)")
|
||
end
|
||
raise CyberError.new(:unrecoverable, "services/dns", "zone serial for '#{@zone}' could not be found (#{output.first})") unless $?.success?
|
||
|
||
if $? == 0
|
||
serial = nil
|
||
... | ... | |
else
|
||
nil
|
||
end
|
||
else
|
||
# TODO: should be checked at startup time
|
||
raise CyberError.new(:unrecoverable, "services/dns", "erroneous configuration: unknown nameserver")
|
||
end
|
||
end
|
||
|
||
def check_zone_file(filename)
|
||
case @config.dns.nameserver || :bind
|
||
when :bind
|
||
case @config.dns.software
|
||
when 'bind'
|
||
output = []
|
||
begin
|
||
IO.popen("named-checkzone '#{@zone}' #{filename}") do |fp|
|
||
... | ... | |
else
|
||
return {:ok => false, :errors => messages}.to_ostruct
|
||
end
|
||
else
|
||
# TODO: should be checked at startup time
|
||
raise CyberError.new(:unrecoverable, "services/dns", "erroneous configuration: unknown nameserver")
|
||
end
|
||
end
|
||
|
Also available in: Unified diff
[evol] work on cyborg server protocol and API #7 (refs #31)