]> git.proxmox.com Git - pve-container.git/commitdiff
deal with disabled cgroup subsystems
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Thu, 21 Jun 2018 08:07:41 +0000 (10:07 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Fri, 6 Jul 2018 09:26:01 +0000 (11:26 +0200)
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@proxmox.com>
src/PVE/CLI/pct.pm
src/PVE/LXC.pm

index 16cd4ec07ddba0b915263dac488a2b64ad816e41..6296d6fc9aaa3b62d4d0b10ba5e6a1a45723d9f5 100755 (executable)
@@ -661,6 +661,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;
index 4be1579b2df5e435f3c03a8c642d8e8940206205..bc0379268bd7742a3533848b69ee6bebfb1793eb 100644 (file)
@@ -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);