Skip to content

Commit

Permalink
Host creation working
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Kelly committed Oct 30, 2010
1 parent bd7e92c commit db7eb55
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 75 deletions.
1 change: 1 addition & 0 deletions app/models/netdb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class Netdb < ActiveRecord::Base
belongs_to :vendor
belongs_to :servertype
has_many :subnets, :foreign_key => "dhcp_id"
has_one :domain, :foreign_key => "dns_id"

validates_uniqueness_of :name
validates_presence_of :vendor_id, :servertype_id
Expand Down
18 changes: 18 additions & 0 deletions app/views/domains/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<% form_for @domain do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :fullname %><br />
<%= f.text_field :fullname %>
</p>
<p>
<%= f.label :dns_id %><br />
<%= f.collection_select :dns_id, Netdb.servertype_name_is("DNS"), :id, :name %>
</p>
<%= render :partial => "common_parameters/parameters", :locals => { :f => f, :type => :domain_parameters } %>

<p><%= f.submit "Submit" %></p>
<% end %>
9 changes: 9 additions & 0 deletions db/migrate/20101015100000_add_dns_column.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class AddDnsColumn < ActiveRecord::Migration
def self.up
add_column :domains, :dns_id, :integer
end

def self.down
remove_column :domains, :dns_id
end
end
2 changes: 1 addition & 1 deletion lib/netdb_manager.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Patch the ActionController with a alias_method_chain that loads our modifications to the models
require 'netdb_manager/action_controller_ext'
require_dependency 'netdb_manager/action_controller_ext'

ActionController::Base.prepend_view_path(File.join(File.dirname(__FILE__), '..', 'app', 'views'))

Expand Down
6 changes: 4 additions & 2 deletions lib/netdb_manager/action_controller_ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ module NetdbManager

module ActionControllerExtensions
def self.included(base) #:nodoc:
require 'resolv'
require 'ipaddr'

base.send :include, InstanceMethods
base.class_eval do
alias_method_chain :process, :netdb_support
Expand All @@ -11,13 +14,12 @@ def self.included(base) #:nodoc:

module InstanceMethods
def process_with_netdb_support *args
#require_dependency 'implementation/lib/dhcp'
require_dependency 'netdb_manager/host_ext'
require_dependency 'netdb_manager/user_ext'
require_dependency 'netdb_manager/subnet_ext'
require_dependency 'netdb_manager/domain_ext'
require_dependency 'netdb_manager/application_controller_ext'
require_dependency 'netdb_manager/hosts_controller_ext'
#require_dependency 'resolv'
process_without_netdb_support *args
end
end
Expand Down
14 changes: 0 additions & 14 deletions lib/netdb_manager/application_controller_ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,10 @@ def load_netdb_caches
raise RuntimeError "Unable to determine the user for this operation " unless @user
return true if SETTINGS[:unattended] and SETTINGS[:unattended] == false

# Fetch the list of server that are memcached
# NetdbManager.dhcp_servers = Rails.cache.fetch("dhcp_servers", :expires_in => NET_TTL){[]}.dup
# raise RuntimeException, "Unable to create DHCP memcache storage" unless NetdbManager.dhcp_servers

# Fetch the memcached servers
NetdbManager.dhcp = {}
for server in NetdbManager.dhcp_servers
NetdbManager.dhcp[server] = Rails.cache.fetch(server, :expires_in => NET_TTL){{}}.dup
raise RuntimeError, "Unable to retrieve server data for #{server}" if NetdbManager.dhcp[server].size == 0
end

# Fetch the user data mecache. This holds per-user data dependant on the server implementation
NetdbManager.user_data = Rails.cache.fetch("user_data", :expires_in => NET_TTL){{}}.dup
raise RuntimeError, "Unable to create user data cache storage" unless NetdbManager.user_data

# The DHCP instance needs access to the session as some of its DHCPServer implementations need to know about the user
#per_user_data = @user_cache[@user.login]
#@dhcp.personalise(per_user_data)
true
end

Expand Down
20 changes: 20 additions & 0 deletions lib/netdb_manager/domain_ext.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module NetdbManager
module DomainExtensions
def self.included(base) #:nodoc:
base.extend ClassMethods
base.send :include, InstanceMethods
base.class_eval do
belongs_to :dns, :class_name => 'Netdb'
end
end

module InstanceMethods

end

module ClassMethods

end
end
end
Domain.send :include, NetdbManager::DomainExtensions
112 changes: 73 additions & 39 deletions lib/netdb_manager/host_ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ def self.included(base)
# This implementation requires memcache
if [Rails.configuration.cache_store].flatten[0] == :mem_cache_store
require_dependency 'proxy_api'
require_dependency 'ipaddr'
else
message = "*********************************************************************\n" +
"DHCP and DNS management require that you install the memcache service\n" +
Expand All @@ -21,81 +20,116 @@ def self.included(base)
base.extend ClassMethods
base.send :include, InstanceMethods
base.class_eval do
after_validation :check_dns
after_save :update_netdbs
before_save :check_dns
after_save :update_netdbs
end
true
end

module InstanceMethods
def check_dns

continue = true
@resolver = Resolv::DNS.new :search => domain.name, :nameserver => domain.dns.address
if (@resolver.getaddress(name) rescue false)
errors.add_to_base "#{name} is already in use"
continue = false
end
if (@resolver.getname(ip) rescue false)
errors.add_to_base "#{ip} is already in use"
continue = false
end
continue
end

def save_netdb_caches

end

def delDHCP dhcp_server
status = log_transaction("Delete a DHCP reservation for #{name}/#{ip}", dhcp_server){
dhcp_server.delReservation self
def getDHCP
log_transaction("Query a DHCP reservation for #{name}/#{ip}", @dhcp){|dhcp|
dhcp.get subnet.number, mac
}
end

def delDHCP
status = log_transaction("Delete a DHCP reservation for #{name}/#{ip}", @dhcp){|dhcp|
dhcp.delete subnet.number, mac
}
return status unless sp_valid?
log_transaction("Delete a DHCP reservation for #{sp_name}/#{sp_ip}", dhcp_server){
dhcp_server.delReservation self, true
log_transaction("Delete a DHCP reservation for #{sp_name}/#{sp_ip}"){|dhcp|
dhcp.delete subnet.number, mac
}
end
# Updates the DHCP scope to add a reservation for this host
# [+dhcp_server+] : A DHCPServer object
# +returns+ : Boolean true on success
def setDHCP dhcp
status = log_transaction("Add a DHCP reservation for #{name}/#{ip}", dhcp_server){
# +returns+ : Boolean true on success
def setDHCP
status = log_transaction("Add a DHCP reservation for #{name}/#{ip}", @dhcp){|dhcp|
#nextserver needs to be an ip
dhcp.set subnet.number, mac, :nextserver => resolver.getaddress(puppetmaster).to_s, :name => name, :filename => media.bootfile, :ip => ip
#resolver = Resolv::DNS.new :search => domain.name, :nameserver => domain.dns.address
begin
puppet = @resolver.getaddress(puppetmaster =~ /\./ ? puppetmaster : "#{puppetmaster}.#{domain.name}").to_s
rescue Exception => e
@dhcp.error = e.message =~/no information for puppet/ ? "Unable to find the address of the puppetmaster in #{domain}" : e.message
return false
end
dhcp.set subnet.number, mac, :name => name, :filename => media.bootfile, :ip => ip, :nextserver => puppet
}
return status unless sp_valid?
log_transaction("Add a DHCP reservation for #{sp_name}/#{sp_ip}", dhcp_server){
log_transaction("Add a DHCP reservation for #{sp_name}/#{sp_ip}", @dhcp){|dhcp|
dhcp.set sp_subnet.number, sp_mac, :name => sp_name, :ip => sp_ip
}
end

def log_transaction message, server, &block
if server
logger.info "#{message}"
unless result = yield(block)
first, rest = message.match(/(\w*)(.*)/)[1,2]
message = "Failed to " + first.downcase + rest + ": #{server.message}"
errors.add_to_base server.message
logger.error message
end
result
else
errors.add_to_base("Access denied")
false

def to_arpa
ip.split(/\./).reverse.join(".") + ".in-addr.arpa"
end

# Updates the DNS zones to add a host
# +returns+ : Boolean true on success
def setDNS
log_transaction("Add the DNS records for #{name}/#{ip}", @dns){|dns|
dns.set(name, :value => ip, :type => "A") &&
dns.set(name, :value => to_arpa, :type => "PTR")
}
end
def log_transaction message, server
logger.info "#{message}"
unless result = yield(server)
first, rest = message.match(/(\w*)(.*)/)[1,2]
message = "Failed to " + first.downcase + rest + ": #{server.error}"
errors.add_to_base server.error
logger.error message
end
result
end

def update_netdbs
return true if RAILS_ENV == "test"
proxy_address = "http://#{subnet.dhcp.address}:4567"
@dhcp = ProxyAPI::DHCP.new(:url => proxy_address)
@dns = ProxyAPI::DNS.new(:url => proxy_address)

Rails.logger.debug "performing transactional update"
Rails.logger.debug "Performing transactional update"
begin
save_dhcp_data
# We have just tested the validity of the DNS operation in check_dns, so if the operation fails it is not due to a conflict
# Therefore the operation failed because the write failed and therefore we do not need to rollback the DNS operation
if setDNS
unless setDHCP
raise RuntimeError, @dhcp.error
end
else
raise RuntimeError, @dns.error
end
true
rescue => e
errors.add_to_base "Failed to update the network databases: " + e.message
raise ActiveRecord::Rollback
raise ActiveRecord::Rollback
false
end
end

def save_dhcp_data
dhcp = ProxyAPI::DHCP.new(:url => "http://#{subnet.dhcp.address}:4567")
if !dhcp.empty? and dhcp.subnets.include? subnet.number
setDHCP dhcp_server
else
raise RuntimeError, "Unable to find the subnet in the cache"
end
def sp_valid?
!sp_name.empty? and !sp_ip.empty? and !sp_mac.empty?
end

def validate
Expand Down
9 changes: 0 additions & 9 deletions lib/netdb_manager/hosts_controller_ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,11 @@ module HostsControllerExtensions
def self.included(base) #:nodoc:
base.send :include, InstanceMethods
base.class_eval do
before_filter :load_netdb_caches, :only => [:clone, :update, :create]
end

end

module InstanceMethods
def subnet_selected
subnet = Subnet.find(params[:subnet_id])

dhcp_server = DHCP.load_server subnet.dhcp
dhcp_server.loadSubnetData DHCP::Server[subnet.number] if dhcp_server.find_subnet(subnet.number).size == 0
NetdbManager.dhcp[subnet.dhcp.address] = dhcp_server
head :ok
end
end
end
end
Expand Down
34 changes: 24 additions & 10 deletions lib/proxy_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def strip_hash_name(hash, name = hash_name)
class Resource
attr_reader :url, :user, :password
include Util
attr_accessor :error

def initialize(args)
@user = args[:user] || "admin"
Expand All @@ -43,28 +44,41 @@ def path_prefix
self.class.to_s.gsub(/.*::/,"")
end

def parse response
if response == "null" or response.empty?
[]
def parse reply
if reply[0].code == "200"
if reply[1].size > 2
JSON.parse(reply[1])
else
true
end
else
JSON.parse(response)
@error = reply[1]
false
end
end

def _get_ path
@resource[URI.escape(path)].get.body
@resource[URI.escape(path)].get{|response, request, result| [result, response] }
rescue Exception => e
[ OpenStruct.new(:code => "500"), e.message]
end

def _post_ payload, path
@resource[path].post payload
@resource[path].post(payload){|response, request, result| [result, response] }
rescue Exception => e
[ OpenStruct.new(:code => "500"), e.message]
end

def _put_ payload, path
@resource[path].put payload
@resource[path].put(payload){|response, request, result| [result, response] }
rescue Exception => e
[ OpenStruct.new(:code => "500"), e.message]
end

def _delete_ path
@resource[path].delete
@resource[path].delete{|response, request, result| [result, response] }
rescue Exception => e
[ OpenStruct.new(:code => "500"), e.message]
end

def hash_name
Expand Down Expand Up @@ -107,8 +121,8 @@ def initialize args
super args
end

def set key, args
parse(_post_(args.merge(:fqdn => key), ""))
def set fqdn, args
parse(_post_(args.merge(:fqdn => fqdn), ""))
end

def delete key
Expand Down

0 comments on commit db7eb55

Please sign in to comment.