[pve-devel] [PATCH container 1/1] deal with disabled cgroup subsystems
Wolfgang Bumiller
w.bumiller at proxmox.com
Thu Jun 21 10:07:41 CEST 2018
When a user disables a cgroup subsystem via eg. a kernel
command line we shouldn't try to generate lxc.cgroup.*
entries for it.
Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
src/PVE/CLI/pct.pm | 6 ++
src/PVE/LXC.pm | 166 ++++++++++++++++++++++++++++++++---------------------
2 files changed, 107 insertions(+), 65 deletions(-)
diff --git a/src/PVE/CLI/pct.pm b/src/PVE/CLI/pct.pm
index 897d595..9eb4ac0 100755
--- a/src/PVE/CLI/pct.pm
+++ b/src/PVE/CLI/pct.pm
@@ -669,6 +669,12 @@ __PACKAGE__->register_method ({
code => sub {
my ($param) = @_;
+ my $cgv1 = PVE::LXC::get_cgroup_subsystems();
+ if (!$cgv1->{cpuset}) {
+ print "cpuset cgroup not available\n";
+ return undef;
+ }
+
my $ctlist = PVE::LXC::config_list();
my $len = 0;
diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index 4be1579..bc03792 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -195,48 +195,62 @@ sub vmstatus {
my $unpriv = $unprivileged->{$vmid};
- my $memory_stat = read_cgroup_list('memory', $vmid, $unpriv, 'memory.stat');
- my $mem_usage_in_bytes = read_cgroup_value('memory', $vmid, $unpriv, 'memory.usage_in_bytes');
-
- $d->{mem} = $mem_usage_in_bytes - $memory_stat->{total_cache};
- $d->{swap} = read_cgroup_value('memory', $vmid, $unpriv, 'memory.memsw.usage_in_bytes') - $mem_usage_in_bytes;
-
- my $blkio_bytes = read_cgroup_value('blkio', $vmid, $unpriv, 'blkio.throttle.io_service_bytes', 1);
- my @bytes = split(/\n/, $blkio_bytes);
- foreach my $byte (@bytes) {
- if (my ($key, $value) = $byte =~ /(Read|Write)\s+(\d+)/) {
- $d->{diskread} += $2 if $key eq 'Read';
- $d->{diskwrite} += $2 if $key eq 'Write';
+ if (-d '/sys/fs/cgroup/memory') {
+ my $memory_stat = read_cgroup_list('memory', $vmid, $unpriv, 'memory.stat');
+ my $mem_usage_in_bytes = read_cgroup_value('memory', $vmid, $unpriv, 'memory.usage_in_bytes');
+
+ $d->{mem} = $mem_usage_in_bytes - $memory_stat->{total_cache};
+ $d->{swap} = read_cgroup_value('memory', $vmid, $unpriv, 'memory.memsw.usage_in_bytes') - $mem_usage_in_bytes;
+ } else {
+ $d->{mem} = 0;
+ $d->{swap} = 0;
+ }
+
+ if (-d '/sys/fs/cgroup/blkio') {
+ my $blkio_bytes = read_cgroup_value('blkio', $vmid, $unpriv, 'blkio.throttle.io_service_bytes', 1);
+ my @bytes = split(/\n/, $blkio_bytes);
+ foreach my $byte (@bytes) {
+ if (my ($key, $value) = $byte =~ /(Read|Write)\s+(\d+)/) {
+ $d->{diskread} += $2 if $key eq 'Read';
+ $d->{diskwrite} += $2 if $key eq 'Write';
+ }
}
+ } else {
+ $d->{diskread} = 0;
+ $d->{diskwrite} = 0;
}
- my $pstat = $parse_cpuacct_stat->($vmid, $unpriv);
+ if (-d '/sys/fs/cgroup/cpuacct') {
+ my $pstat = $parse_cpuacct_stat->($vmid, $unpriv);
- my $used = $pstat->{utime} + $pstat->{stime};
+ my $used = $pstat->{utime} + $pstat->{stime};
- my $old = $last_proc_vmid_stat->{$vmid};
- if (!$old) {
- $last_proc_vmid_stat->{$vmid} = {
- time => $cdtime,
- used => $used,
- cpu => 0,
- };
- next;
- }
+ my $old = $last_proc_vmid_stat->{$vmid};
+ if (!$old) {
+ $last_proc_vmid_stat->{$vmid} = {
+ time => $cdtime,
+ used => $used,
+ cpu => 0,
+ };
+ next;
+ }
- my $dtime = ($cdtime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
+ my $dtime = ($cdtime - $old->{time}) * $cpucount * $cpuinfo->{user_hz};
- if ($dtime > 1000) {
- my $dutime = $used - $old->{used};
+ if ($dtime > 1000) {
+ my $dutime = $used - $old->{used};
- $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
- $last_proc_vmid_stat->{$vmid} = {
- time => $cdtime,
- used => $used,
- cpu => $d->{cpu},
- };
+ $d->{cpu} = (($dutime/$dtime)* $cpucount) / $d->{cpus};
+ $last_proc_vmid_stat->{$vmid} = {
+ time => $cdtime,
+ used => $used,
+ cpu => $d->{cpu},
+ };
+ } else {
+ $d->{cpu} = $old->{cpu};
+ }
} else {
- $d->{cpu} = $old->{cpu};
+ $d->{cpu} = 0;
}
}
@@ -339,6 +353,20 @@ sub parse_ipv4_cidr {
die "unable to parse ipv4 address/mask\n";
}
+sub get_cgroup_subsystems {
+ my $v1 = {};
+ my $v2 = 0;
+ my $data = PVE::Tools::file_get_contents('/proc/self/cgroup');
+ while ($data =~ /^\d+:([^:\n]*):.*$/gm) {
+ my $type = $1;
+ if (length($type)) {
+ $v1->{$_} = 1 foreach split(/,/, $type);
+ } else {
+ $v2 = 1;
+ }
+ }
+ return wantarray ? ($v1, $v2) : $v1;
+}
sub update_lxc_config {
my ($vmid, $conf) = @_;
@@ -380,6 +408,8 @@ sub update_lxc_config {
# files while the container is running!
$raw .= "lxc.monitor.unshare = 1\n";
+ my $cgv1 = get_cgroup_subsystems();
+
# Should we read them from /etc/subuid?
if ($unprivileged && !$custom_idmap) {
$raw .= "lxc.idmap = u 0 100000 65536\n";
@@ -388,7 +418,7 @@ sub update_lxc_config {
if (!PVE::LXC::Config->has_dev_console($conf)) {
$raw .= "lxc.console.path = none\n";
- $raw .= "lxc.cgroup.devices.deny = c 5:1 rwm\n";
+ $raw .= "lxc.cgroup.devices.deny = c 5:1 rwm\n" if $cgv1->{devices};
}
my $ttycount = PVE::LXC::Config->get_tty_count($conf);
@@ -400,23 +430,27 @@ sub update_lxc_config {
my $utsname = $conf->{hostname} || "CT$vmid";
$raw .= "lxc.uts.name = $utsname\n";
- my $memory = $conf->{memory} || 512;
- my $swap = $conf->{swap} // 0;
-
- my $lxcmem = int($memory*1024*1024);
- $raw .= "lxc.cgroup.memory.limit_in_bytes = $lxcmem\n";
+ if ($cgv1->{memory}) {
+ my $memory = $conf->{memory} || 512;
+ my $swap = $conf->{swap} // 0;
- my $lxcswap = int(($memory + $swap)*1024*1024);
- $raw .= "lxc.cgroup.memory.memsw.limit_in_bytes = $lxcswap\n";
+ my $lxcmem = int($memory*1024*1024);
+ $raw .= "lxc.cgroup.memory.limit_in_bytes = $lxcmem\n";
- if (my $cpulimit = $conf->{cpulimit}) {
- $raw .= "lxc.cgroup.cpu.cfs_period_us = 100000\n";
- my $value = int(100000*$cpulimit);
- $raw .= "lxc.cgroup.cpu.cfs_quota_us = $value\n";
+ my $lxcswap = int(($memory + $swap)*1024*1024);
+ $raw .= "lxc.cgroup.memory.memsw.limit_in_bytes = $lxcswap\n";
}
- my $shares = $conf->{cpuunits} || 1024;
- $raw .= "lxc.cgroup.cpu.shares = $shares\n";
+ if ($cgv1->{cpu}) {
+ if (my $cpulimit = $conf->{cpulimit}) {
+ $raw .= "lxc.cgroup.cpu.cfs_period_us = 100000\n";
+ my $value = int(100000*$cpulimit);
+ $raw .= "lxc.cgroup.cpu.cfs_quota_us = $value\n";
+ }
+
+ my $shares = $conf->{cpuunits} || 1024;
+ $raw .= "lxc.cgroup.cpu.shares = $shares\n";
+ }
die "missing 'rootfs' configuration\n"
if !defined($conf->{rootfs});
@@ -436,28 +470,30 @@ sub update_lxc_config {
$raw .= "lxc.net.$ind.mtu = $d->{mtu}\n" if defined($d->{mtu});
}
- my $had_cpuset = 0;
- if (my $lxcconf = $conf->{lxc}) {
- foreach my $entry (@$lxcconf) {
- my ($k, $v) = @$entry;
- $had_cpuset = 1 if $k eq 'lxc.cgroup.cpuset.cpus';
- $raw .= "$k = $v\n";
+ if ($cgv1->{cpuset}) {
+ my $had_cpuset = 0;
+ if (my $lxcconf = $conf->{lxc}) {
+ foreach my $entry (@$lxcconf) {
+ my ($k, $v) = @$entry;
+ $had_cpuset = 1 if $k eq 'lxc.cgroup.cpuset.cpus';
+ $raw .= "$k = $v\n";
+ }
}
- }
- my $cores = $conf->{cores};
- if (!$had_cpuset && $cores) {
- my $cpuset = eval { PVE::CpuSet->new_from_cgroup('lxc', 'effective_cpus') };
- $cpuset = PVE::CpuSet->new_from_cgroup('', 'effective_cpus') if !$cpuset;
- my @members = $cpuset->members();
- while (scalar(@members) > $cores) {
- my $randidx = int(rand(scalar(@members)));
- $cpuset->delete($members[$randidx]);
- splice(@members, $randidx, 1); # keep track of the changes
+ my $cores = $conf->{cores};
+ if (!$had_cpuset && $cores) {
+ my $cpuset = eval { PVE::CpuSet->new_from_cgroup('lxc', 'effective_cpus') };
+ $cpuset = PVE::CpuSet->new_from_cgroup('', 'effective_cpus') if !$cpuset;
+ my @members = $cpuset->members();
+ while (scalar(@members) > $cores) {
+ my $randidx = int(rand(scalar(@members)));
+ $cpuset->delete($members[$randidx]);
+ splice(@members, $randidx, 1); # keep track of the changes
+ }
+ $raw .= "lxc.cgroup.cpuset.cpus = ".$cpuset->short_string()."\n";
}
- $raw .= "lxc.cgroup.cpuset.cpus = ".$cpuset->short_string()."\n";
}
-
+
File::Path::mkpath("$dir/rootfs");
PVE::Tools::file_set_contents("$dir/config", $raw);
--
2.11.0
More information about the pve-devel
mailing list