From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <s.ivanov@proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by lists.proxmox.com (Postfix) with ESMTPS id C6EC073040
 for <pve-devel@lists.proxmox.com>; Mon,  5 Jul 2021 12:58:05 +0200 (CEST)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
 by firstgate.proxmox.com (Proxmox) with ESMTP id BE0CB1DA2B
 for <pve-devel@lists.proxmox.com>; Mon,  5 Jul 2021 12:57:35 +0200 (CEST)
Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com
 [94.136.29.106])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by firstgate.proxmox.com (Proxmox) with ESMTPS id 297521DA16
 for <pve-devel@lists.proxmox.com>; Mon,  5 Jul 2021 12:57:34 +0200 (CEST)
Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1])
 by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 00A7A40B12
 for <pve-devel@lists.proxmox.com>; Mon,  5 Jul 2021 12:57:34 +0200 (CEST)
From: Stoiko Ivanov <s.ivanov@proxmox.com>
To: pve-devel@lists.proxmox.com
Date: Mon,  5 Jul 2021 12:57:16 +0200
Message-Id: <20210705105717.779369-4-s.ivanov@proxmox.com>
X-Mailer: git-send-email 2.30.2
In-Reply-To: <20210705105717.779369-1-s.ivanov@proxmox.com>
References: <20210705105717.779369-1-s.ivanov@proxmox.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.121 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment
 KAM_NUMSUBJECT 0.5 Subject ends in numbers excluding current years
 POISEN_SPAM_PILL          0.1 Meta: its spam
 POISEN_SPAM_PILL_1        0.1 random spam to be learned in bayes
 POISEN_SPAM_PILL_3        0.1 random spam to be learned in bayes
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
Subject: [pve-devel] [PATCH manager v2 1/2] pve6to7: check for containers
 not supporting pure cgroupv2
X-BeenThere: pve-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/>
List-Post: <mailto:pve-devel@lists.proxmox.com>
List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe>
X-List-Received-Date: Mon, 05 Jul 2021 10:58:05 -0000

Helpers copied from pve-container to avoid versioned bumps.

Early returns when no containers are running, or the containers don't
use systemd, as well as returning after finding the first affected
container to minimize impact and resource usage.

Checking running containers first since following /proc/<pid>/root is
cheaper than mounting all volumes for a container

Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
---
 PVE/CLI/pve6to7.pm | 123 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 123 insertions(+)

diff --git a/PVE/CLI/pve6to7.pm b/PVE/CLI/pve6to7.pm
index 60edac11..b9aeb89c 100644
--- a/PVE/CLI/pve6to7.pm
+++ b/PVE/CLI/pve6to7.pm
@@ -23,6 +23,9 @@ use PVE::Tools qw(run_command split_list);
 use PVE::QemuConfig;
 use PVE::QemuServer;
 use PVE::VZDump::Common;
+use PVE::LXC;
+use PVE::LXC::Config;
+use PVE::LXC::Setup;
 
 use Term::ANSIColor;
 
@@ -891,6 +894,126 @@ sub check_storage_content {
     }
 }
 
+sub check_containers_cgroup_compat {
+
+    my $kernel_cli = PVE::Tools::file_get_contents('/proc/cmdline');
+    if ($kernel_cli =~ /systemd.unified_cgroup_hierarchy=0/){
+	log_skip("System explicitly configured for legacy hybrid cgroup hierarchy.");
+	return;
+    }
+
+    my $supports_cgroupv2 = sub {
+	my ($conf, $rootdir) = @_;
+
+	my $get_systemd_version = sub {
+	    my ($self) = @_;
+
+	    my $sd_lib_dir = -d "/lib/systemd" ? "/lib/systemd" : "/usr/lib/systemd";
+	    my $libsd = PVE::Tools::dir_glob_regex($sd_lib_dir, "libsystemd-shared-.+\.so");
+	    if (defined($libsd) && $libsd =~ /libsystemd-shared-(\d+)\.so/) {
+		return $1;
+	    }
+
+	    return undef;
+	};
+
+	my  $unified_cgroupv2_support = sub {
+	    my ($self) = @_;
+
+	    # https://www.freedesktop.org/software/systemd/man/systemd.html
+	    # systemd is installed as symlink to /sbin/init
+	    my $systemd = CORE::readlink('/sbin/init');
+
+	    # assume non-systemd init will run with unified cgroupv2
+	    if (!defined($systemd) || $systemd !~ m@/systemd$@) {
+		return 1;
+	    }
+
+	    # systemd version 232 (e.g. debian stretch) supports the unified hierarchy
+	    my $sdver = $get_systemd_version->();
+	    if (!defined($sdver) || $sdver < 232) {
+		return 0;
+	    }
+
+	    return 1;
+	};
+
+	my $ostype = $conf->{ostype};
+	if ($ostype eq 'devuan' || $ostype eq 'alpine') {
+	    return 1;
+	}
+
+	my $lxc_setup = PVE::LXC::Setup->new($conf, $rootdir);
+	return $lxc_setup->protected_call($unified_cgroupv2_support);
+    };
+
+    my $log_problem = sub {
+	my ($ctid) = @_;
+	log_warn("Found at least one CT ($ctid) which does not support running in a unified " .
+	    "cgroup v2 layout - either upgrade it or set systemd.unified_cgroup_hierarchy=0 " .
+	    "in the kernel cmdline - skipping further checks"
+	);
+    };
+
+    my $cts = eval { PVE::API2::LXC->vmlist({ node => $nodename }) };
+    if ($@) {
+	log_warn("Failed to retrieve information about this node's CTs - $@");
+	return;
+    }
+
+    if (!defined($cts) || !scalar(@$cts)) {
+	log_skip("No containers on node detected.");
+	return;
+    }
+
+    my @running_cts = grep { $_->{status} eq 'running' } @$cts;
+    my @offline_cts = grep { $_->{status} ne 'running' } @$cts;
+
+    for my $ct (@running_cts) {
+	my $ctid = $ct->{vmid};
+	my $pid = eval { PVE::LXC::find_lxc_pid($ctid) };
+	if (my $err = $@) {
+	    log_warn("Failed to get PID for running CT $ctid - $err");
+	    next;
+	}
+	my $rootdir = "/proc/$pid/root";
+	my $conf = PVE::LXC::Config->load_config($ctid);
+
+	my $ret = eval { $supports_cgroupv2->($conf, $rootdir) };
+	if (my $err = $@) {
+	    log_warn("Failed to get cgroup support status for CT $ctid - $err");
+	    next;
+	}
+	if (!$ret) {
+	    $log_problem->($ctid);
+	    return;
+	}
+    }
+
+    my $storage_cfg = PVE::Storage::config();
+    for my $ct (@offline_cts) {
+	my $ctid = $ct->{vmid};
+	my ($conf, $rootdir, $ret);
+	eval {
+	    $conf = PVE::LXC::Config->load_config($ctid);
+	    $rootdir = PVE::LXC::mount_all($ctid, $storage_cfg, $conf);
+	    $ret = $supports_cgroupv2->($conf, $rootdir);
+	};
+	if (my $err = $@) {
+	    log_warn("Failed to load config and mount CT $ctid - $err");
+	    eval { PVE::LXC::umount_all($ctid, $storage_cfg, $conf) };
+	    next;
+	}
+	if (!$ret) {
+	    $log_problem->($ctid);
+	    eval { PVE::LXC::umount_all($ctid, $storage_cfg, $conf) };
+	    last;
+	}
+
+	eval { PVE::LXC::umount_all($ctid, $storage_cfg, $conf) };
+    }
+};
+
 sub check_misc {
     print_header("MISCELLANEOUS CHECKS");
     my $ssh_config = eval { PVE::Tools::file_get_contents('/root/.ssh/config') };
-- 
2.30.2