Class: Proxy::DHCP::KeaApi::Provider

Inherits:
Server
  • Object
show all
Defined in:
lib/smart_proxy_dhcp_kea_api/dhcp_kea_api_main.rb

Overview

The main provider class for the dhcp_kea_api module. This class inherits from the Foreman Smart Proxy's core DHCP::Server and implements the Kea-specific logic for adding and deleting DHCP reservations.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(subnet_service, client, free_ips) ⇒ Provider

Initialises the Kea API provider.

Parameters:

  • subnet_service (Proxy::DHCP::KeaApi::SubnetService)

    The service that manages the in-memory cache of DHCP data.

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

    The client for communicating with the Kea API.

  • free_ips (Proxy::DHCP::FreeIps)

    The service that tracks recently suggested IPs to prevent race conditions.



20
21
22
23
24
25
# File 'lib/smart_proxy_dhcp_kea_api/dhcp_kea_api_main.rb', line 20

def initialize(subnet_service, client, free_ips)
  @subnet_service = subnet_service
  @client = client
  subnet_service.load!
  super('localhost', nil, subnet_service, free_ips)
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client.



13
14
15
# File 'lib/smart_proxy_dhcp_kea_api/dhcp_kea_api_main.rb', line 13

def client
  @client
end

#subnet_serviceObject (readonly)

Returns the value of attribute subnet_service.



13
14
15
# File 'lib/smart_proxy_dhcp_kea_api/dhcp_kea_api_main.rb', line 13

def subnet_service
  @subnet_service
end

Instance Method Details

#add_record(options = {}) ⇒ Proxy::DHCP::Reservation

Creates a new DHCP reservation in Kea. This method orchestrates the process by first calling the parent class's add_record to perform initial validation and IP selection, then building the Kea-specific payload and sending it via the API client.

Examples:

Add a new DHCP reservation for a host

# Assume @provider is an instance of Proxy::DHCP::KeaApi::Provider
# and 'subnet' is a valid Proxy::DHCP::Subnet object for '192.168.1.0/24'
options = {
  'mac' => 'aa:bb:cc:dd:ee:ff',
  'hostname' => 'test-host.example.com',
  'ip' => '192.168.1.15',
  subnet: subnet,
  'nextServer' => 'tftp.example.com',
  'filename' => 'pxelinux.0',
  'routers' => ['192.168.1.1'],
  'ntp_servers' => ['192.168.1.254']
}

reservation = @provider.add_record(options)

reservation.mac      #=> "aa:bb:cc:dd:ee:ff"
reservation.ip       #=> "192.168.1.15"
reservation.name     #=> "test-host.example.com"
reservation.subnet   #=> #<Proxy::DHCP::Subnet ...>

Parameters:

  • options (Hash) (defaults to: {})

    A hash containing the details for the new reservation.

Options Hash (options):

  • 'mac' (String)

    The hardware address of the host.

  • 'ip' (String)

    The IP address to reserve.

  • 'hostname' (String)

    The hostname for the reservation.

  • :subnet (Proxy::DHCP::Subnet)

    The subnet object this reservation belongs to.

  • 'nextServer' (String, nil) — default: optional

    The IP of the TFTP boot server.

  • 'filename' (String, nil) — default: optional

    The boot filename (e.g., 'pxelinux.0').

Returns:

  • (Proxy::DHCP::Reservation)

    The created reservation object.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/smart_proxy_dhcp_kea_api/dhcp_kea_api_main.rb', line 62

def add_record(options = {})
  logger.debug "DHCP options received from Foreman: #{options.inspect}"
  record = super

  reservation_args = build_base_reservation_args(record)
  add_boot_and_server_options(reservation_args, options)

  option_data = build_option_data(options)
  reservation_args['option-data'] = option_data unless option_data.empty?

  @client.post_command('dhcp4', 'reservation-add', { reservation: reservation_args })
  subnet_service.add_host(record.subnet.network, record)

  logger.info "Successfully added reservation for MAC #{record.mac} and IP #{record.ip}"
  record
end

#del_record(record) ⇒ Proxy::DHCP::Reservation

Deletes a DHCP reservation from Kea.

Examples:

Delete a known DHCP reservation

# Assume @provider is an instance of Proxy::DHCP::KeaApi::Provider
mac_to_delete = 'aa:bb:cc:dd:ee:ff'

# First, find the reservation object
record_to_delete = @provider.get_record('mac' => mac_to_delete)

# Now, pass the entire object to del_record
if record_to_delete
  result = @provider.del_record(record_to_delete)
  #=> #<Proxy::DHCP::Reservation ...>
end

Parameters:

  • record (Proxy::DHCP::Reservation)

    The reservation object to be deleted. This object should be retrieved from the subnet service first.

Returns:

  • (Proxy::DHCP::Reservation)

    The object that was successfully deleted.

Raises:

  • (Proxy::DHCP::Error)

    if the corresponding Kea subnet-id cannot be found or the API call fails.



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/smart_proxy_dhcp_kea_api/dhcp_kea_api_main.rb', line 99

def del_record(record)
  logger.debug "Deleting record; #{record.inspect}"
  unless record.is_a?(::Proxy::DHCP::Reservation)
    logger.warn "Attempted to delete a record for MAC '#{record.mac}' but it is not a Reservation (actual type: #{record.class.name}). No action taken."
    return record
  end

  subnet_id = @subnet_service.kea_id_map[record.subnet.network]
  raise Proxy::DHCP::Error, "Unable to find Kea subnet-id for network #{record.subnet.network}" unless subnet_id

  # Construct the arguments for the 'reservation-del' command using the identifier triplet.
  args = {
    'subnet-id': subnet_id,
    'identifier-type': 'hw-address',
    'identifier' => record.mac
  }

  @client.post_command('dhcp4', 'reservation-del', args)
  subnet_service.delete_host(record)

  logger.info "Successfully deleted reservation for MAC #{record.mac} and IP #{record.ip}"
  record
end