diff --git a/PVE/Ceph/Makefile b/PVE/Ceph/Makefile index ae628720..2901ebe5 100644 --- a/PVE/Ceph/Makefile +++ b/PVE/Ceph/Makefile @@ -1,8 +1,9 @@ include ../../defines.mk PERLSOURCE = \ - Services.pm\ - Tools.pm + Releases.pm \ + Services.pm \ + Tools.pm \ all: diff --git a/PVE/Ceph/Releases.pm b/PVE/Ceph/Releases.pm new file mode 100644 index 00000000..9dd3a8e6 --- /dev/null +++ b/PVE/Ceph/Releases.pm @@ -0,0 +1,126 @@ +package PVE::Ceph::Releases; + +use v5.36; + +use PVE::pvecfg; + +my sub get_current_pve_major_release { + my $release_tuples = [ split(/\./, PVE::pvecfg::release()) ]; + return $release_tuples->[0]; +} + +my $_ceph_release_info; +my sub get_ceph_release_def { + if (defined($_ceph_release_info)) { + return $_ceph_release_info; + } + + # Track all ceph releases (from a initial cut-off) with some metainfo. + # + # Schema keys: + # - `release`: version number of the stable release, which for ceph normally is `X.2` + # - `initial-upstream-release`: the ISO 8601 formatted day when upstream made their initial + # stable release. + # - `estimated-end-of-upstream-support`: the ISO 8601 formatted day when upstream will go EOL + # - `available-for-pve-release`: a hash that denotes for which PVE major release series a ceph + # release is available, where available does not necessarily means (already) fully supported + # - `current-backend-default`: set to `1` if a release is currently used as default in the + # backend, i.e. by pveceph. The wizard from the web UI often uses a newer release, which is + # currently tracked manually there. + # - `unsupported`: set to `1` to mark a release as (currently) unsupported, which most often + # means that upstream either had no stable release yet, or we aren't 100 % finished with QA + # of that release yet. + # + # NOTE: very old releases got left out from the list, but there's _no_ need to clean-up + # periodically check https://docs.ceph.com/en/latest/releases/ for all past releases + my $ceph_release_info = { + octopus => { + release => '15.2', + 'initial-upstream-release' => '2020-03-23', + 'estimated-end-of-upstream-support' => '2022-08-09', + 'available-for-pve-release' => { + 6 => 1, + 7 => 1, + }, + }, + pacific => { + release => '16.2', + 'initial-upstream-release' => '2021-03-31', + 'estimated-end-of-upstream-support' => '2024-03-04', + 'available-for-pve-release' => { + 7 => 1, + }, + }, + quincy => { + release => '17.2', + 'current-backend-default' => 1, + 'initial-upstream-release' => '2022-04-19', + 'estimated-end-of-upstream-support' => '2024-06-01', + 'available-for-pve-release' => { + 7 => 1, + 8 => 1, + }, + }, + reef => { + release => '18.2', + 'initial-upstream-release' => '2023-08-07', + 'estimated-end-of-upstream-support' => '2025-08-01', + 'available-for-pve-release' => { + 8 => 1, + }, + }, + }; + + my $current_pve_major_release = get_current_pve_major_release(); + for my $codename (sort keys $ceph_release_info->%*) { + my $ceph_release = $ceph_release_info->{$codename}; + $ceph_release->{codename} = $codename; + $ceph_release->{'available-for-current-pve-release'} = $ceph_release->{'available-for-pve-release'}->{$current_pve_major_release}; + } + + $_ceph_release_info = $ceph_release_info; +} + +sub get_ceph_release_info($codename) { + my $ceph_releases = get_ceph_release_def(); + return $ceph_releases->{$codename}; +} + +my $_available_ceph_releases; +sub get_all_available_ceph_releases { + if (!defined($_available_ceph_releases)) { + my $ceph_releases = get_ceph_release_def(); + $_available_ceph_releases = {}; + for my $codename (sort keys $ceph_releases->%*) { + if ($ceph_releases->{$codename}->{'available-for-current-pve-release'}) { + $_available_ceph_releases->{$codename} = $ceph_releases->{$codename}; + } + } + } + return $_available_ceph_releases; +} + +sub get_available_ceph_release_codenames($include_unstable_releases = 0) { + my $available_releases = get_all_available_ceph_releases(); + + return $include_unstable_releases + ? [ sort keys $available_releases->%* ] + : [ grep { !$available_releases->{$_}->{unsupported} } sort keys $available_releases->%* ] + ; +} + +my $_default_ceph_release_codename; +sub get_default_ceph_release_codename { + if (!defined($_default_ceph_release_codename)) { + my $ceph_releases = get_all_available_ceph_releases(); + my @default_release = grep { $ceph_releases->{$_}->{'current-backend-default'} } keys $ceph_releases->%*; + die "internal error: got multiple ceph releases with 'current-backend-default' set\n" + if scalar(@default_release) > 1; + die "internal error: got no ceph releases with 'current-backend-default' set\n" + if scalar(@default_release) < 1; + $_default_ceph_release_codename = $default_release[0]; + } + return $_default_ceph_release_codename; +} + +1;