Project

General

Profile

Download (4.76 KB) Statistics
| Branch: | Tag: | Revision:
module Proxy::DHCP
class SubnetService
include Proxy::Log

SEARCH_MASKS = (0..31).map { |bit| ~(1 << bit) }

attr_reader :m, :subnets, :leases_by_ip, :leases_by_mac, :reservations_by_ip, :reservations_by_mac, :reservations_by_name

def initialize(leases_by_ip, leases_by_mac, reservations_by_ip, reservations_by_mac, reservations_by_name, subnets = {})
@subnets = subnets
@leases_by_ip = leases_by_ip
@leases_by_mac = leases_by_mac
@reservations_by_ip = reservations_by_ip
@reservations_by_mac = reservations_by_mac
@reservations_by_name = reservations_by_name
@m = Monitor.new
end

def self.initialized_instance
new(::Proxy::MemoryStore.new, ::Proxy::MemoryStore.new,
::Proxy::MemoryStore.new, ::Proxy::MemoryStore.new, ::Proxy::MemoryStore.new)
end

def add_subnet(subnet)
m.synchronize do
key = subnet.ipaddr.to_i
raise Proxy::DHCP::Error, "Unable to add subnet #{subnet}" if subnets.key?(key)
logger.debug("Added a subnet: #{subnet.network}")
subnets[key] = subnet
subnet
end
end

def add_subnets(*subnets)
m.synchronize do
subnets.each { |s| add_subnet(s) }
subnets
end
end

def delete_subnet(subnet_address)
m.synchronize { subnets.delete(Proxy::DHCP.ipv4_to_i(subnet_address)) }
logger.debug("Deleted a subnet: #{subnet_address}")
end

def find_subnet(address)
m.synchronize do
ipv4_as_i = Proxy::DHCP.ipv4_to_i(address)
return subnets[ipv4_as_i] if subnets.key?(ipv4_as_i)
do_find_subnet(subnets, ipv4_as_i, address)
end
end

def do_find_subnet(all_subnets, address_as_i, address)
search_as_i = address_as_i
SEARCH_MASKS.each do |mask|
# zero consecutive least-significant bits until a matching prefix is found
search_as_i &= mask
if all_subnets.key?(search_as_i)
matching = all_subnets[search_as_i]
return matching if matching.netmask_to_i & address_as_i == search_as_i
end
end
nil
end
private :do_find_subnet

def all_subnets
m.synchronize { subnets.values }
end

def add_lease(subnet_address, record)
m.synchronize do
leases_by_ip[subnet_address, record.ip] = record
leases_by_mac[subnet_address, record.mac] = record
end
logger.debug("Added a lease record: #{record.ip}:#{record.mac}")
end

def add_host(subnet_address, record)
m.synchronize do
reservations_by_ip[subnet_address, record.ip] = record
reservations_by_mac[subnet_address, record.mac] = record
reservations_by_name[record.name] = record
end
logger.debug("Added a reservation: #{record.ip}:#{record.mac}:#{record.name}")
end

def delete_lease(record)
m.synchronize do
leases_by_ip.delete(record.subnet.network, record.ip)
leases_by_mac.delete(record.subnet.network, record.mac)
end
logger.debug("Deleted a lease record: #{record.ip}:#{record.mac}")
end

def delete_host(record)
m.synchronize do
reservations_by_ip.delete(record.subnet.network, record.ip)
reservations_by_mac.delete(record.subnet.network, record.mac)
reservations_by_name.delete(record.name)
end
logger.debug("Deleted a reservation: #{record.ip}:#{record.mac}:#{record.name}")
end

def find_lease_by_mac(subnet_address, mac_address)
m.synchronize { leases_by_mac[subnet_address, mac_address] }
end

def find_host_by_mac(subnet_address, mac_address)
m.synchronize { reservations_by_mac[subnet_address, mac_address] }
end

def find_lease_by_ip(subnet_address, ip_address)
m.synchronize { leases_by_ip[subnet_address, ip_address] }
end

def find_host_by_ip(subnet_address, ip_address)
m.synchronize { reservations_by_ip[subnet_address, ip_address] }
end

def find_host_by_hostname(hostname)
m.synchronize { reservations_by_name[hostname] }
end

def all_hosts(subnet_address = nil)
if subnet_address
return m.synchronize { reservations_by_ip[subnet_address] ? reservations_by_ip.values(subnet_address) : [] }
end
m.synchronize { reservations_by_ip.values }
end

def all_leases(subnet_address = nil)
if subnet_address
return m.synchronize { leases_by_ip[subnet_address] ? leases_by_ip.values(subnet_address) : [] }
end
m.synchronize { leases_by_ip.values }
end

def clear
m.synchronize do
subnets.clear
leases_by_ip.clear
leases_by_mac.clear
reservations_by_ip.clear
reservations_by_mac.clear
reservations_by_name.clear
end
end

def group_changes
m.synchronize { yield }
end
end
end
(7-7/7)