2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-05-09 10:10:09 +00:00

Fix Kea UEFI reservation boot policy

This commit is contained in:
Vinícius Ferrão
2026-04-28 03:03:40 -03:00
parent dd7efe5d93
commit 0f606615b3
12 changed files with 614 additions and 87 deletions
@@ -15,13 +15,37 @@ Use this matrix for:
* DDNS and service-management changes
* PXE, xNBA, or boot-policy changes
Acceptance Scope
----------------
The validation result for this matrix is scoped to DHCP backend behavior and
boot handoff:
* backend selection matches the platform policy
* generated backend configuration validates with the backend-native validator
* static reservations allocate correctly, including Kea reservations outside
``networks.dynamicrange``
* dynamic pools are emitted only by the DHCP server that owns the network
* the expected bootloader, node script, kernel, initrd, or root image artifacts
are offered and fetched for the row under test
* shell-oriented rows reach the expected xNBA or Genesis shell state
Failures after the expected boot artifacts have been delivered are image,
initrd, kernel, userspace, or packaging follow-up work. They must be tracked,
but they do not turn the DHCP backend acceptance row red unless the failure is
caused by DHCP policy, allocation, or boot option rendering.
Secure Boot is not part of this matrix. Secure OVMF builds such as
``OVMF_CODE.secboot.fd`` and ``OVMF_VARS.secboot.fd`` must be treated as
unsupported unless xCAT explicitly adds Secure Boot support.
Backend Policy
--------------
The default backend split is:
* EL9, Ubuntu 22.04 LTS, and older supported releases: ``ISC DHCP``
* EL10, Ubuntu 24.04 LTS, and newer supported releases: ``Kea``
* EL9, Ubuntu 20.04 LTS, and older supported releases: ``ISC DHCP``
* EL10, Ubuntu 22.04 LTS, and newer supported releases: ``Kea``
``site.dhcpbackend=auto`` must follow that rule. Explicit ``isc`` and ``kea``
overrides remain available for development and troubleshooting.
@@ -40,6 +64,8 @@ Run these checks for every DHCP backend change before live validation:
``require-client-classes``
* Kea 3.x output must use ``only-in-additional-list`` and
``evaluate-additional-classes``
* Kea UEFI x86_64 boot classes must cover PXE architecture ids ``0x0007``
and ``0x0009`` plus UEFI HTTP boot architecture id ``0x0010``
* backend-native configuration validation:
@@ -69,26 +95,100 @@ The following matrix is the default live validation gate for DHCP backend work.
- ``xNBA shell``
- ``makedhcp -n``; ``dhcpd -t``; reservation add/query/delete; DHCP/TFTP;
node-specific xNBA handoff; Genesis fetch
* - Ubuntu 22.04 LTS
* - Ubuntu 20.04 LTS
- ``x86_64``
- ``ISC``
- ``xNBA shell``
- ``makedhcp -n``; ``dhcpd -t``; reservation add/query/delete; DHCP/TFTP;
node-specific xNBA handoff; Genesis fetch
* - Ubuntu 22.04 LTS
- ``x86_64``
- ``Kea``
- ``xNBA shell`` and compute-image handoff
- ``makedhcp -n``; ``kea-dhcp4 -t``; reservation add/query/delete;
xNBA shell boot; compute-image boot artifact handoff through kernel,
initrd, and root image when image validation is in scope
* - EL10
- ``x86_64``
- ``Kea``
- ``xNBA shell`` and ``full netboot image``
- ``xNBA shell`` and compute-image handoff
- ``makedhcp -n``; ``kea-dhcp4 -t``; reservation add/query/delete;
xNBA shell boot; full compute-image boot through kernel, initrd, and
root image
xNBA shell boot; compute-image boot artifact handoff through kernel,
initrd, and root image when image validation is in scope
* - Ubuntu 24.04 LTS
- ``x86_64``
- ``Kea``
- ``xNBA shell`` and ``full netboot image``
- ``xNBA shell`` and compute-image handoff
- ``makedhcp -n``; ``kea-dhcp4 -t``; reservation add/query/delete;
xNBA shell boot; full compute-image boot through kernel, initrd, and
root image
xNBA shell boot; compute-image boot artifact handoff through kernel,
initrd, and root image when image validation is in scope
Kea Boot and Reservation Regression Matrix
------------------------------------------
Run this matrix whenever a change touches Kea boot policy, client
classification, address pools, or host reservations.
.. list-table::
:header-rows: 1
:widths: 20 18 62
* - Scenario
- Backend Scope
- Minimum Required Checks
* - BIOS PXE/xNBA
- ``ISC`` and ``Kea`` when touched
- DHCP offer for architecture ``0x0000``; expected BIOS loader
``pxelinux.0`` or ``xcat/xnba.kpxe``; xNBA second-stage URL when the
client returns with user-class ``xNBA``.
* - UEFI PXE architecture ``0x0007``
- ``Kea``
- Client matches ``xcat-uefi-x64``; offer includes ``xcat/xnba.efi``;
node-specific xNBA UEFI second-stage class returns the ``.uefi`` node
script URL.
* - UEFI PXE architecture ``0x0009``
- ``Kea``
- Same checks as ``0x0007``. This is the alternate x86_64 UEFI PXE
architecture id observed in the existing xCAT DHCP logic.
* - UEFI HTTP architecture ``0x0010``
- ``Kea``
- Client matches ``xcat-uefi-x64`` and the xNBA UEFI second-stage class;
validate the DHCP offer against real UEFI HTTP firmware or an
equivalent DHCP client fixture. The April 26, 2026 validation used a raw
DHCP fixture with option 93 set to ``0x0010`` and confirmed Kea offered
the reserved outside-pool address and ``xcat/xnba.efi`` without
``ALLOC_FAIL_NO_POOLS``.
* - Static reservation outside dynamic pool
- ``Kea``
- Node address is inside the Kea subnet and outside
``networks.dynamicrange``; generated reservation includes
``ip-address``; DHCP ACK uses the reserved address; Kea logs do not
contain ``ALLOC_FAIL_NO_POOLS``.
* - Static reservation inside dynamic pool
- ``Kea``
- Record the expected behavior explicitly. Current ``makedhcp`` treats
node IPs overlapping ``networks.dynamicrange`` as dynamic and does not
render a fixed ``ip-address`` reservation. Any change that supports
in-pool fixed reservations must add live allocation coverage.
* - Dynamic pool ownership in hierarchy
- ``Kea``
- When ``networks.dhcpserver`` is set, only the owning DHCP server renders
``networks.dynamicrange`` as Kea pools. Non-owning service nodes may
render the subnet for reservations and options, but must not render
duplicate dynamic pools.
* - Stateful netboot image
- ``ISC`` and ``Kea`` when touched
- DHCP/TFTP/HTTP handoff reaches kernel, initrd, root image, and the
expected xCAT node state.
* - Stateless netboot image
- ``ISC`` and ``Kea`` when touched
- DHCP/TFTP/HTTP handoff reaches the stateless image and validates
post-boot xCAT state.
* - ``ALLOC_FAIL_NO_POOLS`` regression
- ``Kea``
- Reproduce a node with static reservation and no usable dynamic pool;
confirm Kea still allocates the reserved address and no allocation
failure is logged.
Extended Architecture Matrix
----------------------------
@@ -109,9 +209,9 @@ paths.
* - EL10
- ``ppc64le``
- ``Kea``
- ``Genesis handoff``
- DHCP offer; boot file handoff; xCAT Genesis reachability; POWER boot-path
correctness
- ``POWER GRUB handoff``
- DHCP offer; boot file handoff; POWER boot-path correctness; Genesis
shell when Genesis payload validation is in scope
Current Lab Baseline
--------------------
@@ -125,76 +225,183 @@ Validation access should use the ``builder`` account and the
``id_ed25519_reposync`` SSH key. Avoid relying on ad-hoc root login or
one-off cloud-init keys when recording repeatable validation procedure.
Full Ubuntu 24.04 ``x86_64`` stateless KVM validation required Ubuntu
``genimage`` fixes for early BOOTIF handling and a lean initrd driver set.
Those image-generation fixes are tracked separately from the Kea DHCP backend
policy changes.
Known Exceptions
----------------
Known blockers do not remove the matrix requirement. They must be recorded
explicitly in the validation result.
explicitly in the validation result. A blocker only turns a DHCP acceptance row
red when the root cause is DHCP backend policy, allocation, or boot option
rendering.
Current exceptions:
* Ubuntu 22.04 LTS ISC OMAPI/``omshell`` host reservation updates are blocked by
issue ``#11``. The failure reproduces on upstream ``master`` and is not caused
by the Kea backend work.
* EL10 ``ppc64le`` Kea configuration and DHCP unit validation pass. Full POWER
image boot validation can still be blocked by a ``genesis.kernel.ppc64``
invalid-ELF issue unrelated to Kea. Initial triage showed the installed
``/tftpboot/xcat/genesis.kernel.ppc64`` is a PowerPC/OpenPOWER ELF, not an
``x86_64`` binary, and is the package payload from
``xCAT-genesis-base-ppc64-2.18.0-RC1`` built on
``xcat-dev-server-ppc.cluster.local`` on March 30, 2026. The likely change
area is the Genesis rebuild work merged before this PR, especially PR ``#8``
/ merge ``40a7e4c43`` and commits ``d691c5ccd`` (Genesis base source
package generation), ``4a1905171`` (ppc64le Genesis boot changes), and
``baa2380cd`` (moving the dracut call into the spec).
xCAT3 issue ``#11``. The failure reproduces on upstream ``master`` and is not
caused by the Kea backend work. ``site.dhcpbackend=auto`` therefore selects
Kea for Ubuntu 22.04 and newer releases; live Ubuntu 22.04 Kea validation
remains a follow-up matrix row.
* Ubuntu ``ppc64le`` package installation is missing required boot packages such
as ``goconserver``, ``grub2-xcat``, and ``xcat-genesis-base-ppc64``. This is
tracked by xCAT3 issue ``#13`` and is separate from Kea DHCP behavior.
Current PR Validation Snapshot
------------------------------
As of April 23, 2026, the ``kea-dhcp-backend`` PR has the following DHCP
backend validation result:
As of April 26, 2026, this PR has the following DHCP backend acceptance result
for the supported KVM rows. All rows in this table are green for the DHCP
backend scope described above.
.. list-table::
:header-rows: 1
:widths: 16 10 10 20 44
:widths: 16 10 12 18 12 32
* - Platform
- Arch
- Backend
- Boot Path
- Result
- Notes
* - EL9
- ``x86_64``
- ``ISC``
- BIOS PXE/xNBA
- Pass
- ``site.dhcpbackend=auto`` selected ``isc``; legacy DHCP unit subset
passed.
* - Ubuntu 22.04 LTS
- DHCP/TFTP, node-specific xNBA handoff, Genesis shell, and compute-image
validation passed.
* - EL9
- ``x86_64``
- ``ISC``
- Pass with known exception
- ``site.dhcpbackend=auto`` selected ``isc``; legacy DHCP unit subset
passed. OMAPI reservation updates remain tracked by issue ``#11``.
- UEFI PXE/xNBA
- Pass
- Non-Secure-Boot UEFI DHCP/TFTP, node-specific xNBA handoff, Genesis
shell, and compute-image validation passed.
* - EL9
- ``ppc64le``
- ``ISC``
- POWER GRUB/Genesis
- Pass
- DHCP/TFTP/GRUB handoff fetched ``genesis.kernel.ppc64`` and
``genesis.fs.ppc64.gz``; node reached the Genesis shell.
* - EL10
- ``x86_64``
- ``Kea 3.0.1``
- BIOS PXE/xNBA
- Pass
- Renderer emitted ``evaluate-additional-classes`` and
``only-in-additional-list``; ``kea-dhcp4 -t`` passed.
- Static reservation outside ``networks.dynamicrange`` allocated; no
``ALLOC_FAIL_NO_POOLS``; xNBA shell passed; regenerated compute-image
boot reached ``sshd`` with ``selinux=0`` in the command line.
* - Ubuntu 24.04 LTS
- ``x86_64``
- ``Kea 2.4.1``
- BIOS PXE/xNBA
- Pass
- Renderer emitted ``require-client-classes`` and ``only-if-required``;
full DHCP unit suite and ``kea-dhcp4 -t`` passed.
- Static reservation outside ``networks.dynamicrange`` allocated; no
``ALLOC_FAIL_NO_POOLS``; xNBA shell passed; compute-image boot fetched
``rootimg.cpio.gz`` and reached ``sshd`` with ``netdrivers=overlay``.
* - EL10
- ``x86_64``
- ``Kea 3.0.1``
- UEFI PXE/xNBA
- Pass
- Non-Secure-Boot UEFI path matched the Kea x86_64 UEFI boot policy;
regenerated compute-image boot reached ``sshd`` with ``selinux=0`` in
the command line.
* - EL10
- ``x86_64``
- ``Kea 3.0.1``
- UEFI HTTP arch ``0x0010``
- Pass
- Raw DHCP fixture on the KVM provisioning bridge sent option 93
``0x0010`` from the reserved outside-pool node MAC and received lease
``10.241.10.22`` with boot file ``xcat/xnba.efi``; no
``ALLOC_FAIL_NO_POOLS`` was observed. xCAT3 issue ``#17`` is closed as
completed.
* - Ubuntu 24.04 LTS
- ``x86_64``
- ``Kea 2.4.1``
- UEFI PXE/xNBA
- Pass
- Non-Secure-Boot UEFI path matched the Kea x86_64 UEFI boot policy;
xNBA shell passed; compute-image boot fetched ``rootimg.cpio.gz`` and
reached ``sshd`` with the separate Ubuntu ``genimage`` fixes applied.
* - EL10
- ``ppc64le``
- ``Kea 3.0.1``
- POWER GRUB/Genesis
- Pass
- Renderer emitted ``evaluate-additional-classes`` and
``only-in-additional-list``; full DHCP unit suite and ``kea-dhcp4 -t``
passed. Full image boot remains blocked after GRUB by the separate
Genesis ppc64 kernel issue described above.
- Static reservation outside ``networks.dynamicrange`` allocated; no
``ALLOC_FAIL_NO_POOLS``; TFTP/GRUB handoff passed; original EL10
``genesis.kernel.ppc64`` and ``genesis.fs.ppc64.gz`` reached xCAT
``shell`` state after replacing the broken ``grub2-xcat 1.0-3`` ppc
GRUB core/module tree with the coherent
``2.02-0.76.el7.1.snap201905160255`` tree. The remaining xCAT3 issue
``#16`` follow-up is package provenance for ``grub2-xcat``, not DHCP or
Genesis payload behavior.
* - Ubuntu 24.04 LTS
- ``ppc64le``
- ``Kea 2.4.1``
- POWER GRUB/Genesis
- Pass
- Static reservation outside ``networks.dynamicrange`` allocated; no
``ALLOC_FAIL_NO_POOLS``; DHCP/TFTP/GRUB handoff passed and the node
reached Genesis with the temporary EL9 ppc64le payload workaround.
Skipped Rows
------------
The following rows are intentionally not counted in the current PR acceptance
table:
.. list-table::
:header-rows: 1
:widths: 18 10 12 60
* - Platform
- Arch
- Backend
- Reason
* - Ubuntu 22.04 LTS
- ``x86_64``
- ``Kea``
- Skipped in this PR. Unit coverage now pins Ubuntu 22.04 to Kea by
default because ISC OMAPI/``omshell`` is blocked by xCAT3 issue ``#11``;
live KVM validation remains a follow-up row.
* - Ubuntu 22.04 LTS
- ``ppc64le``
- ``Kea``
- Skipped for the same Ubuntu 22.04 Kea follow-up validation reason as the
``x86_64`` row.
External Follow-up Tracking
---------------------------
These issues are outside the DHCP acceptance result but must be referenced when
reporting this validation run:
.. list-table::
:header-rows: 1
:widths: 12 22 66
* - Issue
- Area
- Impact
* - xCAT3 ``#13``
- Ubuntu ``ppc64le`` packages
- Missing ``goconserver``, ``grub2-xcat``, and
``xcat-genesis-base-ppc64`` block clean Ubuntu ppc64le package
installation.
* - xCAT3 ``#16``
- ``ppc64le`` GRUB package
- EL10 ppc64le fails with ``grub2-xcat 1.0-3`` because its POWER GRUB
core/module tree cannot load the ppc64le Genesis kernel. The live row is
green after hotpatching the TFTP GRUB tree to
``2.02-0.76.el7.1.snap201905160255`` while keeping the original EL10
Genesis payload.
Reporting Rule
--------------
@@ -7,7 +7,7 @@ Purpose
xCAT currently integrates DHCP through ISC DHCP. That behavior should remain the
default on platforms where ISC DHCP is still available and supported. Kea DHCP
will be added as a second backend for platforms that need it, starting with EL10
and Ubuntu 24.04.
and Ubuntu 22.04.
The public xCAT contract remains ``makedhcp``. The implementation underneath
``makedhcp`` will select an ISC or Kea backend based on site configuration and
@@ -20,7 +20,7 @@ The ``kea-dhcp-backend`` work implements the Kea backend foundation:
* backend selection through ``site.dhcpbackend``
* ISC as the preserved default on platforms that still support it
* Kea as the automatic default for EL10 and Ubuntu 24.04+
* Kea as the automatic default for EL10 and Ubuntu 22.04+
* Kea DHCPv4 and DHCPv6 JSON rendering with Perl's ``JSON`` module
* Kea DHCPv4, DHCPv6, Control Agent, and DHCP-DDNS configuration validation
before install
@@ -46,7 +46,7 @@ Remaining work is validation and hardening:
* full PXE boot validation on real hardware or nested guests for every
supported architecture
* complete service-node and disjoint-DHCP scenario validation
* CI integration for EL10 and Ubuntu 24.04 containers
* CI integration for EL10 and Ubuntu 22.04+ containers
Backend Selection
-----------------
@@ -58,8 +58,8 @@ Add a site attribute:
Selection rules:
* ``auto`` keeps ISC DHCP on existing supported platforms such as EL8, EL9,
older Ubuntu/Debian releases, and SLES.
* ``auto`` selects Kea DHCP on EL10 and Ubuntu 24.04.
Ubuntu 20.04 and older Ubuntu/Debian releases, and SLES.
* ``auto`` selects Kea DHCP on EL10 and Ubuntu 22.04+.
* ``isc`` forces the ISC backend.
* ``kea`` forces the Kea backend.
* A forced backend that is unavailable must fail with a clear error.
@@ -159,10 +159,10 @@ ISC services:
Kea services:
* ``kea-dhcp4``
* optional ``kea-dhcp6``
* ``kea-dhcp4`` or Debian-style ``kea-dhcp4-server``
* optional ``kea-dhcp6`` or Debian-style ``kea-dhcp6-server``
* optional ``kea-ctrl-agent``
* optional ``kea-dhcp-ddns``
* optional ``kea-dhcp-ddns`` or Debian-style ``kea-dhcp-ddns-server``
Control Agent must be running before REST operations are attempted. D2 should
only be managed when Kea DDNS support is configured.
@@ -187,7 +187,8 @@ Backends render the same intent as:
Boot coverage must include:
* x86 BIOS
* x86_64 UEFI
* x86_64 UEFI PXE architecture ids ``0x0007`` and ``0x0009``
* x86_64 UEFI HTTP boot architecture id ``0x0010``
* ARM64
* OpenPOWER/OPAL
* ONIE
@@ -205,10 +206,28 @@ Baseline Kea behavior should be deterministic and not depend on optional hooks:
* validate generated configuration
* reload Kea
Kea reservation policy must map xCAT's existing ``makedhcp`` semantics
explicitly:
* ``networks.dynamicrange`` renders as Kea dynamic address pools.
* Node addresses outside ``networks.dynamicrange`` render as static
``ip-address`` host reservations.
* Node addresses inside ``networks.dynamicrange`` are currently treated as
dynamic by ``makedhcp`` and do not render fixed ``ip-address`` reservations;
enabling in-pool fixed reservations is a separate behavior change that needs
explicit live validation.
* DHCPv4 output should keep Kea subnet host reservations enabled with
``reservations-in-subnet`` set to ``true`` and should not switch globally to
out-of-pool-only mode unless all fixed reservations are known to be outside
dynamic pools.
* In hierarchical deployments, ``networks.dhcpserver`` ownership must be
honored before rendering ``networks.dynamicrange`` as Kea pools, matching
the legacy ISC behavior that prevents duplicate dynamic leases.
Optimized behavior can use Kea Control Agent plus host-commands when available.
This requires verifying that the target distribution packages include the host
commands hook library, such as ``libdhcp_host_cmds.so``. Do not assume this
library is present in EL10 or Ubuntu 24.04 without testing the actual packages.
library is present in EL10 or Ubuntu 22.04+ without testing the actual packages.
If host-commands are unavailable, the JSON render and reload path must still
work.
@@ -240,7 +259,7 @@ dependencies only for platforms using Kea.
Known areas:
* ``xCAT.spec`` and ``xCATsn.spec`` currently depend on ``/usr/sbin/dhcpd``.
* EL10 and Ubuntu 24.04 packaging should depend on the correct Kea server
* EL10 and Ubuntu 22.04+ packaging should depend on the correct Kea server
packages.
* ``dhclient`` and ``dhcp-client`` are separate client-side genesis/netboot
issues and should not be conflated with the server backend.
@@ -270,6 +289,8 @@ Unit tests:
* Kea JSON renderer coverage
* host reservation formatting
* subnet and pool mapping
* Kea reservation policy flags for subnet reservations and out-of-pool-only
overrides
* backend selection and override behavior
Configuration validation tests:
@@ -287,8 +308,9 @@ Configuration validation tests:
Backend selection tests:
* ``auto`` uses ISC on EL9
* ``auto`` uses ISC on Ubuntu 20.04
* ``auto`` uses Kea on EL10
* ``auto`` uses Kea on Ubuntu 24.04
* ``auto`` uses Kea on Ubuntu 22.04 and Ubuntu 24.04
* forced ``kea`` works on EL9 when Kea packages are installed
* forced unavailable backend fails clearly
@@ -297,6 +319,7 @@ Integration matrix:
* EL9 plus ISC
* EL9 plus forced Kea
* EL10 plus Kea
* Ubuntu 22.04 plus Kea
* Ubuntu 24.04 plus Kea
Semantic parity tests:
@@ -315,6 +338,8 @@ Functional smoke tests:
* ``XCAT_KEA_LIVE_SMOKE=1`` validates live Control Agent host-commands when
Kea and the host-commands hook are installed
* DHCP offers contain expected boot options
* Kea static reservations outside dynamic pools allocate without
``ALLOC_FAIL_NO_POOLS``
* real PXE boot behavior is validated for each supported architecture
Test Infrastructure
@@ -328,7 +353,7 @@ ordinary containers.
Open test infrastructure details to confirm:
* SSH access method and user for ``rome01.local.versatushpc.com.br``
* available base images for EL9, EL10, and Ubuntu 24.04
* available base images for EL9, EL10, Ubuntu 22.04, and Ubuntu 24.04
* libvirt network names and whether isolated DHCP test networks are already
available
* whether nested or privileged test guests can run DHCP client and PXE tests
@@ -339,21 +364,26 @@ Open test infrastructure details to confirm:
Manual Validation Snapshot
--------------------------
As of April 23, 2026, the branch has been exercised on KVM guests across ISC
As of April 26, 2026, the branch has been exercised on KVM guests across ISC
and Kea backends:
* EL10 plus Kea on x86_64: passed end-to-end xNBA netboot with a Rocky 10.1
compute image. The node fetched the xNBA script, kernel, initrd, and rootimg,
then reached xCAT ``netbooting`` state.
* Ubuntu 24.04 plus Kea on x86_64: passed xNBA shell boot and full netboot
image fetch. The node downloaded the node script, Genesis artifacts, and the
generated root image, and Kea reservation queries succeeded.
* Ubuntu 24.04 plus Kea on x86_64: passed BIOS and non-Secure-Boot UEFI xNBA
shell boot and full stateless compute-image boot. The nodes downloaded the
node script, kernel, initrd, and generated root image, then reached ``sshd``.
Kea allocated static reservations outside ``networks.dynamicrange`` without
``ALLOC_FAIL_NO_POOLS``. The KVM osimage used ``netdrivers=overlay`` because
``virtio_net`` is built into the Ubuntu 24.04 generic kernel.
* EL9 plus ISC on x86_64: passed legacy ISC plus xNBA shell boot, including
DHCP, TFTP, node-script handoff, and Genesis fetch.
* Ubuntu 22.04 plus ISC on x86_64: passed legacy ISC DHCP, TFTP, generated
* Ubuntu 22.04 plus forced ISC on x86_64: passed legacy ISC DHCP, TFTP, generated
xNBA network script, and Genesis fetch. Per-node OMAPI reservation updates on
Jammy still fail with ``omshell`` descriptor errors and appear to be a
preexisting Ubuntu-specific ISC issue outside the Kea scope.
preexisting Ubuntu-specific ISC issue outside the Kea scope. Because of that
issue, ``site.dhcpbackend=auto`` now selects Kea on Ubuntu 22.04 and newer
Ubuntu releases.
* EL10 plus Kea on ppc64le: passed Kea 3.x renderer validation with
``evaluate-additional-classes`` and ``only-in-additional-list``; passed
``kea-dhcp4 -t``; passed the full DHCP unit suite on ppc64le after installing
@@ -392,5 +422,6 @@ Guiding Rule
------------
``makedhcp`` remains the stable xCAT interface. ISC remains the default backend
where it works. Kea is added as a backend for platforms that need it, with shared
DHCP intent and backend-specific rendering and control.
where it works and remains supported. Kea is added as a backend for platforms
that need it, with shared DHCP intent and backend-specific rendering and
control.
+2 -2
View File
@@ -59,7 +59,7 @@ sub default_backend {
my $os_name = exists $args{os_name} ? $args{os_name} : $class->_osver('os');
my $version = exists $args{version} ? $args{version} : $class->_osver('version');
if ( defined($os_name) && $os_name =~ /^ubuntu$/i && _version_at_least( $version, '24.04' ) ) {
if ( defined($os_name) && $os_name =~ /^ubuntu$/i && _version_at_least( $version, '22.04' ) ) {
return 'kea';
}
@@ -156,7 +156,7 @@ sub _command_exists {
sub _version_at_least {
my ( $version, $minimum ) = @_;
return 0 unless defined($version) && $version =~ /^\d+(?:\.\d+)*/;
return 0 unless defined($version) && $version =~ /^\d+\.\d+(?:\.\d+)*$/;
my @version_parts = split /\./, $version;
my @minimum_parts = split /\./, $minimum;
+67 -10
View File
@@ -10,6 +10,13 @@ use Math::BigInt;
use xCAT::DHCP::Range;
use xCAT::NetworkUtils;
my %KEA_SERVICE_CANDIDATES = (
'kea-dhcp4' => [ 'kea-dhcp4', 'kea-dhcp4-server' ],
'kea-dhcp6' => [ 'kea-dhcp6', 'kea-dhcp6-server' ],
'kea-dhcp-ddns' => [ 'kea-dhcp-ddns', 'kea-dhcp-ddns-server' ],
'kea-ctrl-agent' => [ 'kea-ctrl-agent' ],
);
sub new {
my ( $class, %args ) = @_;
return bless \%args, $class;
@@ -56,8 +63,10 @@ sub render_dhcp4_config {
type => 'memfile',
name => '/var/lib/kea/kea-leases4.csv',
},
'valid-lifetime' => _integer( _first_defined( $intent->{'valid-lifetime'}, $intent->{valid_lifetime}, 43200 ) ),
subnet4 => [ map { $self->_render_subnet4($_) } @{ _first_defined( $intent->{subnet4}, $intent->{subnets}, [] ) } ],
'valid-lifetime' => _integer( _first_defined( $intent->{'valid-lifetime'}, $intent->{valid_lifetime}, 43200 ) ),
'reservations-in-subnet' => _json_bool( _first_defined( $intent->{'reservations-in-subnet'}, $intent->{reservations_in_subnet}, 1 ) ),
'reservations-out-of-pool' => _json_bool( _first_defined( $intent->{'reservations-out-of-pool'}, $intent->{reservations_out_of_pool}, 1 ) ),
subnet4 => [ map { $self->_render_subnet4($_) } @{ _first_defined( $intent->{subnet4}, $intent->{subnets}, [] ) } ],
);
$dhcp4{'control-socket'} = $intent->{'control-socket'} if $intent->{'control-socket'};
@@ -434,16 +443,19 @@ sub restart_services {
push @services, 'kea-dhcp6' if $opts{ipv6};
push @services, 'kea-ctrl-agent' if $opts{ctrl_agent};
my @units;
foreach my $service (@services) {
my $unit = $self->_kea_service($service);
push @units, $unit;
if ( $opts{enable} ) {
my $enable_ret = xCAT::Utils->enableservice($service);
return { error => "Failed to enable $service." } if $enable_ret != 0;
my $enable_ret = xCAT::Utils->enableservice($unit);
return { error => "Failed to enable $unit." } if $enable_ret != 0;
}
my $ret = xCAT::Utils->restartservice($service);
return { error => "Failed to restart $service." } if $ret != 0;
my $ret = xCAT::Utils->restartservice($unit);
return { error => "Failed to restart $unit." } if $ret != 0;
}
return { services => \@services };
return { services => \@units };
}
sub check_services {
@@ -454,12 +466,15 @@ sub check_services {
my @services = ('kea-dhcp4');
push @services, 'kea-dhcp6' if $opts{ipv6};
my @units;
foreach my $service (@services) {
my $ret = xCAT::Utils->checkservicestatus($service);
return { error => "$service is not running. Please start the Kea DHCP service." } if $ret != 0;
my $unit = $self->_kea_service($service);
push @units, $unit;
my $ret = xCAT::Utils->checkservicestatus($unit);
return { error => "$unit is not running. Please start the Kea DHCP service." } if $ret != 0;
}
return { services => \@services };
return { services => \@units };
}
sub upsert_reservations {
@@ -867,6 +882,13 @@ sub _integer {
return 0 + $value;
}
sub _json_bool {
my ($value) = @_;
return $value if ref($value) eq 'JSON::PP::Boolean' || ref($value) eq 'JSON::Boolean';
return $value ? JSON::true : JSON::false;
}
sub _set_config_permissions {
my ($path) = @_;
@@ -895,6 +917,41 @@ sub _kea_group {
return;
}
sub _kea_service {
my ( $self, $service ) = @_;
# Kea service names are package-specific, not strictly distribution-specific.
# Prefer the unit that is actually installed so derivatives, backports, and
# locally rebuilt packages do not need a distro/version decision tree here.
foreach my $candidate ( @{ $KEA_SERVICE_CANDIDATES{$service} || [$service] } ) {
return $candidate if $self->_service_available($candidate);
}
return $service;
}
sub _service_available {
my ( $self, $service ) = @_;
my $unit = "$service.service";
foreach my $dir ( @{ $self->{service_unit_dirs} || _systemd_unit_dirs() } ) {
return 1 if -e "$dir/$unit";
}
return 1 if -x "/etc/init.d/$service";
return 0;
}
sub _systemd_unit_dirs {
return [
'/etc/systemd/system',
'/run/systemd/system',
'/usr/lib/systemd/system',
'/lib/systemd/system',
];
}
sub _command_path {
my ($command) = @_;
+8 -2
View File
@@ -7,6 +7,7 @@ sub kea_client_classes {
my ( $class, %opts ) = @_;
my $xnba_user_class = xnba_user_class_test();
my $uefi_x64_arch_match = uefi_x64_client_architecture_match_expr();
my $bios_boot = $opts{xnba_kpxe} ? 'xcat/xnba.kpxe' : 'pxelinux.0';
my $uefi_boot = $opts{xnba_efi} ? 'xcat/xnba.efi' : '';
my @classes;
@@ -24,7 +25,7 @@ sub kea_client_classes {
if ($uefi_boot ne '') {
push @classes, {
name => 'xcat-uefi-x64',
test => "(option[93].hex == 0x0007 or option[93].hex == 0x0009) and not ($xnba_user_class)",
test => "($uefi_x64_arch_match) and not ($xnba_user_class)",
'boot-file-name' => $uefi_boot,
};
}
@@ -55,6 +56,7 @@ sub kea_xnba_node_classes {
my $nodes = $opts{nodes} || [];
my $xnba_user_class = xnba_user_class_test();
my $uefi_x64_arch_match = uefi_x64_client_architecture_match_expr();
my @classes;
foreach my $node (@$nodes) {
@@ -73,7 +75,7 @@ sub kea_xnba_node_classes {
if ( $opts{xnba_efi} ) {
push @classes, {
name => "$class_base-uefi",
test => "$xnba_user_class and option[93].hex == 0x0009 and $mac_test",
test => "$xnba_user_class and ($uefi_x64_arch_match) and $mac_test",
'boot-file-name' => "$base_url.uefi",
'user-context' => _xnba_user_context($node),
};
@@ -87,6 +89,10 @@ sub xnba_user_class_test {
return "(option[77].exists and (option[77].text == 'xNBA' or option[77].hex == 0x784e4241 or substring(option[77].hex,1,4) == 'xNBA'))";
}
sub uefi_x64_client_architecture_match_expr {
return "option[93].hex == 0x0007 or option[93].hex == 0x0009 or option[93].hex == 0x0010";
}
sub _xnba_class_base {
my ( $node, $mac ) = @_;
+1 -1
View File
@@ -762,7 +762,7 @@ sub mknetboot
}
# turn off the selinux
if ($osver =~ m/(fedora12|fedora13|rhels7|rhels8|ol7|ol8|alma8|rocky8)/) {
if ($osver =~ m/(fedora12|fedora13|(?:rhels|ol|alma|rocky)(?:[7-9]|10))/) {
$kcmdline .= " selinux=0 ";
}
+25 -6
View File
@@ -2359,9 +2359,6 @@ sub kea_build_dhcp4_intent
%netcfgs = ();
@alldomains = ();
my @interfaces = grep { $_ ne '!remote!' && $_ !~ /!remote!/ } sort keys %$activenics;
@interfaces = ('*') unless @interfaces;
my $httpport = "80";
my @hports = xCAT::TableUtils->get_site_attribute("httpport");
if ($hports[0]) {
@@ -2387,6 +2384,23 @@ sub kea_build_dhcp4_intent
}
my @routes = kea_ipv4_routes(@vnets);
my %dhcp_interfaces = %$activenics;
if (!keys %dhcp_interfaces) {
my %configured_local_interfaces = map { $_->{mgtifname} => 1 } grep { $_->{mgtifname} && $_->{mgtifname} !~ /!remote!/ } @vnets;
foreach my $route (@routes) {
my ( $net, $netif, undef, $flags ) = @$route;
next if kea_skip_ipv4_network($net);
next if defined($flags) && $flags =~ /G/;
next if $netif =~ /!remote!/;
$dhcp_interfaces{$netif} = 1 if $configured_local_interfaces{$netif};
}
}
my @interfaces = grep { $_ ne '!remote!' && $_ !~ /!remote!/ } sort keys %dhcp_interfaces;
if (!@interfaces && !$dhcp_interfaces{'!remote!'}) {
return { error => "Unable to infer local Kea DHCP interfaces. Set site.dhcpinterfaces to the intended provisioning interface." };
}
my @subnets;
my @opal_classes;
my $id = 1;
@@ -2400,9 +2414,9 @@ sub kea_build_dhcp4_intent
if ($interface =~ /!remote!\S*/) {
$remote = 1;
$interface =~ s/!remote!\s*(.*)$/$1/;
next unless $activenics->{'!remote!'};
next unless $dhcp_interfaces{'!remote!'};
} else {
next unless $activenics->{$interface};
next unless $dhcp_interfaces{$interface};
}
my $subnet = kea_subnet4_intent($nettab, $net, $mask, $interface, $remote, $id, $httpport);
@@ -2767,11 +2781,16 @@ sub kea_subnet4_intent
push @option_data, { name => 'domain-search', data => $domainstring } if $domainstring;
my $prefix = kea_mask_to_prefix($mask);
my $dynamicrange = $ent ? $ent->{dynamicrange} : undef;
if ( $dynamicrange && $ent->{dhcpserver} && xCAT::NetworkUtils->thishostisnot( $ent->{dhcpserver} ) ) {
$dynamicrange = undef;
}
my $opal_class = kea_opal_client_class($net, $prefix, $tftp, $httpport);
my %subnet = (
id => $id,
subnet => "$net/$prefix",
dynamicrange => $ent ? $ent->{dynamicrange} : undef,
dynamicrange => $dynamicrange,
option_data => \@option_data,
next_server => $tftp,
);
+25 -1
View File
@@ -45,8 +45,14 @@ is(
is(
xCAT::DHCP::Backend->default_backend( platform => '', os => 'ubuntu22.04', os_name => 'ubuntu', version => '22.04' ),
'kea',
'Ubuntu 22.04 defaults to Kea'
);
is(
xCAT::DHCP::Backend->default_backend( platform => '', os => 'ubuntu20.04', os_name => 'ubuntu', version => '20.04' ),
'isc',
'Ubuntu 22.04 defaults to ISC'
'Ubuntu 20.04 defaults to ISC'
);
is(
@@ -55,6 +61,18 @@ is(
'Ubuntu 24.04 defaults to Kea'
);
is(
xCAT::DHCP::Backend->default_backend( platform => '', os => 'ubuntu24.04', os_name => 'ubuntu', version => '24.04.4' ),
'kea',
'Ubuntu 24.04 point releases default to Kea'
);
is(
xCAT::DHCP::Backend->default_backend( platform => '', os => 'ubuntu24.04', os_name => 'ubuntu', version => '24' ),
'isc',
'Ubuntu major-only version is not treated as a date-based release'
);
is(
xCAT::DHCP::Backend->default_backend( platform => '', os => 'ubuntu24.10', os_name => 'ubuntu', version => '24.10' ),
'kea',
@@ -97,6 +115,12 @@ is(
'auto selects Kea on Ubuntu 24.04'
);
is(
xCAT::DHCP::Backend->choose( requested => 'auto', os => 'ubuntu22.04', os_name => 'ubuntu', version => '22.04' )->{name},
'kea',
'auto selects Kea on Ubuntu 22.04'
);
like(
xCAT::DHCP::Backend->choose( requested => 'invalid' )->{error},
qr/Invalid site\.dhcpbackend/,
+4
View File
@@ -22,6 +22,7 @@ is( $by_name{'xcat-bios'}{'boot-file-name'}, 'xcat/xnba.kpxe', 'BIOS clients rec
like( $by_name{'xcat-bios'}{test}, qr/not \(\(option\[77\]\.exists/, 'generic BIOS class excludes xNBA second-stage clients' );
like( $by_name{'xcat-uefi-x64'}{test}, qr/0x0007/, 'UEFI x64 class matches architecture 7' );
like( $by_name{'xcat-uefi-x64'}{test}, qr/0x0009/, 'UEFI x64 class matches architecture 9' );
like( $by_name{'xcat-uefi-x64'}{test}, qr/0x0010/, 'UEFI x64 class matches HTTP boot architecture 16' );
like( $by_name{'xcat-uefi-x64'}{test}, qr/not \(\(option\[77\]\.exists/, 'generic UEFI class excludes xNBA second-stage clients' );
is( $by_name{'xcat-aarch64'}{'boot-file-name'}, 'boot/grub2/grub2.aarch64', 'AArch64 clients receive grub2 boot file' );
is( $by_name{'xcat-ppc64'}{'boot-file-name'}, '/boot/grub2/grub2.ppc', 'POWER clients receive grub2 Open Firmware boot file' );
@@ -48,6 +49,9 @@ like( $xnba_bios->{test}, qr/pkt4\.mac == 0x52544b100011/, 'xNBA second-stage cl
is( $xnba_bios->{'boot-file-name'}, 'http://10.241.10.1:80/tftpboot/xcat/xnba/nodes/cn01', 'xNBA BIOS class returns the node script URL' );
is( $xnba_bios->{'user-context'}{'xcat-purpose'}, 'xnba-second-stage', 'xNBA class carries removable user-context' );
is( $xnba_by_name{'xcat-xnba-cn01-52544b100011-uefi'}{'boot-file-name'}, 'http://10.241.10.1:80/tftpboot/xcat/xnba/nodes/cn01.uefi', 'xNBA UEFI class returns the UEFI node script URL' );
like( $xnba_by_name{'xcat-xnba-cn01-52544b100011-uefi'}{test}, qr/0x0007/, 'xNBA UEFI class matches standard UEFI PXE architecture 7' );
like( $xnba_by_name{'xcat-xnba-cn01-52544b100011-uefi'}{test}, qr/0x0009/, 'xNBA UEFI class matches alternate UEFI PXE architecture 9' );
like( $xnba_by_name{'xcat-xnba-cn01-52544b100011-uefi'}{test}, qr/0x0010/, 'xNBA UEFI class matches UEFI HTTP boot architecture 16' );
my $combined_classes = xCAT::DHCP::BootPolicy->kea_client_classes(
xnba_kpxe => 1,
+13 -1
View File
@@ -42,7 +42,7 @@ my $json = $backend->render_dhcp4_config(
},
{
name => 'xcat-uefi-x64',
test => "(option[93].hex == 0x0007 or option[93].hex == 0x0009) and not ((option[77].exists and (option[77].text == 'xNBA' or option[77].hex == 0x784e4241 or substring(option[77].hex,1,4) == 'xNBA')))",
test => "(option[93].hex == 0x0007 or option[93].hex == 0x0009 or option[93].hex == 0x0010) and not ((option[77].exists and (option[77].text == 'xNBA' or option[77].hex == 0x784e4241 or substring(option[77].hex,1,4) == 'xNBA')))",
'boot-file-name' => 'xcat/xnba.efi',
},
],
@@ -82,6 +82,18 @@ my $json = $backend->render_dhcp4_config(
},
],
},
{
id => 2,
subnet => '192.168.123.0/24',
pools => [],
reservations => [
{
'hw-address' => '52:54:00:65:43:21',
'ip-address' => '192.168.123.50',
hostname => 'node02',
},
],
},
],
}
);
+132
View File
@@ -0,0 +1,132 @@
use strict;
use warnings;
no warnings 'once';
use FindBin;
use lib "$FindBin::Bin/../../perl-xCAT";
use Test::More;
BEGIN {
package xCAT::Table;
our $networks;
sub new {
my ( $class, $name ) = @_;
return $name eq 'networks' ? $networks : undef;
}
$INC{'xCAT/Table.pm'} = __FILE__;
package xCAT::TableUtils;
sub getTftpDir { return '/tftpboot'; }
sub get_site_attribute { return; }
$INC{'xCAT/TableUtils.pm'} = __FILE__;
package xCAT::Utils;
sub osver { return 'rhels9'; }
sub runcmd { return; }
$INC{'xCAT/Utils.pm'} = __FILE__;
package xCAT::NetworkUtils;
sub import {
my $caller = caller;
no strict 'refs';
*{"${caller}::getipaddr"} = \&getipaddr;
}
sub getipaddr { return '10.0.0.1'; }
sub my_ip_facing { return ( 0, '10.0.0.1' ); }
sub thishostisnot { return 0; }
sub ip_forwarding_enabled { return 0; }
sub nodeonmynet { return 1; }
$INC{'xCAT/NetworkUtils.pm'} = __FILE__;
package xCAT::ServiceNodeUtils;
sub getSNList { return; }
$INC{'xCAT/ServiceNodeUtils.pm'} = __FILE__;
package xCAT::NodeRange;
$INC{'xCAT/NodeRange.pm'} = __FILE__;
}
require "$FindBin::Bin/../../xCAT-server/lib/xcat/plugins/dhcp.pm";
{
package DHCPKeaIntentNetTable;
sub new {
my ( $class, $entry ) = @_;
return bless { entry => $entry }, $class;
}
sub getAllAttribs {
my ( $self, @attrs ) = @_;
return { domain => $self->{entry}{domain} } if @attrs == 1 && $attrs[0] eq 'domain';
return { %{ $self->{entry} } };
}
sub getAttribs {
my ($self) = @_;
return { %{ $self->{entry} } };
}
sub close { return; }
}
my %network_entry = (
net => '10.0.0.0',
mask => '255.255.255.0',
mgtifname => 'eth0',
dynamicrange => '10.0.0.100-10.0.0.150',
domain => 'cluster.test',
tftpserver => '<xcatmaster>',
);
{
no warnings 'redefine';
local *xCAT_plugin::dhcp::kea_ipv4_routes = sub {
return (
[ '10.0.0.0', 'eth0', '255.255.255.0', '' ],
[ '192.168.1.0', 'enp3s0', '255.255.255.0', '' ],
);
};
local *xCAT_plugin::dhcp::kea_boot_client_classes = sub { return []; };
local *xCAT_plugin::dhcp::kea_option_defs = sub { return []; };
local *xCAT_plugin::dhcp::kea_global_option_data = sub { return []; };
local *xCAT_plugin::dhcp::kea_dhcp_lease_time = sub { return 43200; };
local *xCAT_plugin::dhcp::kea_control_agent_enabled = sub { return 0; };
local $xCAT::Table::networks = DHCPKeaIntentNetTable->new( \%network_entry );
my $intent = xCAT_plugin::dhcp::kea_build_dhcp4_intent( bless({}, 'DHCPKeaIntentBackend'), {} );
is_deeply( $intent->{interfaces}, ['eth0'], 'empty dhcpinterfaces infers the local provisioning interface' );
is( scalar @{ $intent->{subnets} }, 1, 'empty dhcpinterfaces still renders local routed subnet' );
is( $intent->{subnets}[0]{subnet}, '10.0.0.0/24', 'rendered subnet comes from local route' );
}
{
no warnings 'redefine';
local *xCAT::NetworkUtils::thishostisnot = sub { return 1; };
my $nettab = DHCPKeaIntentNetTable->new(
{
%network_entry,
dhcpserver => 'service-node-a',
}
);
my $subnet = xCAT_plugin::dhcp::kea_subnet4_intent( $nettab, '10.0.0.0', '255.255.255.0', 'eth0', 0, 1, 80 );
ok( !defined( $subnet->{dynamicrange} ), 'non-owning Kea server does not render dynamic pool' );
}
{
no warnings 'redefine';
local *xCAT::NetworkUtils::thishostisnot = sub { return 0; };
my $nettab = DHCPKeaIntentNetTable->new(
{
%network_entry,
dhcpserver => 'service-node-a',
}
);
my $subnet = xCAT_plugin::dhcp::kea_subnet4_intent( $nettab, '10.0.0.0', '255.255.255.0', 'eth0', 0, 1, 80 );
is( $subnet->{dynamicrange}, $network_entry{dynamicrange}, 'owning Kea server renders dynamic pool' );
}
done_testing();
+35
View File
@@ -11,6 +11,21 @@ use Test::More;
use xCAT::DHCP::Backend::Kea;
my $backend = xCAT::DHCP::Backend::Kea->new( kea_version => '2.4.1' );
my $unit_dir = tempdir( CLEANUP => 1 );
foreach my $unit (qw/kea-dhcp4-server.service kea-dhcp6-server.service kea-dhcp-ddns-server.service kea-ctrl-agent.service/) {
open( my $unit_fh, '>', "$unit_dir/$unit" ) or die "Unable to write $unit_dir/$unit: $!";
close($unit_fh);
}
my $service_backend = xCAT::DHCP::Backend::Kea->new( service_unit_dirs => [$unit_dir] );
is( $service_backend->_kea_service('kea-dhcp4'), 'kea-dhcp4-server', 'Debian-style DHCPv4 service name is detected' );
is( $service_backend->_kea_service('kea-dhcp6'), 'kea-dhcp6-server', 'Debian-style DHCPv6 service name is detected' );
is( $service_backend->_kea_service('kea-dhcp-ddns'), 'kea-dhcp-ddns-server', 'Debian-style DHCP-DDNS service name is detected' );
is( $service_backend->_kea_service('kea-ctrl-agent'), 'kea-ctrl-agent', 'control agent service keeps canonical name' );
open( my $canonical_unit_fh, '>', "$unit_dir/kea-dhcp4.service" ) or die "Unable to write canonical Kea unit: $!";
close($canonical_unit_fh);
is( $service_backend->_kea_service('kea-dhcp4'), 'kea-dhcp4', 'canonical Kea service name is preferred when present' );
my $json = $backend->render_dhcp4_config(
{
interfaces => ['eth0'],
@@ -60,6 +75,8 @@ ok( $config->{Dhcp4}, 'renderer creates a Dhcp4 document' );
is_deeply( $config->{Dhcp4}{'interfaces-config'}{interfaces}, ['eth0'], 'interfaces are rendered' );
is( $config->{Dhcp4}{'valid-lifetime'}, 600, 'valid lifetime is rendered' );
is( $config->{Dhcp4}{'lease-database'}{type}, 'memfile', 'memfile lease backend is the default' );
is( $config->{Dhcp4}{'reservations-in-subnet'}, JSON::true, 'subnet host reservations are enabled by default' );
is( $config->{Dhcp4}{'reservations-out-of-pool'}, JSON::true, 'out-of-pool host reservations are enabled by default' );
my $subnet = $config->{Dhcp4}{subnet4}[0];
is( $subnet->{id}, 1, 'subnet id is rendered' );
@@ -172,6 +189,23 @@ my $empty_boot_subnet = decode_json($empty_boot_json)->{Dhcp4}{subnet4}[0];
is( $empty_boot_subnet->{'next-server'}, '0.0.0.0', 'false-looking next-server value is preserved' );
is( $empty_boot_subnet->{'boot-file-name'}, '', 'empty boot-file-name is preserved' );
my $reservation_policy_json = $backend->render_dhcp4_config(
{
'reservations-in-subnet' => 1,
'reservations-out-of-pool' => 1,
subnets => [
{
id => 9,
subnet => '10.0.9.0/24',
pools => [],
},
],
}
);
my $reservation_policy_config = decode_json($reservation_policy_json);
is( $reservation_policy_config->{Dhcp4}{'reservations-in-subnet'}, JSON::true, 'reservation in-subnet policy can be overridden' );
is( $reservation_policy_config->{Dhcp4}{'reservations-out-of-pool'}, JSON::true, 'reservation out-of-pool policy can be overridden' );
my $comment_dir = tempdir(CLEANUP => 1);
my $commented_config = "$comment_dir/kea-dhcp4.conf";
my $commented_content = <<'COMMENTED_JSON';
@@ -222,6 +256,7 @@ $backend->upsert_reservations(
]
);
is( scalar @{ $reservation_config->{Dhcp4}{subnet4}[0]{reservations} }, 1, 'reservation is added to matching subnet' );
is_deeply( $reservation_config->{Dhcp4}{subnet4}[0]{pools}, [], 'out-of-pool static reservation does not require a dynamic pool' );
$backend->upsert_reservations(
$reservation_config,