From 5467c1aef941b557dbb61c6a53ff7e81422ff01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Sat, 18 Jul 2026 01:41:13 -0300 Subject: [PATCH 1/2] refactor(dhcp): reuse shared version comparison --- perl-xCAT/xCAT/DHCP/Backend.pm | 24 +++--------------------- perl-xCAT/xCAT/DHCP/Backend/Kea.pm | 24 ++++-------------------- 2 files changed, 7 insertions(+), 41 deletions(-) diff --git a/perl-xCAT/xCAT/DHCP/Backend.pm b/perl-xCAT/xCAT/DHCP/Backend.pm index 1a753b981..0132f8a97 100644 --- a/perl-xCAT/xCAT/DHCP/Backend.pm +++ b/perl-xCAT/xCAT/DHCP/Backend.pm @@ -59,8 +59,9 @@ 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, '22.04' ) ) { - return 'kea'; + if ( defined($os_name) && $os_name =~ /^ubuntu$/i && defined($version) && $version =~ /^\d+\.\d+(?:\.\d+)*$/ ) { + require xCAT::Utils; + return 'kea' if xCAT::Utils->version_cmp( $version, '22.04' ) >= 0; } return 'isc'; @@ -153,23 +154,4 @@ sub _command_exists { return 0; } -sub _version_at_least { - my ( $version, $minimum ) = @_; - - return 0 unless defined($version) && $version =~ /^\d+\.\d+(?:\.\d+)*$/; - - my @version_parts = split /\./, $version; - my @minimum_parts = split /\./, $minimum; - my $max = @version_parts > @minimum_parts ? @version_parts : @minimum_parts; - - for my $idx ( 0 .. $max - 1 ) { - my $left = $version_parts[$idx] || 0; - my $right = $minimum_parts[$idx] || 0; - return 1 if $left > $right; - return 0 if $left < $right; - } - - return 1; -} - 1; diff --git a/perl-xCAT/xCAT/DHCP/Backend/Kea.pm b/perl-xCAT/xCAT/DHCP/Backend/Kea.pm index e83c55673..c4c1a27e0 100644 --- a/perl-xCAT/xCAT/DHCP/Backend/Kea.pm +++ b/perl-xCAT/xCAT/DHCP/Backend/Kea.pm @@ -899,7 +899,10 @@ sub _use_modern_additional_class_syntax { return 0 if $self->{additional_class_syntax} && $self->{additional_class_syntax} eq 'legacy'; my $version = $self->kea_version(); - return _version_at_least( $version, '2.7.4' ); + return 0 unless defined($version) && $version =~ /\A\d+(?:\.\d+)*(?:-[A-Za-z0-9]+)?\z/; + + require xCAT::Utils; + return xCAT::Utils->version_cmp( $version, '2.7.4' ) >= 0 ? 1 : 0; } sub kea_version { @@ -934,25 +937,6 @@ sub _first_defined { return; } -sub _version_at_least { - my ( $version, $minimum ) = @_; - - return 0 unless defined($version) && $version =~ /^\d+(?:\.\d+)*/; - - my @version_parts = split /\./, $version; - my @minimum_parts = split /\./, $minimum; - my $max = @version_parts > @minimum_parts ? @version_parts : @minimum_parts; - - for my $idx ( 0 .. $max - 1 ) { - my $left = $version_parts[$idx] || 0; - my $right = $minimum_parts[$idx] || 0; - return 1 if $left > $right; - return 0 if $left < $right; - } - - return 1; -} - sub _integer { my ($value) = @_; From 0ddc19e74b9cd2232c8b7fd9ca27a9904e420738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Sat, 18 Jul 2026 01:48:05 -0300 Subject: [PATCH 2/2] test(dhcp): cover shared version comparison --- xCAT-test/unit/dhcp_backend_selection.t | 18 ++++++++++++++++++ xCAT-test/unit/dhcp_kea_renderer.t | 21 +++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/xCAT-test/unit/dhcp_backend_selection.t b/xCAT-test/unit/dhcp_backend_selection.t index 544d0cf76..9083ec2c9 100644 --- a/xCAT-test/unit/dhcp_backend_selection.t +++ b/xCAT-test/unit/dhcp_backend_selection.t @@ -55,6 +55,18 @@ is( 'Ubuntu 22.04 point releases default to Kea' ); +is( + xCAT::DHCP::Backend->default_backend( platform => '', os => 'ubuntu22.04', os_name => 'ubuntu', version => '22.04.0' ), + 'kea', + 'Ubuntu release with a trailing zero component meets the minimum' +); + +is( + xCAT::DHCP::Backend->default_backend( platform => '', os => 'ubuntu22.03.99', os_name => 'ubuntu', version => '22.03.99' ), + 'isc', + 'Ubuntu release below the minimum stays on ISC despite a newer point component' +); + is( xCAT::DHCP::Backend->default_backend( platform => '', os => 'ubuntu20.04', os_name => 'ubuntu', version => '20.04' ), 'isc', @@ -79,6 +91,12 @@ is( 'Ubuntu major-only version is not treated as a date-based release' ); +is( + xCAT::DHCP::Backend->default_backend( platform => '', os => 'ubuntu24.04', os_name => 'ubuntu', version => '24.04-LTS' ), + 'isc', + 'Ubuntu version suffix is rejected by the numeric release contract' +); + is( xCAT::DHCP::Backend->default_backend( platform => '', os => 'ubuntu24.10', os_name => 'ubuntu', version => '24.10' ), 'kea', diff --git a/xCAT-test/unit/dhcp_kea_renderer.t b/xCAT-test/unit/dhcp_kea_renderer.t index 3099dd26e..a2e00c782 100644 --- a/xCAT-test/unit/dhcp_kea_renderer.t +++ b/xCAT-test/unit/dhcp_kea_renderer.t @@ -11,6 +11,27 @@ use Test::More; use xCAT::DHCP::Backend::Kea; my $backend = xCAT::DHCP::Backend::Kea->new( kea_version => '2.4.1' ); + +my @additional_class_syntax_cases = ( + [ '2.7.3', 0, 'Kea release below 2.7.4 uses legacy additional-class fields' ], + [ '2.7.4', 1, 'Kea 2.7.4 uses modern additional-class fields' ], + [ '2.10', 1, 'Kea two-digit minor release uses modern additional-class fields' ], + [ '2.7', 0, 'Kea release with fewer components stays below 2.7.4' ], + [ '2.7.4.0', 1, 'Kea release with a trailing zero component meets the minimum' ], + [ '2.7.4-rc1', 1, 'Kea suffix above the 2.7.4 numeric core keeps modern fields' ], + [ '2.7.3-rc1', 0, 'Kea suffix below the 2.7.4 numeric core keeps legacy fields' ], + [ '', 0, 'empty Kea version keeps legacy additional-class fields' ], + [ 'not-a-version', 0, 'malformed Kea version keeps legacy additional-class fields' ], + [ '2.7foo', 0, 'digit-leading malformed Kea version keeps legacy additional-class fields' ], + [ 'v2.7.4', 0, 'prefixed Kea version keeps legacy additional-class fields' ], +); + +foreach my $case (@additional_class_syntax_cases) { + my ( $version, $modern, $description ) = @$case; + my $version_backend = xCAT::DHCP::Backend::Kea->new( kea_version => $version ); + is( $version_backend->_use_modern_additional_class_syntax(), $modern, $description ); +} + 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: $!";