module Proxy::Ipam::IpamHelper

Module containing helper methods for use by all External IPAM provider implementations

Constants

ERRORS
MAX_IP_RETRIES

Public Instance Methods

cache_next_ip(ip_cache, ip, mac, cidr, subnet_id, group_name) click to toggle source

Checks the cache for existing ip, and returns it if it exists. If not exists, it will find a new ip (using find_new_ip), and it is added to the cache.

# File lib/smart_proxy_ipam/ipam_helper.rb, line 69
def cache_next_ip(ip_cache, ip, mac, cidr, subnet_id, group_name)
  group = group_name.nil? ? '' : group_name
  ip_cache.set_group(group, {}) if ip_cache.get_group(group).nil?
  subnet_hash = ip_cache.get_cidr(group, cidr)
  next_ip = nil

  if mac && subnet_hash&.key?(mac.to_sym)
    next_ip = ip_cache.get_ip(group, cidr, mac)
  else
    new_ip = ip
    ip_not_in_cache = subnet_hash.nil? ? true : !subnet_hash.to_s.include?(new_ip.to_s)

    if ip_not_in_cache
      next_ip = new_ip.to_s
      ip_cache.add(new_ip, mac, cidr, group)
    else
      next_ip = find_new_ip(ip_cache, subnet_id, new_ip, mac, cidr, group)
    end

    unless usable_ip(next_ip, cidr)
      return { error: "No free addresses found in subnet #{cidr}. Some available ip's may be cached. Try again in #{@ip_cache.get_cleanup_interval} seconds after cache is cleared." }
    end
  end

  next_ip
end
find_new_ip(ip_cache, subnet_id, ip, mac, cidr, group_name) click to toggle source

Called when next available IP from External IPAM has been cached by another user/host, but not actually persisted in External IPAM yet. This method will increment the IP, up to MAX_IP_RETRIES times, and check if it is available in External IPAM each iteration. It will return the original IP(the 'ip' param) if no new IP's are found after MAX_IP_RETRIES iterations.

# File lib/smart_proxy_ipam/ipam_helper.rb, line 41
def find_new_ip(ip_cache, subnet_id, ip, mac, cidr, group_name)
  found_ip = nil
  temp_ip = ip
  retry_count = 0

  loop do
    new_ip = increment_ip(temp_ip)
    ipam_ip = ip_exists?(new_ip, subnet_id, group_name)

    # If new IP doesn't exist in IPAM and not in the cache
    if !ipam_ip && !ip_cache.ip_exists(new_ip, cidr, group_name)
      found_ip = new_ip.to_s
      ip_cache.add(found_ip, mac, cidr, group_name)
      break
    end

    temp_ip = new_ip
    retry_count += 1
    break if retry_count >= MAX_IP_RETRIES
  end

  return ip if found_ip.nil?

  found_ip
end
get_request_group(params) click to toggle source
# File lib/smart_proxy_ipam/ipam_helper.rb, line 105
def get_request_group(params)
  group = params[:group] ? URI.escape(URI.decode(params[:group])) : nil
  halt 500, { error: errors[:groups_not_supported] }.to_json if group && !provider.groups_supported?
  group
end
increment_ip(ip) click to toggle source
# File lib/smart_proxy_ipam/ipam_helper.rb, line 96
def increment_ip(ip)
  IPAddr.new(ip.to_s).succ.to_s
end
provider() click to toggle source
# File lib/smart_proxy_ipam/ipam_helper.rb, line 26
def provider
  @provider ||=
    begin
      unless client.authenticated?
        halt 500, { error: 'Invalid credentials for External IPAM' }.to_json
      end
      client
    end
end
usable_ip(ip, cidr) click to toggle source
# File lib/smart_proxy_ipam/ipam_helper.rb, line 100
def usable_ip(ip, cidr)
  network = IPAddr.new(cidr)
  network.include?(IPAddr.new(ip)) && network.to_range.last != ip
end