diff --git a/app/views/hosts/_unattended.html.erb b/app/views/hosts/_unattended.html.erb
index b3cfe9b..7647b86 100644
--- a/app/views/hosts/_unattended.html.erb
+++ b/app/views/hosts/_unattended.html.erb
@@ -5,6 +5,7 @@
Domain |
<%= f.collection_select :domain_id, Domain.all, :id, :to_label %> |
Subnet |
+ <% if sn = Subnet.first.dhcp; DHCP.cache_server @dhcp_servers, @dhcp, @user_data, dhcp; end -%>
<%= f.collection_select :subnet_id, Subnet.all, :id, :to_label %> |
IP |
<%= f.text_field :ip, :size => 16 %> |
@@ -48,6 +49,9 @@
<% end -%>
<% end -%>
+<%= observe_field(:host_subnet_id,
+ :url => { :action => :subnet_selected, :id => @host.id },
+ :with => :subnet_id)%>
<%= observe_field(:host_architecture_id,
:url => { :action => :architecture_selected, :id => @host.id },
diff --git a/init.rb b/init.rb
index e4d3f7b..51d35ab 100644
--- a/init.rb
+++ b/init.rb
@@ -1,3 +1,3 @@
#require_dependency File.join(File.dirname(__FILE__), "..", "..", "..", "config", "initializers", "foreman")
-require 'netdb_manager'
+require_dependency 'netdb_manager'
ActiveSupport::Dependencies.load_once_paths.delete lib_path
\ No newline at end of file
diff --git a/lib/dhcp.rb b/lib/dhcp.rb
deleted file mode 100644
index 89e27cc..0000000
--- a/lib/dhcp.rb
+++ /dev/null
@@ -1,281 +0,0 @@
-# A generic module for dhcp queries and commands
-# This is accessible on two levels:
-# A top-level hash based class which models all the subnets within the database
-# A second-level hash based class which represents a single DHCP server
-# The second level class is vendor specific Currently we support Microsoft Servers
-# via a web based gateway to the netsh.exe program and the InfoBlox DHCP server, which
-# is accessed directly
-# The DHCP entries are cached in a Memcache store and are shared among all users of the
-# system
-module DHCP
- # There has been a problem with the gateway transport or the data
- # we received does not make sense
- class DHCPError < RuntimeError; end
-
- # This class models the DHCP subnets within the organisation
- # After initialisation
- # dhcp = DHCP::Server.new(per_user_data_hash)
- # individual subnets can be referenced by
- # dhcp["172.29.216.0"]
- # and data is available via
- # mac = dhcp["172.29.216.0"]["172.29.216.12"]
- # A particular server can be found by
- # dhcp.serverFor["172.29.216.0"]
- class Dhcp < Hash
- attr_reader :user
- attr_accessor :denied
-
- def to_s
- "[" + self.keys.join(",") + "]"
- end
-
- def logger; RAILS_DEFAULT_LOGGER; end
-
- # Set the per_user_data in this DHCP instance and in all DHCPServer instances
- # [+per_user_data+] : Hash located in the user's session
- def personalise per_user_data
- for server in @servers.values
- server.personalise per_user_data
- end
- # Extract the DHCP object's per_user_data
- # This is a list of server addresses that have denied us access or are unavailable
- # Some dhcp server implementations may grant or deny access based on the user
- @denied = per_user_data[:denied] ||= []
- @user = per_user_data[:user]
- end
-
- # Populate my hash with {subnet_number => nil, subnet_number => nil, . . .}
- # These hashes will be filled in when the subnet is first accessed
- # [+per_user_data+] : Hash located in the user's session
- def initialize(per_user_data)
- super()
-
- @servers = {}
-
- personalise per_user_data
-
- @initialized = false
- for subnet in Subnet.all.map(&:number)
- self[subnet] = nil
- end
- @initialized = true
- flush
- end
-
- # A reference to a scope will instantiate the relevant DHCP server type and
- # link the server's scopes into this object
- #[+scope+] : String representation of the scope's IP address
- def [](scope)
- sn = Subnet.find_by_number(scope)
- dhcpServerAddress = sn.dhcp.address
- if self.has_key? scope and not @denied.include?(dhcpServerAddress) and @initialized and
- (self.fetch(scope).nil? or self.fetch(scope).size == 0)
- if @servers[dhcpServerAddress].nil?
- gateway = sn.domain.gateway # This will be nil if using InfoBlox
- vendor = sn.dhcp.vendor.name
- logger.debug "Cache miss for scope #{scope}"
- begin
- @servers[dhcpServerAddress] = eval("#{vendor}DHCPServer").new(dhcpServerAddress, self, gateway)
- rescue NameError
- raise "Failed to load DHCP vendor library. Class #{vendor}DHCPServer unavailable"
- end
- logger.debug "Loaded #{vendor} server #{dhcpServerAddress}"
- end
- server = @servers[dhcpServerAddress]
- # Do a cache probe to trigger a scope read
- server[scope]["0.0.0.0"]
- self[scope] = server[scope]
- flush
- end
- super # Finally call the Hash[] method to return the data that we have obtained
- end
-
- # This method returns the dhcp server that manages this subnet It also loads the server's scopes whilst
- # it does this and therefore reports the user's permissions on that server
- # [+number+] : String representation of the desired subnet numer
- def serverFor number
- # Trigger a cache probe to be sure that the server's data has been loaded
- self[number]
- sn = Subnet.find_by_number(number)
- @servers[sn.dhcp.address]
- end
-
- # Remove all cached ad uncached data for the subnet
- # [+subnet_number+] : String representation of the subnet's number
- def invalidate subnet_number
- logger.debug "Erasing DHCP data for #{subnet_number}"
- self[subnet_number] = nil
- server = serverFor subnet_number
- server[subnet_number] = nil
- flush
- end
-
- # Push our DHCP datastructure into the memcache for others to use
- def flush
- # Reserialize the DHCP data back into the cache
- # We have to use a dup or otherwise we are frozen.
- Rails.cache.write(:dhcp, self.dup, :expires_in => NET_TTL)
- end
- end # class Dhcp
-
- # This abstract class models a generic DHCP server
- # After initialisation
- # # dhcp = DHCPServer.new("172.29.216.40", parent DHCP object)
- # entries can be accessed by
- # mac = dhcp["172.29.216"]["172.29.205.26"]
- class DHCPServer < Hash
- @@Option = {"hostname" => {"code" => 12, "vendor" => false, "type" => "string"},\
- "TFTP boot server" => {"code" => 66, "vendor" => false, "type" => "string"},\
- "TFTP boot file" => {"code" => 67, "vendor" => false, "type" => "string"},\
- "root server ip address" => {"code" => 2, "vendor" => true, "type" => "ipaddress"},\
- "root path name" => {"code" => 4, "vendor" => true, "type" => "string"},\
- "install server ip address" => {"code" => 10, "vendor" => true, "type" => "ipaddress"},\
- "install server hostname" => {"code" => 11, "vendor" => true, "type" => "string"},\
- "install path" => {"code" => 12, "vendor" => true, "type" => "string"},\
- "sysid config file server" => {"code" => 13, "vendor" => true, "type" => "string"},\
- "jumpstart server" => {"code" => 14, "vendor" => true, "type" => "string"}\
- }
-
- @@debug = false
- attr_reader :dhcpServerAddress, :dhcp, :message
-
- def logger; RAILS_DEFAULT_LOGGER; end
- def netdbType; "DHCP"; end
-
- def personalise per_user_data
- # Override this function in your vendor implemetion to retrieve per_user data
- # See DHCP#personalise
- end
-
- def denied?
- @dhcp.denied.include? @dhcpServerAddress
- end
-
- def to_s
- "[" + self.keys.join(",") + "]"
- end
-
- # A reference to a scopeIpAddress will populate our hash
- #[+ScopeIpAddress+] : String containing the scope IP address
- def [](scopeIpAddress)
- raise DHCPError.new("The subnet #{scopeIpAddress} is not managed by #{@dhcpServerAddress}") if not self.has_key? scopeIpAddress and not denied?
- if self.has_key? scopeIpAddress and self.fetch(scopeIpAddress).nil? and not denied?
- self[scopeIpAddress] = {}
- if loadScopeData scopeIpAddress, self.fetch(scopeIpAddress)
- @dhcp.flush
- else
- @dhcp.denied << @dhcpServerAddress
- end
- end
- super # Finally call the Hash[] method to return the data that we have obtained
- end
-
- # Connect to the named DHCP server and populate our hash keys with the scope that the machine servers
- # [+dhcpServerAdress+] : String containing the DHCP server's IP addresss
- # [+dhcp+] : The parent Dhcp object
- def initialize(dhcpServerAddress, dhcp)
- super()
-
- @dhcpServerAddress = dhcpServerAddress
- @dhcp = dhcp
- # This variable contains the last error detected in the library
- @message = ""
-
- scopes = loadScopes unless denied?
- if scopes
- scopes.each do |scope|
- self[scope] = nil
- end
- else
- @dhcp.denied << @dhcpServerAddress
- end
- end
- # Remove a DHCP reservation
- # [+host+] : Host object
- # [+sp+] : Boolean which indicates whether we are dealing with the primary or service processor reservation
- def delReservation(host, sp = nil)
- scopeIpAddress = sp ? host.sp_subnet.number : host.subnet.number
- ip = sp ? host.sp_ip : host.ip
- # It is not an error to remove an entry that does not exist. After all, the reservation has been removed. :-)
- ((@message = "#{ip} is not registered in the DHCP") and return true) unless self[scopeIpAddress].has_key? ip
-
- if delRecordFor scopeIpAddress, ip
- # Reserialize the DHCP data back into the cache
- @dhcp.flush
- true
- else
- false
- end
- end
-
- # Create a DHCP reservation
- # [+host+] : Host object
- # [+sp+] : Boolean which indicates whether we are dealing with the primary or service processor reservation
- def setReservation(host, sp = nil)
- scopeIpAddress = sp ? host.sp_subnet.number : host.subnet.number
- ip = sp ? host.sp_ip : host.ip
- mac = sp ? host.sp_mac : host.mac
- name = sp ? host.sp_name : host.name
- (@message = "#{ip} already exists") and return false if self[scopeIpAddress].has_key? ip
-
- (@message = "Cannot determine the host's hardware or vendor class!") and return false \
- if (host.operatingsystem.name =~ /Solaris/ and host.architecture == "sparc") and (host.model.hclass.nil? or host.model.vclass.nil?)
-
- # The puppetmaster value refers to the source of puppet manifests at runtime
- # All boot servers are fully qualified in DHCP to work around some strange PXE card issues
- if setRecordFor scopeIpAddress, ip, name, mac, host.media, host.model, host.architecture
- # Reserialize the DHCP data back into the cache
- @dhcp.flush
- true
- else
- false
- end
- end
-
- # Access a hosts DHCP reservation and replace the mac value with a hash which also includes additional DHCP options
- # This is alpha level code and is only implemented for MSDHCP servers
- # [+ip+] : String containing the IP Address
- def getDetails ip
- raise RuntimeError.new("Running the virtual DHCPServer.getDetails method! Please provide vendor specific code")
- end
-
- protected
- # A DHCP entry may be just a mac or a hash of attributes
- def MAC scopeIpAddress, ip
- record = self[scopeIpAddress][ip]
- mac = record.is_a?(Hash) ? record[:mac] : record
- mac = mac.gsub(/:/,"")
- end
-
- private
- def loadScopes
- raise RuntimeError.new("Running the virtual DHCPServer.loadScopes method! Please provide vendor specific code")
- end
- # Load a scope's reservation records
- # [+scopeIpAddress+] : String containing the scope's IP address
- # [+scope+] : Hash into which we load the scop's data
- def loadScopeData scopeIpAddress, scope
- raise RuntimeError.new("Running the virtual DHCPServer.loadScopes method! Please provide vendor specific code")
- end
- # Add a DHCP entry
- # This method should be overriden in the subclass representing the type of DHCP server
- # [+scopeIpAddress+] : String containing the Scope's IP address
- # [+ip+] : String containing the IP for the record to be removed
- # [+hostname+] : String containing the host's name
- # [+mac+] : String containing the host's MAC address
- # [+media+] : Media object
- # [+model+] : String containing the host's model. Required for sparc machines as this is encoded in MS DHCP servers
- # [+architecture+] : String containing the host's architecture
- def setRecordFor(scopeIpAddress, ip, hostname, mac, media, model = nil, architecture = nil)
- raise RuntimeError.new("Running the virtual DHCPServer::setRecordFor method. Please provide vendor specific code")
- end
- # Delete the DHCP entry
- # This method should be overriden in the subclass representing the type of DHCP server
- # [+scopeIpAddress+] : String contaiing the Scope's IP address
- # [+ip+] : String containing the IP address
- def delRecordFor(scopeIpAddress, ip)
- raise RuntimeError.new("Running the virtual DHCPServer::delRecordFor method! Please provide vendor specific code")
- end
- end # class DHCPServer
-
-end # Module
diff --git a/lib/iscdhcp.rb b/lib/iscdhcp.rb
deleted file mode 100644
index 3d138b3..0000000
--- a/lib/iscdhcp.rb
+++ /dev/null
@@ -1,209 +0,0 @@
-# This class models a ISC DHCP server
-# After initialiasation, entries can be accessed by
-# dhcp = ISCServer.new("172.29.216.40", dhcp)
-# ip = dhcp["172.29.216"]["000c291c34f2"]
-class ISCDHCPServer < DHCP::DHCPServer
-
- # Delete the DHCP entry
- # This method is vendor specific and updates the DHCP server via the adaptor
- # [+scopeIpAddress+] : String containing the Scope's IP address
- # [+ip+] : String containing the IP for the record to be removed
- def delRecordFor(scopeIpAddress, ip)
- record = self[scopeIpAddress][ip]
- mac = record.is_a?(Hash) ? record[:mac] : record
- #mac = mac.gsub(/:/,"")
-
- omcmd "connect"
- omcmd "set hardware-address = #{mac}"
- omcmd "open"
- omcmd "remove"
- omcmd "disconnect"
-
- Util.syslog "#{@dhcp.user} removed DHCP reservation for #{ip}/#{mac}"
- self[scopeIpAddress].delete ip
- true
- end
- protected
-
- # Add a DHCP entry
- # This method is vendor specific and updates the dhcp entry via the adaptor
- # [+scopeIpAddress+] : String containing the Scope's IP address
- # [+ip+] : String containing the IP for the record to be removed
- # [+name+] : String containing the host's name
- # [+mac+] : String containing the host's MAC address
- # [+media+] : Media object
- # [+model+] : String containing the host's model Required for sparc machines as this is encoded in MS DHCP servers
- # [+architecture+] : Architecture object
- def setRecordFor(scopeIpAddress, ip, name, mac, media, model=nil, architecture = nil)
- (@message = "#{mac} already exists in scope #{scopeIpAddress}!" and return false) if self[scopeIpAddress].has_value? mac
-
- omcmd "connect"
- omcmd "set name = \"#{name}\""
- omcmd "set ip-address = #{ip}"
- omcmd "set hardware-address = #{mac}"
- omcmd "set hardware-type = 1" # This is ethernet
-
- self[scopeIpAddress][ip] = mac
-
- unless media.bootserver.nil? # We are done if this is a service processor reservation
- hexserv = Resolv.getaddress(media.bootserver).split(".").map{|i| "%02x" % i }.join(":")
-
-
- omcmd "set statements = \"filename = \\\"#{"kickstart/" + media.bootfile}\\\";\""
-
- if architecture.name == "sparc"
- #TODO: Add Sun vendor options
- end
- end
- omcmd "create"
- omcmd "disconnect"
- Util.syslog "#{@dhcp.user} created DHCP reservation for #{name} @ #{ip}/#{mac}"
- true
- end
- # Connect to the named DHCP server and populate our hash keys with the scope that the machine servers
- # [+dhcpServerAdress+] : String containing the DHCP server's IP addresss
- # [+dhcp+] : Dhcp object refering to parent
- def initialize(dhcpServerAddress, dhcp, option)
- # Connect to the named DHCP server and download its reservations
- @dhcpd_conf = nil
- @dhcpd_leased = nil
- @netmask = {}
- super(dhcpServerAddress, dhcp)
- # For now we make the assumption that this code runs on the dhcpd server
- end
-
- private
- def omcmd cmd, *args
- if cmd == "connect"
- @om = IO.popen("/usr/bin/omshell", "r+")
- server_addr = @dhcpServerAddress=~/^\d/ ? @dhcpServerAddress : Resolv.getaddress(@dhcpServerAddress)
- @om.puts "server #{server_addr}"
- @om.puts "connect"
- @om.puts "new host"
- elsif
- cmd == "disconnect"
- @om.close_write
- status = @om.readlines
- @om.close
- @om = nil # we cannot serialize an IO obejct, even if closed.
- status=~/can't/
- else
- @om.puts cmd
- end
- end
- def download_configuration
- if @dhcpd_conf
- system "scp -B -q #{@dhcpServerAddress}:#{@dhcpd_conf} /tmp" if not FileTest.file? "/tmp/dhcpd.conf" or File.mtime("/tmp/dhcpd.conf") > Time.now - 5.minutes
- else
- if system("scp -B -q #{@dhcpServerAddress}:/etc/dhcp3/dhcpd.conf /tmp")
- @dhcpd_conf = "/etc/dhcp3/dhcpd.conf"
- elsif system("scp -B -q #{@dhcpServerAddress}:/etc/dhcpd.conf /tmp")
- @dhcpd_conf = "/etc/dhcpd.conf"
- end
- end
- @message = "Unable to retrieve the DHCP configuration file from #{@dhcpServerAddress}" and return false unless FileTest.file? "/tmp/dhcpd.conf"
- if @dhcpd_leases
- system "scp -B -q #{@dhcpServerAddress}:#{@dhcpd_leases} /tmp" if not FileTest.file? "/tmp/dhclient.leases" or File.mtime("/tmp/dhclient.leases") > Time.now - 5.minutes
- else
- if system("scp -B -q #{@dhcpServerAddress}:/var/lib/dhcp3/dhcpd.leases /tmp")
- @dhcpd_leases = "/var/lib/dhcp3/dhcpd.leases"
- elsif system("scp -B -q #{@dhcpServerAddress}:/var/lib/dhcp/dhcpd.leases /tmp")
- @dhcpd_leases = "/var/lib/dhcp/dhcpd.leases"
- end
- end
- @@messsage = "Unable to retrieve the DHCP leases file from #{@dhcpServerAddress}" and return false unless FileTest.file? "/tmp/dhcpd.leases"
- true
- end
- # Enumerates the server's scopes
- # Returns a list of active scopes
- def loadScopes
- return false unless download_configuration
- entries = open("/tmp/dhcpd.conf"){|f|f.readlines}.delete_if{|l| not l=~/^\s*subnet/}.map{|l| l.match(/^\s*subnet\s+([\d\.]+)\s+netmask\s+([\d\.]+)/)[1,2]}
- scopes = []
- for subnet, netmask in entries
- @netmask[subnet] = netmask
- scopes << subnet
- end
- @message = "No scopes were found on #{@dnsServerAddress}" and return false if scopes.empty?
- scopes
- end
- # Load a scopes' reservation records
- # [+scopeIpAddress+] : String containing the scope's IP address
- # [+scope+] : Hash to be populated by the load operation
- def loadScopeData scopeIpAddress, scope
- logger.debug "Loading scope: " + scopeIpAddress
- return false unless download_configuration
- # Populate the hash that represent the scope reservations
- # Skip the first few lines returned by the server and gateway code
-
- # Clear the hash as we maybe reloading the cache
- scope.clear
-
- # Extract the data
- conf = open("/tmp/dhcpd.conf"){|f|f.readlines} + open("/tmp/dhcpd.leases"){|f|f.readlines}
- # Skip comment lines
- conf = conf.delete_if{|line| line=~/^\s*#/}.map{|l| l.chomp}.join("")
- conf.scan(/host\s+(\S+\s*\{[^}]+\})/) do |h|
- key, body = h[0].match(/^(\S+)\s*\{([^\}]+)/)[1,2]
- ip = mac = nil
- body.scan(/([^;]+);/) do |d|
- if match = d[0].match(/hardware\s+ethernet\s(\S+)/)
- mac = match[1]
- elsif match = d[0].match(/deleted\s(\S+)/)
- scope[key].delete if scope.has_key? key
- elsif match = d[0].match(/fixed-address\s(\S+)/)
- ip = match[1]
- if ip=~/^\D/
- ip = Resolv.getaddress ip rescue nil
- mac = nil if ip.nil?
- end
- end
- if mac and ip and Subnet.contains? scopeIpAddress, ip
- scope[ip] = mac
- mac = ip = nil
- end
- end
- end
- true
- end
-
-
- # Access a hosts DHCP reservation and replace the mac value with a hash which also includes additional DHCP options
- # This is alpha level code and is only implemented for MSDHCP servers
- # [+ip+] : String containing the IP Address
- def getDetails ip
- return nil
- scopeIpAddress = Subnet.find_subnet(ip).dhcp.address
- #TODO: integrate with GetDetails method
- logger.debug "Finding DHCP data for #{ip}"
- response = invoke "query reservation", nil, "CommandName=/ShowReservedOptionValue&ScopeIPAddress=#{scopeIpAddress}&ReservedIP=#{ip}"
- return if response[2] =~/not a reserved client/ # The machine had no reservation so do nothing
-
- scopeOptions = {}
- optionId = nil
- # Replace the key -> macaddress with key -> {:mac => value}
- mac = self[scopeIpAddress][ip]
- mac = mac[:mac] if mac.is_a?(Hash)
- self[scopeIpAddress][ip] = {:mac => mac}
- # Merge the scope options into each new reservation
- self[scopeIpAddress][ip].update scopeOptions
-
- # Add any host specific options replacing any scope level options
- response.each do |line|
- line.chomp
- break if line.match(/^Command completed/)
- if optionIdMatch = line.match(/OptionId : (\d+)/)
- optionId = optionIdMatch[1]
- next
- end
- # TODO: generalise for element values containing spaces
- if optionValue = line.match(/Option Element Value = (\S+)/) and optionValue = optionValue[1]
- self[scopeIpAddress][ip][optionId] = optionValue
- end
- end
- end
-
-end# class MSDHCPServer
-if __FILE__ == $0
- # TODO Generated stub
-end
diff --git a/lib/netdb_manager/action_controller_ext.rb b/lib/netdb_manager/action_controller_ext.rb
index cb5d5f5..fb4e24b 100644
--- a/lib/netdb_manager/action_controller_ext.rb
+++ b/lib/netdb_manager/action_controller_ext.rb
@@ -9,9 +9,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/application_controller_ext'
+ require_dependency 'netdb_manager/hosts_controller_ext'
process_without_netdb_support *args
end
end
diff --git a/lib/netdb_manager/application_controller_ext.rb b/lib/netdb_manager/application_controller_ext.rb
index 3ae645e..1dcaebd 100644
--- a/lib/netdb_manager/application_controller_ext.rb
+++ b/lib/netdb_manager/application_controller_ext.rb
@@ -5,30 +5,38 @@ module ApplicationControllerExtensions
def self.included(base) #:nodoc:
base.send :include, InstanceMethods
base.class_eval do
- before_filter :initialise_caches
+ # Setting the filter chain here will not work as it is too late. Set it in each controller individually.
+ #before_filter :load_netdb_caches
end
+ true
end
-
+
module InstanceMethods
- def initialise_caches
- return true unless @user
+ 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
-
- @dhcp = Rails.cache.fetch(:dhcp, :expires_in => NET_TTL){
- DHCP::Dhcp.new(session)
- }.dup # For some reason the object is frozen in this implementation of the cache!
- raise RuntimeException, "Unable to create DHCP memcache storage" unless @dhcp
-
- @user_cache = Rails.cache.fetch("user_cache", :expires_in => NET_TTL){
- {}
- }.dup # For some reason the object is frozen in this implementation of the cache!
- raise RuntimeException, "Unable to create password cache storage" unless @pass
+
+ # Fetch the list of server that are memcached
+ @dhcp_servers = Rails.cache.fetch("dhcp_servers", :expires_in => NET_TTL){[]}.dup
+ raise RuntimeException, "Unable to create DHCP memcache storage" unless @dhcp_servers
+
+ # Fetch the memcached servers
+ @dhcp = {}
+ for server in @dhcp_servers
+ @dhcp[server] = Rails.cache.fetch(server, :expires_in => NET_TTL){{}}.dup
+ raise RuntimeError, "Unable to retrieve server data for #{server}" if @dhcp[server].size == 0
+ end
+
+ # Fetch the user data mecache. This holds per-user data dependant on the server implementation
+ @user_cache = Rails.cache.fetch("user_cache", :expires_in => NET_TTL){{}}.dup
+ raise RuntimeError, "Unable to create user cache storage" unless @user_cache
# 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[login]
- @dhcp.personalise(per_user_data)
+ #per_user_data = @user_cache[@user.login]
+ #@dhcp.personalise(per_user_data)
true
- end
+ end
+
def save_network_data
return true if RAILS_ENV == "test"
if @dhcp
@@ -43,4 +51,4 @@ def save_network_data
end
end
end
-ApplicaitonController::Base.send :include, NetdbManager::ApplicationControllerExtensions
+ApplicationController.send :include, NetdbManager::ApplicationControllerExtensions
diff --git a/lib/netdb_manager/host_ext.rb b/lib/netdb_manager/host_ext.rb
index 6f63a7c..e6de164 100644
--- a/lib/netdb_manager/host_ext.rb
+++ b/lib/netdb_manager/host_ext.rb
@@ -3,8 +3,8 @@ module HostExtensions
def self.included(base)
# This implementation requires memcache
if [Rails.configuration.cache_store].flatten[0] == :mem_cache_store
- require_dependency 'dhcp'
- require_dependency 'iscdhcp'
+ require_dependency 'implementation/lib/dhcp'
+ #require_dependency 'iscdhcp'
require_dependency 'ipaddr'
include DHCP
else
@@ -18,16 +18,26 @@ def self.included(base)
puts message
exit
end
-
+
base.extend ClassMethods
base.send :include, InstanceMethods
base.class_eval do
- after_save :transactional_update
+ before_validation :load_netdb_caches
+ after_validation :check_dns
+ after_save :transactional_update, :save_netdb_caches
end
true
end
-
+
module InstanceMethods
+ def check_dns
+
+ end
+
+ def save_netdb_caches
+
+ end
+
def delDHCP dhcpServer
status = log_status("Delete a DHCP reservation for #{name}/#{ip}", dhcpServer){
dhcpServer.delReservation self
@@ -70,7 +80,6 @@ def transactional_update
puts "performing transactional update"
Rails.logger.debug "performing transactional update"
begin
- initialise_network_cache
save_network_data
true
rescue
diff --git a/lib/netdb_manager/hosts_controller_ext.rb b/lib/netdb_manager/hosts_controller_ext.rb
new file mode 100644
index 0000000..776b947
--- /dev/null
+++ b/lib/netdb_manager/hosts_controller_ext.rb
@@ -0,0 +1,20 @@
+module NetdbManager
+ module HostsControllerExtensions
+ def self.included(base) #:nodoc:
+ base.send :include, InstanceMethods
+ base.class_eval do
+ before_filter :load_netdb_caches
+ end
+
+ end
+
+ module InstanceMethods
+ def subnet_selected
+ dhcp = Subnet.find(params[:subnet_id]).dhcp
+
+ DHCP.cache_server @dhcp_servers, @dhcp, @user_cache, dhcp
+ end
+ end
+ end
+end
+HostsController.send :include, NetdbManager::HostsControllerExtensions
diff --git a/lib/netdb_manager/subnet_ext.rb b/lib/netdb_manager/subnet_ext.rb
new file mode 100644
index 0000000..28a6af6
--- /dev/null
+++ b/lib/netdb_manager/subnet_ext.rb
@@ -0,0 +1,30 @@
+module NetdbManager
+ module SubnetExtensions
+ def self.included(base) #:nodoc:
+ base.extend ClassMethods
+ base.send :include, InstanceMethods
+ base.class_eval do
+ belongs_to :dhcp, :class_name => 'Netdb'
+ validate_on_create :must_be_unique_per_site
+
+ end
+ end
+
+ module InstanceMethods
+ # Before we save a subnet ensure that we cannot find a subnet at our site with an identical name
+ def must_be_unique_per_site
+ if self.domain and self.domain.subnets
+ unless self.domain.subnets.find_by_name(self.name).nil?
+ errors.add_to_base "The name #{self.name} is already in use at #{self.domain.fullname}"
+ end
+ end
+ end
+
+ end
+
+ module ClassMethods
+
+ end
+ end
+end
+Subnet.send :include, NetdbManager::SubnetExtensions