Class: Proxy::DHCP::KeaApi::SubnetService

Inherits:
SubnetService
  • Object
show all
Includes:
Log
Defined in:
lib/smart_proxy_dhcp_kea_api/dhcp_kea_api_subnet_service.rb

Overview

Manages the in-memory cache of DHCP data for the Kea provider.

This class is responsible for fetching all subnet, reservation, and lease information from the Kea API. It inherits from the core DHCP::SubnetService to get the underlying data structures (e.g. hashes for leases and hosts) and caching logic. Its primary public method, load!, orchestrates the population of this cache. It also maintains a mapping of Foreman subnet networks to their internal Kea API subnet IDs.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client, leases_by_ip, leases_by_mac, reservations_by_ip, reservations_by_mac, reservations_by_name) ⇒ void

Initialises the SubnetService.

rubocop:disable Metrics/ParameterLists

Parameters:

  • client (Proxy::DHCP::KeaApi::Client)

    The client for communicating with the Kea API.

  • leases_by_ip (Proxy::MemoryStore)

    A memory store for leases, passed to the parent class.

  • leases_by_mac (Proxy::MemoryStore)

    A memory store for leases, passed to the parent class.

  • reservations_by_ip (Proxy::MemoryStore)

    A memory store for reservations, passed to the parent class.

  • reservations_by_mac (Proxy::MemoryStore)

    A memory store for reservations, passed to the parent class.

  • reservations_by_name (Proxy::MemoryStore)

    A memory store for reservations, passed to the parent class.



36
37
38
39
40
41
42
# File 'lib/smart_proxy_dhcp_kea_api/dhcp_kea_api_subnet_service.rb', line 36

def initialize(client, leases_by_ip, leases_by_mac, reservations_by_ip, reservations_by_mac, reservations_by_name)
  @client = client
  @kea_id_map = {}
  # The `super` call initialises the parent `DHCP::SubnetService`, setting up all the
  # underlying data stores for caching subnets, leases, and reservations.
  super(leases_by_ip, leases_by_mac, reservations_by_ip, reservations_by_mac, reservations_by_name)
end

Instance Attribute Details

#kea_id_mapObject (readonly)

A hash mapping a subnet network address (e.g., "192.168.1.0") to its internal Kea API integer ID (e.g., 1). This is crucial for making API calls that require a subnet-id.



24
25
26
# File 'lib/smart_proxy_dhcp_kea_api/dhcp_kea_api_subnet_service.rb', line 24

def kea_id_map
  @kea_id_map
end

Instance Method Details

#load!true

The main entry point for loading all DHCP data from the Kea server. It ensures the cache is cleared before performing a fresh load.

rubocop:disable Naming/PredicateMethod

Returns:

  • (true)

    on success.

Raises:

  • (Proxy::DHCP::Error)

    if any part of the loading process fails.

See Also:



53
54
55
56
57
58
59
60
# File 'lib/smart_proxy_dhcp_kea_api/dhcp_kea_api_subnet_service.rb', line 53

def load!
  subnets.clear
  @kea_id_map.clear

  load_subnets_and_reservations_from_kea
  load_leases_from_kea
  true
end

#load_leases_from_keavoid

This method returns an undefined value.

Fetches all active leases from the Kea API for the subnets currently in the cache.

Raises:

  • (Proxy::DHCP::Error)

    if the API call fails.

See Also:



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/smart_proxy_dhcp_kea_api/dhcp_kea_api_subnet_service.rb', line 91

def load_leases_from_kea
  # This guard is necessary because the `lease4-get-all` command requires
  # a list of subnet IDs to query. If no subnets were loaded, we can't get leases.
  return if @kea_id_map.empty?

  response = @client.post_command('dhcp4', 'lease4-get-all', { subnets: @kea_id_map.values })
  return unless response && response['leases']

  response['leases'].each do |lease|
    ip = lease['ip-address']
    mac = lease['hw-address']
    # We must find the corresponding Subnet object from our cache to associate with the lease.
    subnet_obj = find_subnet(ip)
    unless subnet_obj
      logger.warn "Skipping lease for IP #{ip} as it does not belong to any known subnet."
      next
    end

    record = ::Proxy::DHCP::Lease.new(nil, ip, mac, subnet_obj, lease['cltt'], lease['expire'], 'active')
    # Add the lease to the parent class's cache.
    add_lease(subnet_obj.network, record)
  end
rescue Proxy::DHCP::Error => e
  logger.error "Failed to load all leases from Kea: #{e.message}"
  raise
end

#load_subnets_and_reservations_from_keavoid

This method returns an undefined value.

Fetches all subnets and their associated reservations from the Kea API. This single config-get call is the most efficient way to get all static configuration.

Raises:

  • (Proxy::DHCP::Error)

    if the API call fails.

  • (IPAddr::InvalidAddressError)

    if a subnet address from Kea is invalid.

See Also:



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/smart_proxy_dhcp_kea_api/dhcp_kea_api_subnet_service.rb', line 69

def load_subnets_and_reservations_from_kea
  config = @client.post_command('dhcp4', 'config-get')
  subnets_data = config&.dig('Dhcp4', 'subnet4')
  return unless subnets_data

  subnets_data.each do |subnet_data|
    process_subnet(subnet_data)
  end
  # The rescue blocks ensure that if any API or parsing error occurs, the provider
  # will fail to load, preventing the proxy from starting in a broken state.
rescue Proxy::DHCP::Error => e
  logger.error "Failed to load subnets and reservations from Kea: #{e.message}"
  raise
rescue IPAddr::InvalidAddressError => e
  logger.error "Failed to parse subnet from Kea, invalid address found: #{e.message}"
  raise
end