my $lockdir = "/run/lock/lxc";
mkdir $lockdir;
mkdir "/etc/pve/nodes/$nodename/lxc";
-my $MAX_MOUNT_POINTS = 10;
+my $MAX_MOUNT_POINTS = 256;
my $MAX_UNUSED_DISKS = $MAX_MOUNT_POINTS;
# BEGIN implemented abstract methods from PVE::AbstractConfig
}
sub __snapshot_rollback_vm_start {
- my ($class, $vmid, $vmstate, $forcemachine);
+ my ($class, $vmid, $vmstate, $data);
die "implement me - save vmstate\n";
}
maxLength => 40,
});
+my $features_desc = {
+ mount => {
+ optional => 1,
+ type => 'string',
+ description => "Allow mounting file systems of specific types."
+ ." This should be a list of file system types as used with the mount command."
+ ." Note that this can have negative effects on the container's security."
+ ." With access to a loop device, mounting a file can circumvent the mknod"
+ ." permission of the devices cgroup, mounting an NFS file system can"
+ ." block the host's I/O completely and prevent it from rebooting, etc.",
+ format_description => 'fstype;fstype;...',
+ pattern => qr/[a-zA-Z0-9; ]+/,
+ },
+ nesting => {
+ optional => 1,
+ type => 'boolean',
+ default => 0,
+ description => "Allow nesting."
+ ." Best used with unprivileged containers with additional id mapping."
+ ." Note that this will expose procfs and sysfs contents of the host"
+ ." to the guest.",
+ },
+ keyctl => {
+ optional => 1,
+ type => 'boolean',
+ default => 0,
+ description => "For unprivileged containers only: Allow the use of the keyctl() system call."
+ ." This is required to use docker inside a container."
+ ." By default unprivileged containers will see this system call as non-existent."
+ ." This is mostly a workaround for systemd-networkd, as it will treat it as a fatal"
+ ." error when some keyctl() operations are denied by the kernel due to lacking permissions."
+ ." Essentially, you can choose between running systemd-networkd or docker.",
+ },
+};
+
my $confdesc = {
lock => {
optional => 1,
type => 'string',
description => "Lock/unlock the VM.",
- enum => [qw(mounted migrate backup snapshot rollback)],
+ enum => [qw(backup disk migrate mounted rollback snapshot snapshot-delete)],
},
onboot => {
optional => 1,
arch => {
optional => 1,
type => 'string',
- enum => ['amd64', 'i386'],
+ enum => ['amd64', 'i386', 'arm64', 'armhf'],
description => "OS architecture type.",
default => 'amd64',
},
description => "Makes the container run as unprivileged user. (Should not be modified manually.)",
default => 0,
},
+ features => {
+ optional => 1,
+ type => 'string',
+ format => $features_desc,
+ description => "Allow containers access to advanced features.",
+ },
};
my $valid_lxc_conf_keys = {
'lxc.apparmor.profile' => 1,
'lxc.apparmor.allow_incomplete' => 1,
+ 'lxc.apparmor.allow_nesting' => 1,
+ 'lxc.apparmor.raw' => 1,
'lxc.selinux.context' => 1,
'lxc.include' => 1,
'lxc.arch' => 1,
}
} elsif ($opt eq 'unprivileged') {
die "unable to delete read-only option: '$opt'\n";
+ } elsif ($opt eq 'features') {
+ next if $hotplug_error->($opt);
+ delete $conf->{$opt};
} else {
die "implement me (delete: $opt)"
}
} elsif ($opt eq 'ostype') {
next if $hotplug_error->($opt);
$conf->{$opt} = $value;
+ } elsif ($opt eq 'features') {
+ next if $hotplug_error->($opt);
+ $conf->{$opt} = $value;
} else {
die "implement me: $opt";
}
return $res;
}
+sub parse_features {
+ my ($class, $data) = @_;
+ return {} if !$data;
+ return PVE::JSONSchema::parse_property_string($features_desc, $data);
+}
+
sub option_exists {
my ($class, $name) = @_;
sub foreach_mountpoint_full {
my ($class, $conf, $reverse, $func, @param) = @_;
- foreach my $key ($class->mountpoint_names($reverse)) {
+ my $mps = [ grep { defined($conf->{$_}) } $class->mountpoint_names($reverse) ];
+ foreach my $key (@$mps) {
my $value = $conf->{$key};
- next if !defined($value);
my $mountpoint = $key eq 'rootfs' ? $class->parse_ct_rootfs($value, 1) : $class->parse_ct_mountpoint($value, 1);
next if !defined($mountpoint);