pve7to8: sync over from stable-7 branch

for after-upgrade checks

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2023-06-08 13:07:05 +02:00
parent 79007cfc40
commit eed1e93ee9

View File

@ -3,6 +3,8 @@ package PVE::CLI::pve7to8;
use strict; use strict;
use warnings; use warnings;
use Cwd ();
use PVE::API2::APT; use PVE::API2::APT;
use PVE::API2::Ceph; use PVE::API2::Ceph;
use PVE::API2::LXC; use PVE::API2::LXC;
@ -20,7 +22,7 @@ use PVE::NodeConfig;
use PVE::RPCEnvironment; use PVE::RPCEnvironment;
use PVE::Storage; use PVE::Storage;
use PVE::Storage::Plugin; use PVE::Storage::Plugin;
use PVE::Tools qw(run_command split_list); use PVE::Tools qw(run_command split_list file_get_contents);
use PVE::QemuConfig; use PVE::QemuConfig;
use PVE::QemuServer; use PVE::QemuServer;
use PVE::VZDump::Common; use PVE::VZDump::Common;
@ -36,6 +38,8 @@ use base qw(PVE::CLIHandler);
my $nodename = PVE::INotify::nodename(); my $nodename = PVE::INotify::nodename();
my $upgraded = 0; # set in check_pve_packages
sub setup_environment { sub setup_environment {
PVE::RPCEnvironment->setup_default_cli_env(); PVE::RPCEnvironment->setup_default_cli_env();
} }
@ -175,7 +179,7 @@ sub check_pve_packages {
my $pkgs = join(', ', map { $_->{Package} } @$updates); my $pkgs = join(', ', map { $_->{Package} } @$updates);
log_warn("updates for the following packages are available:\n $pkgs"); log_warn("updates for the following packages are available:\n $pkgs");
} else { } else {
log_pass("all packages uptodate"); log_pass("all packages up-to-date");
} }
print "\nChecking proxmox-ve package version..\n"; print "\nChecking proxmox-ve package version..\n";
@ -185,8 +189,6 @@ sub check_pve_packages {
my ($maj, $min, $pkgrel) = $proxmox_ve->{OldVersion} =~ m/^(\d+)\.(\d+)[.-](\d+)/; my ($maj, $min, $pkgrel) = $proxmox_ve->{OldVersion} =~ m/^(\d+)\.(\d+)[.-](\d+)/;
my $upgraded = 0;
if ($maj > $min_pve_major) { if ($maj > $min_pve_major) {
log_pass("already upgraded to Proxmox VE " . ($min_pve_major + 1)); log_pass("already upgraded to Proxmox VE " . ($min_pve_major + 1));
$upgraded = 1; $upgraded = 1;
@ -263,6 +265,8 @@ sub check_storage_health {
} }
check_storage_content(); check_storage_content();
eval { check_storage_content_dirs() };
log_fail("failed to check storage content directories - $@") if $@;
} }
sub check_cluster_corosync { sub check_cluster_corosync {
@ -467,7 +471,7 @@ sub check_ceph {
# TODO: check OSD min-required version, if to low it breaks stuff! # TODO: check OSD min-required version, if to low it breaks stuff!
log_info("cehcking local Ceph version.."); log_info("checking local Ceph version..");
if (my $release = eval { PVE::Ceph::Tools::get_local_version(1) }) { if (my $release = eval { PVE::Ceph::Tools::get_local_version(1) }) {
my $code_name = $ceph_release2code->{"$release"} || 'unknown'; my $code_name = $ceph_release2code->{"$release"} || 'unknown';
if ($release == $ceph_supported_release) { if ($release == $ceph_supported_release) {
@ -500,9 +504,24 @@ sub check_ceph {
{ 'key' => 'osd', 'name' => 'OSD' }, { 'key' => 'osd', 'name' => 'OSD' },
]; ];
my $ceph_versions_simple = {};
my $ceph_versions_commits = {};
for my $type (keys %$ceph_versions) {
for my $full_version (keys $ceph_versions->{$type}->%*) {
if ($full_version =~ m/^(.*) \((.*)\).*\(.*\)$/) {
# String is in the form of
# ceph version 17.2.6 (810db68029296377607028a6c6da1ec06f5a2b27) quincy (stable)
# only check the first part, e.g. 'ceph version 17.2.6', the commit hash can
# be different
$ceph_versions_simple->{$type}->{$1} = 1;
$ceph_versions_commits->{$type}->{$2} = 1;
}
}
}
foreach my $service (@$services) { foreach my $service (@$services) {
my ($name, $key) = $service->@{'name', 'key'}; my ($name, $key) = $service->@{'name', 'key'};
if (my $service_versions = $ceph_versions->{$key}) { if (my $service_versions = $ceph_versions_simple->{$key}) {
if (keys %$service_versions == 0) { if (keys %$service_versions == 0) {
log_skip("no running instances detected for daemon type $name."); log_skip("no running instances detected for daemon type $name.");
} elsif (keys %$service_versions == 1) { } elsif (keys %$service_versions == 1) {
@ -513,6 +532,9 @@ sub check_ceph {
} else { } else {
log_skip("unable to determine versions of running Ceph $name instances."); log_skip("unable to determine versions of running Ceph $name instances.");
} }
my $service_commits = $ceph_versions_commits->{$key};
log_info("different builds of same version detected for an $name. Are you in the middle of the upgrade?")
if $service_commits && keys %$service_commits > 1;
} }
my $overall_versions = $ceph_versions->{overall}; my $overall_versions = $ceph_versions->{overall};
@ -521,7 +543,7 @@ sub check_ceph {
} elsif (keys %$overall_versions == 1) { } elsif (keys %$overall_versions == 1) {
log_pass("single running overall version detected for all Ceph daemon types."); log_pass("single running overall version detected for all Ceph daemon types.");
$noout_wanted = 0; # off post-upgrade, on pre-upgrade $noout_wanted = 0; # off post-upgrade, on pre-upgrade
} else { } elsif (keys $ceph_versions_simple->{overall}->%* != 1) {
log_warn("overall version mismatch detected, check 'ceph versions' output for details!"); log_warn("overall version mismatch detected, check 'ceph versions' output for details!");
} }
} }
@ -646,7 +668,7 @@ sub check_backup_retention_settings {
log_warn("unable to parse node's VZDump configuration - $err"); log_warn("unable to parse node's VZDump configuration - $err");
} }
log_pass("no problems found.") if $pass; log_pass("no backup retention problems found.") if $pass;
} }
sub check_cifs_credential_location { sub check_cifs_credential_location {
@ -673,7 +695,7 @@ sub check_cifs_credential_location {
} }
sub check_custom_pool_roles { sub check_custom_pool_roles {
log_info("Checking custom roles for pool permissions.."); log_info("Checking custom role IDs for clashes with new 'PVE' namespace..");
if (! -f "/etc/pve/user.cfg") { if (! -f "/etc/pve/user.cfg") {
log_skip("user.cfg does not exist"); log_skip("user.cfg does not exist");
@ -712,10 +734,22 @@ sub check_custom_pool_roles {
} }
} }
foreach my $role (sort keys %{$roles}) { my ($custom_roles, $pve_namespace_clashes) = (0, 0);
for my $role (sort keys %{$roles}) {
next if PVE::AccessControl::role_is_special($role); next if PVE::AccessControl::role_is_special($role);
$custom_roles++;
# TODO: any role updates? if ($role =~ /^PVE/i) {
log_warn("custom role '$role' clashes with 'PVE' namespace for built-in roles");
$pve_namespace_clashes++;
}
}
if ($pve_namespace_clashes > 0) {
log_fail("$pve_namespace_clashes custom role(s) will clash with 'PVE' namespace for built-in roles enforced in Proxmox VE 8");
} elsif ($custom_roles > 0) {
log_pass("none of the $custom_roles custom roles will clash with newly enforced 'PVE' namespace")
} else {
log_pass("no custom roles defined, so no clash with 'PVE' role ID namespace enforced in Proxmox VE 8")
} }
} }
@ -725,7 +759,7 @@ my sub check_max_length {
} }
sub check_node_and_guest_configurations { sub check_node_and_guest_configurations {
log_info("Checking node and guest description/note legnth.."); log_info("Checking node and guest description/note length..");
my @affected_nodes = grep { my @affected_nodes = grep {
my $desc = PVE::NodeConfig::load_config($_)->{desc}; my $desc = PVE::NodeConfig::load_config($_)->{desc};
@ -804,7 +838,7 @@ sub check_storage_content {
next if $scfg->{content}->{images}; next if $scfg->{content}->{images};
next if $scfg->{content}->{rootdir}; next if $scfg->{content}->{rootdir};
# Skip 'iscsi(direct)' (and foreign plugins with potentially similiar behavior) with 'none', # Skip 'iscsi(direct)' (and foreign plugins with potentially similar behavior) with 'none',
# because that means "use LUNs directly" and vdisk_list() in PVE 6.x still lists those. # because that means "use LUNs directly" and vdisk_list() in PVE 6.x still lists those.
# It's enough to *not* skip 'dir', because it is the only other storage that supports 'none' # It's enough to *not* skip 'dir', because it is the only other storage that supports 'none'
# and 'images' or 'rootdir', hence being potentially misconfigured. # and 'images' or 'rootdir', hence being potentially misconfigured.
@ -926,14 +960,52 @@ sub check_storage_content {
} }
if ($pass) { if ($pass) {
log_pass("no problems found"); log_pass("no storage content problems found");
}
}
sub check_storage_content_dirs {
my $storage_cfg = PVE::Storage::config();
# check that content dirs are pairwise inequal
my $any_problematic = 0;
for my $storeid (sort keys $storage_cfg->{ids}->%*) {
my $scfg = $storage_cfg->{ids}->{$storeid};
next if !PVE::Storage::storage_check_enabled($storage_cfg, $storeid, undef, 1);
next if !$scfg->{path} || !$scfg->{content};
eval { PVE::Storage::activate_storage($storage_cfg, $storeid) };
if (my $err = $@) {
log_warn("activating '$storeid' failed - $err");
next;
}
my $resolved_subdirs = {};
my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
for my $vtype (keys $scfg->{content}->%*) {
my $abs_subdir = Cwd::abs_path($plugin->get_subdir($scfg, $vtype));
push $resolved_subdirs->{$abs_subdir}->@*, $vtype;
}
for my $subdir (keys $resolved_subdirs->%*) {
if (scalar($resolved_subdirs->{$subdir}->@*) > 1) {
my $types = join(", ", $resolved_subdirs->{$subdir}->@*);
log_warn("storage '$storeid' uses directory $subdir for multiple content types ($types).");
$any_problematic = 1;
}
}
}
if ($any_problematic) {
log_fail("re-using directory for multiple content types (see above) is no longer supported in Proxmox VE 8!")
} else {
log_pass("no storage re-uses a directory for multiple content types.")
} }
} }
sub check_containers_cgroup_compat { sub check_containers_cgroup_compat {
if ($forced_legacy_cgroup) { if ($forced_legacy_cgroup) {
log_warn("System explicitly configured for legacy hybrid cgroup hierarchy.\n" log_warn("System explicitly configured for legacy hybrid cgroup hierarchy.\n"
." NOTE: support for the hybrid cgroup hierachy will be removed in future Proxmox VE 9 (~ 2025)." ." NOTE: support for the hybrid cgroup hierarchy will be removed in future Proxmox VE 9 (~ 2025)."
); );
} }
@ -1052,6 +1124,34 @@ sub check_containers_cgroup_compat {
} }
}; };
sub check_lxcfs_fuse_version {
log_info("Checking if LXCFS is running with FUSE3 library, if already upgraded..");
if (!$upgraded) {
log_skip("not yet upgraded, no need to check the FUSE library version LXCFS uses");
return;
}
my $lxcfs_pid = eval { file_get_contents('/run/lxcfs.pid') };
if (my $err = $@) {
log_fail("failed to get LXCFS pid - $err");
return;
}
chomp $lxcfs_pid;
my $lxcfs_maps = eval { file_get_contents("/proc/${lxcfs_pid}/maps") };
if (my $err = $@) {
log_fail("failed to get LXCFS maps - $err");
return;
}
if ($lxcfs_maps =~ /\/libfuse.so.2/s) {
log_warn("systems seems to be upgraded but LXCFS is still running with FUSE 2 library, not yet rebooted?")
} elsif ($lxcfs_maps =~ /\/libfuse3.so.3/s) {
log_pass("systems seems to be upgraded and LXCFS is running with FUSE 3 library")
}
return;
}
sub check_apt_repos { sub check_apt_repos {
log_info("Checking if the suite for the Debian security repository is correct.."); log_info("Checking if the suite for the Debian security repository is correct..");
@ -1109,7 +1209,7 @@ sub check_apt_repos {
PVE::Tools::dir_glob_foreach($dir, '^.*\.list$', $check_file); PVE::Tools::dir_glob_foreach($dir, '^.*\.list$', $check_file);
if (!$found) { if (!$found) {
# only warn, it might be defined in a .sources file or in a way not catched above # only warn, it might be defined in a .sources file or in a way not caaught above
log_warn("No Debian security repository detected in /etc/apt/sources.list and " . log_warn("No Debian security repository detected in /etc/apt/sources.list and " .
"/etc/apt/sources.list.d/*.list"); "/etc/apt/sources.list.d/*.list");
} }
@ -1122,7 +1222,7 @@ sub check_time_sync {
if ($unit_active->('systemd-timesyncd.service')) { if ($unit_active->('systemd-timesyncd.service')) {
log_warn( log_warn(
"systemd-timesyncd is not the best choice for time-keeping on servers, due to only applying" "systemd-timesyncd is not the best choice for time-keeping on servers, due to only applying"
." updates on boot.\n While not necesarry for the upgrade it's recommended to use one of:\n" ." updates on boot.\n While not necessary for the upgrade it's recommended to use one of:\n"
." * chrony (Default in new Proxmox VE installations)\n * ntpsec\n * openntpd\n" ." * chrony (Default in new Proxmox VE installations)\n * ntpsec\n * openntpd\n"
); );
} elsif ($unit_active->('ntp.service')) { } elsif ($unit_active->('ntp.service')) {
@ -1234,6 +1334,7 @@ sub check_misc {
check_backup_retention_settings(); check_backup_retention_settings();
check_cifs_credential_location(); check_cifs_credential_location();
check_custom_pool_roles(); check_custom_pool_roles();
check_lxcfs_fuse_version();
check_node_and_guest_configurations(); check_node_and_guest_configurations();
check_apt_repos(); check_apt_repos();
} }