class Proxy::Ipam::IpCache
Class for managing temp in-memory cache to prevent same IP's being suggested in race conditions
Constants
- DEFAULT_CLEANUP_INTERVAL
Public Class Methods
new()
click to toggle source
# File lib/smart_proxy_ipam/ip_cache.rb, line 18 def initialize @m = Monitor.new init_cache start_cleanup_task end
Public Instance Methods
add(ip, mac, cidr, group_name)
click to toggle source
# File lib/smart_proxy_ipam/ip_cache.rb, line 57 def add(ip, mac, cidr, group_name) logger.debug("Adding IP '#{ip}' to cache for subnet '#{cidr}' in group '#{group_name}' for IPAM provider #{@provider.to_s}") @m.synchronize do mac_addr = mac.nil? || mac.empty? ? SecureRandom.uuid : mac group_hash = @ip_cache[group_name.to_sym] group_hash.each do |key, values| if values.keys.include? mac_addr.to_sym @ip_cache[group_name.to_sym][key].delete(mac_addr.to_sym) end @ip_cache[group_name.to_sym].delete(key) if @ip_cache[group_name.to_sym][key].nil? || @ip_cache[group_name.to_sym][key].empty? end if group_hash.key?(cidr.to_sym) @ip_cache[group_name.to_sym][cidr.to_sym][mac_addr.to_sym] = {ip: ip.to_s, timestamp: Time.now.to_s} else @ip_cache = @ip_cache.merge({group_name.to_sym => {cidr.to_sym => {mac_addr.to_sym => {ip: ip.to_s, timestamp: Time.now.to_s}}}}) end end end
get_cidr(group, cidr)
click to toggle source
# File lib/smart_proxy_ipam/ip_cache.rb, line 40 def get_cidr(group, cidr) @ip_cache[group.to_sym][cidr.to_sym] end
get_cleanup_interval()
click to toggle source
# File lib/smart_proxy_ipam/ip_cache.rb, line 48 def get_cleanup_interval DEFAULT_CLEANUP_INTERVAL end
get_group(group)
click to toggle source
# File lib/smart_proxy_ipam/ip_cache.rb, line 36 def get_group(group) @ip_cache[group.to_sym] end
get_ip(group_name, cidr, mac)
click to toggle source
# File lib/smart_proxy_ipam/ip_cache.rb, line 44 def get_ip(group_name, cidr, mac) @ip_cache[group_name.to_sym][cidr.to_sym][mac.to_sym][:ip] end
get_provider()
click to toggle source
# File lib/smart_proxy_ipam/ip_cache.rb, line 28 def get_provider @provider end
ip_exists(ip, cidr, group_name)
click to toggle source
# File lib/smart_proxy_ipam/ip_cache.rb, line 52 def ip_exists(ip, cidr, group_name) cidr_key = @ip_cache[group_name.to_sym][cidr.to_sym]&.to_s cidr_key.include?(ip.to_s) end
set_group(group, value)
click to toggle source
# File lib/smart_proxy_ipam/ip_cache.rb, line 32 def set_group(group, value) @ip_cache[group.to_sym] = value end
set_provider_name(provider)
click to toggle source
# File lib/smart_proxy_ipam/ip_cache.rb, line 24 def set_provider_name(provider) @provider = provider end
Private Instance Methods
init_cache()
click to toggle source
@ip_cache structure
Groups of subnets are cached under the External IPAM Group name. For example, “IPAM Group Name” would be the section name in phpIPAM. All IP's cached for subnets that do not have an External IPAM group specified, they are cached under the “” key. IP's are cached using one of two possible keys:
1). Mac Address 2). UUID (Used when Mac Address not specified)
{
"": { "100.55.55.0/24":{ "00:0a:95:9d:68:10": {"ip": "100.55.55.1", "timestamp": "2019-09-17 12:03:43 -D400"}, "906d8bdc-dcc0-4b59-92cb-665935e21662": {"ip": "100.55.55.2", "timestamp": "2019-09-17 11:43:22 -D400"} }, }, "IPAM Group Name": { "123.11.33.0/24":{ "00:0a:95:9d:68:33": {"ip": "123.11.33.1", "timestamp": "2019-09-17 12:04:43 -0400"}, "00:0a:95:9d:68:34": {"ip": "123.11.33.2", "timestamp": "2019-09-17 12:05:48 -0400"}, "00:0a:95:9d:68:35": {"ip": "123.11.33.3", "timestamp:: "2019-09-17 12:06:50 -0400"} } }, "Another IPAM Group": { "185.45.39.0/24":{ "00:0a:95:9d:68:55": {"ip": "185.45.39.1", "timestamp": "2019-09-17 12:04:43 -0400"}, "00:0a:95:9d:68:56": {"ip": "185.45.39.2", "timestamp": "2019-09-17 12:05:48 -0400"} } }
}
# File lib/smart_proxy_ipam/ip_cache.rb, line 116 def init_cache @m.synchronize do if @ip_cache && !@ip_cache.empty? logger.debug("Processing ip cache for IPAM provider #{@provider.to_s}") @ip_cache.each do |group, subnets| subnets.each do |cidr, macs| macs.each do |mac, ip| if Time.now - Time.parse(ip[:timestamp]) > DEFAULT_CLEANUP_INTERVAL @ip_cache[group][cidr].delete(mac) end end @ip_cache[group].delete(cidr) if @ip_cache[group][cidr].nil? || @ip_cache[group][cidr].empty? end end else logger.debug("Clearing ip cache for IPAM provider #{@provider.to_s}") @ip_cache = {'': {}} end end end
start_cleanup_task()
click to toggle source
# File lib/smart_proxy_ipam/ip_cache.rb, line 80 def start_cleanup_task logger.info("Starting ip cache maintenance for IPAM provider #{@provider.to_s}, used by /next_ip.") @timer_task = Concurrent::TimerTask.new(execution_interval: DEFAULT_CLEANUP_INTERVAL) { init_cache } @timer_task.execute end