use strict;
use warnings;
+
use Fcntl qw(O_RDONLY);
use PVE::AbstractConfig;
use PVE::JSONSchema qw(get_standard_option);
use PVE::Tools;
+use PVE::LXC;
+
use base qw(PVE::AbstractConfig);
-use constant {FIFREEZE => 0xc0045877,
- FITHAW => 0xc0045878};
+use constant {
+ FIFREEZE => 0xc0045877,
+ FITHAW => 0xc0045878,
+};
my $nodename = PVE::INotify::nodename();
my $lock_handles = {};
return if $err; # skip further test
return if $backup_only && !$class->mountpoint_backup_enabled($ms, $mountpoint);
- $err = 1
- if !PVE::Storage::volume_has_feature($storecfg, $feature,
- $mountpoint->{volume},
- $snapname, $running, $opts);
+ $err = 1 if !PVE::Storage::volume_has_feature(
+ $storecfg, $feature, $mountpoint->{volume}, $snapname, $running, $opts);
});
return $err ? 0 : 1;
lock => {
optional => 1,
type => 'string',
- description => "Lock/unlock the VM.",
+ description => "Lock/unlock the container.",
enum => [qw(backup create destroyed disk fstrim migrate mounted rollback snapshot snapshot-delete)],
},
onboot => {
optional => 1,
type => 'boolean',
- description => "Specifies whether a VM will be started during system bootup.",
+ description => "Specifies whether a container will be started during system bootup.",
default => 0,
},
startup => get_standard_option('pve-startup-order'),
arch => {
optional => 1,
type => 'string',
- enum => ['amd64', 'i386', 'arm64', 'armhf'],
+ enum => ['amd64', 'i386', 'arm64', 'armhf', 'riscv32', 'riscv64'],
description => "OS architecture type.",
default => 'amd64',
},
cpuunits => {
optional => 1,
type => 'integer',
- description => "CPU weight for a VM. Argument is used in the kernel fair scheduler. The larger the number is, the more CPU time this VM gets. Number is relative to the weights of all the other running VMs.\n\nNOTE: You can disable fair-scheduler configuration by setting this to 0.",
+ description => "CPU weight for a container, will be clamped to [1, 10000] in cgroup v2.",
+ verbose_description => "CPU weight for a container. Argument is used in the kernel fair "
+ ."scheduler. The larger the number is, the more CPU time this container gets. Number "
+ ."is relative to the weights of all the other running guests.",
minimum => 0,
maximum => 500000,
- default => 1024,
+ default => 'cgroup v1: 1024, cgroup v2: 100',
},
memory => {
optional => 1,
type => 'integer',
- description => "Amount of RAM for the VM in MB.",
+ description => "Amount of RAM for the container in MB.",
minimum => 16,
default => 512,
},
swap => {
optional => 1,
type => 'integer',
- description => "Amount of SWAP for the VM in MB.",
+ description => "Amount of SWAP for the container in MB.",
minimum => 0,
default => 512,
},
type => 'integer',
description => 'Maximum transfer unit of the interface. (lxc.network.mtu)',
minimum => 64, # minimum ethernet frame is 64 bytes
+ maximum => 65535,
optional => 1,
},
ip => {
description => "Apply rate limiting to the interface",
optional => 1,
},
+ # TODO: Rename this option and the qemu-server one to `link-down` for PVE 8.0
+ link_down => {
+ type => 'boolean',
+ description => 'Whether this interface should be disconnected (like pulling the plug).',
+ optional => 1,
+ },
};
PVE::JSONSchema::register_format('pve-lxc-network', $netconf_desc);
$value = PVE::LXC::verify_searchdomain_list($value);
} elsif ($opt eq 'unprivileged') {
die "unable to modify read-only option: '$opt'\n";
+ } elsif ($opt eq 'tags') {
+ $value = PVE::GuestHelpers::get_unique_tags($value);
+ } elsif ($opt =~ m/^net(\d+)$/) {
+ my $res = PVE::JSONSchema::parse_property_string($netconf_desc, $value);
+
+ if (my $mtu = $res->{mtu}) {
+ my $bridge_mtu = PVE::Network::read_bridge_mtu($res->{bridge});
+ die "$opt: MTU size '$mtu' is bigger than bridge MTU '$bridge_mtu'\n"
+ if ($mtu > $bridge_mtu);
+ }
}
$conf->{pending}->{$opt} = $value;
$class->remove_from_pending_delete($conf, $opt);
sub parse_lxc_network {
my ($class, $data) = @_;
- my $res = {};
-
- return $res if !$data;
+ return {} if !$data;
- $res = PVE::JSONSchema::parse_property_string($netconf_desc, $data);
+ my $res = PVE::JSONSchema::parse_property_string($netconf_desc, $data);
$res->{type} = 'veth';
if (!$res->{hwaddr}) {
}
# END JSON config code
+# takes a max memory value as KiB and returns an tuple with max and high values
+sub calculate_memory_constraints {
+ my ($memory) = @_;
+
+ return if !defined($memory);
+
+ # cgroup memory usage is limited by the hard 'max' limit (OOM-killer enforced) and the soft
+ # 'high' limit (cgroup processes get throttled and put under heavy reclaim pressure).
+ my $memory_max = int($memory * 1024 * 1024);
+ # Set the high to 1016/1024 (~99.2%) of the 'max' hard limit clamped to 128 MiB max, to scale
+ # it for the lower range while having a decent 2^x based rest for 2^y memory configs.
+ my $memory_high = $memory >= 16 * 1024 ? int(($memory - 128) * 1024 * 1024) : int($memory * 1024 * 1016);
+
+ return ($memory_max, $memory_high);
+}
+
my $LXC_FASTPLUG_OPTIONS= {
'description' => 1,
'onboot' => 1,
# memory (iow. memory+swap). This means we have to change them together.
my $hotplug_memory_done;
my $hotplug_memory = sub {
- my ($wanted_memory, $wanted_swap) = @_;
+ my ($new_memory, $new_swap) = @_;
- $wanted_memory = int($wanted_memory * 1024 * 1024) if defined($wanted_memory);
- $wanted_swap = int($wanted_swap * 1024 * 1024) if defined($wanted_swap);
- $cgroup->change_memory_limit($wanted_memory, $wanted_swap);
+ ($new_memory, my $new_memory_high) = calculate_memory_constraints($new_memory);
+ $new_swap = int($new_swap * 1024 * 1024) if defined($new_swap);
+ $cgroup->change_memory_limit($new_memory, $new_swap, $new_memory_high);
$hotplug_memory_done = 1;
};
} elsif ($opt eq 'cpulimit') {
$cgroup->change_cpu_quota(undef, undef); # reset, cgroup module can better decide values
} elsif ($opt eq 'cpuunits') {
- $cgroup->change_cpu_shares(undef, $confdesc->{cpuunits}->{default});
+ $cgroup->change_cpu_shares(undef);
} elsif ($opt =~ m/^net(\d)$/) {
my $netid = $1;
PVE::Network::veth_delete("veth${vmid}i$netid");
my $quota = 100000 * $value;
$cgroup->change_cpu_quota(int(100000 * $value), 100000);
} elsif ($opt eq 'cpuunits') {
- $cgroup->change_cpu_shares($value, $confdesc->{cpuunits}->{default});
+ $cgroup->change_cpu_shares($value);
} elsif ($opt =~ m/^net(\d+)$/) {
my $netid = $1;
my $net = $class->parse_lxc_network($value);
return $return_volumes;
}
+sub get_derived_property {
+ my ($class, $conf, $name) = @_;
+
+ if ($name eq 'max-cpu') {
+ return $conf->{cpulimit} || $conf->{cores} || 0;
+ } elsif ($name eq 'max-memory') {
+ return ($conf->{memory} || 512) * 1024 * 1024;
+ } else {
+ die "unknown derived property - $name\n";
+ }
+}
+
1;