]> git.proxmox.com Git - pve-container.git/blobdiff - src/PVE/LXC.pm
Fix #881: uninitialized value on valid lxc.cgroup keys
[pve-container.git] / src / PVE / LXC.pm
index 2899fa966876139c1a57f4bed53625b8b07660c1..f761f33b564e28b822bfb6d861f9ee9478774aa7 100644 (file)
@@ -54,6 +54,18 @@ my $rootfs_desc = {
        description => 'Volume size (read only value).',
        optional => 1,
     },
+    acl => {
+       type => 'boolean',
+       format_description => 'acl',
+       description => 'Explicitly enable or disable ACL support.',
+       optional => 1,
+    },
+    ro => {
+       type => 'boolean',
+       format_description => 'ro',
+       description => 'Read-only mountpoint (not supported with bind mounts)',
+       optional => 1,
+    },
 };
 
 PVE::JSONSchema::register_standard_option('pve-ct-rootfs', {
@@ -231,9 +243,10 @@ my $valid_lxc_conf_keys = {
     'lxc.mount' => 1,
     'lxc.mount.entry' => 1,
     'lxc.mount.auto' => 1,
-    'lxc.rootfs' => 1,
+    'lxc.rootfs' => 'lxc.rootfs is auto generated from rootfs',
     'lxc.rootfs.mount' => 1,
-    'lxc.rootfs.options' => 1,
+    'lxc.rootfs.options' => 'lxc.rootfs.options is not supported' .
+                            ', please use mountpoint options in the "rootfs" key',
     # lxc.cgroup.*
     'lxc.cap.drop' => 1,
     'lxc.cap.keep' => 1,
@@ -257,10 +270,6 @@ my $valid_lxc_conf_keys = {
     'lxc.start.order' => 1,
     'lxc.group' => 1,
     'lxc.environment' => 1,
-    'lxc.' => 1,
-    'lxc.' => 1,
-    'lxc.' => 1,
-    'lxc.' => 1,
 };
 
 my $netconf_desc = {
@@ -508,8 +517,11 @@ sub parse_pct_config {
        if ($line =~ m/^(lxc\.[a-z0-9_\-\.]+)(:|\s*=)\s*(.*?)\s*$/) {
            my $key = $1;
            my $value = $3;
-           if ($valid_lxc_conf_keys->{$key} || $key =~ m/^lxc\.cgroup\./) {
+           my $validity = $valid_lxc_conf_keys->{$key} || 0;
+           if ($validity eq 1 || $key =~ m/^lxc\.cgroup\./) {
                push @{$conf->{lxc}}, [$key, $value];
+           } elsif (my $errmsg = $validity) {
+               warn "vm $vmid - $key: $errmsg\n";
            } else {
                warn "vm $vmid - unable to parse config: $line\n";
            }
@@ -1732,7 +1744,8 @@ my $snapshot_prepare = sub {
            if defined($conf->{snapshots}->{$snapname});
 
        my $storecfg = PVE::Storage::config();
-       die "snapshot feature is not available\n" if !has_feature('snapshot', $conf, $storecfg);
+       my $feature = $snapname eq 'vzdump' ? 'vzdump' : 'snapshot';
+       die "snapshot feature is not available\n" if !has_feature($feature, $conf, $storecfg);
 
        $snap = $conf->{snapshots}->{$snapname} = {};
 
@@ -1782,11 +1795,14 @@ sub has_feature {
     my ($feature, $conf, $storecfg, $snapname) = @_;
     
     my $err;
+    my $vzdump = $feature eq 'vzdump';
+    $feature = 'snapshot' if $vzdump;
 
     foreach_mountpoint($conf, sub {
        my ($ms, $mountpoint) = @_;
 
        return if $err; # skip further test
+       return if $vzdump && $ms ne 'rootfs' && !$mountpoint->{backup};
        
        $err = 1 if !PVE::Storage::volume_has_feature($storecfg, $feature, $mountpoint->{volume}, $snapname);
 
@@ -1865,17 +1881,29 @@ sub snapshot_delete {
 
     my $storecfg = PVE::Storage::config();
 
-    my $del_snap =  sub {
+    my $unlink_parent = sub {
 
-       check_lock($conf);
+       my ($confref, $new_parent) = @_;
 
-       if ($conf->{parent} eq $snapname) {
-           if ($conf->{snapshots}->{$snapname}->{snapname}) {
-               $conf->{parent} = $conf->{snapshots}->{$snapname}->{parent};
+       if ($confref->{parent} && $confref->{parent} eq $snapname) {
+           if ($new_parent) {
+               $confref->{parent} = $new_parent;
            } else {
-               delete $conf->{parent};
+               delete $confref->{parent};
            }
        }
+    };
+
+    my $del_snap =  sub {
+
+       check_lock($conf);
+
+       my $parent = $conf->{snapshots}->{$snapname}->{parent};
+       foreach my $snapkey (keys %{$conf->{snapshots}}) {
+           &$unlink_parent($conf->{snapshots}->{$snapkey}, $parent);
+       }
+
+       &$unlink_parent($conf, $parent);
 
        delete $conf->{snapshots}->{$snapname};
 
@@ -2174,6 +2202,17 @@ sub mountpoint_mount {
 
     die "unknown snapshot path for '$volid'" if !$storage && defined($snapname);
 
+    my $optstring = '';
+    if (defined($mountpoint->{acl})) {
+       $optstring .= ($mountpoint->{acl} ? 'acl' : 'noacl');
+    }
+    if ($mountpoint->{ro}) {
+       $optstring .= ',' if $optstring;
+       $optstring .= 'ro';
+    }
+
+    my @extra_opts = ('-o', $optstring);
+
     if ($storage) {
 
        my $scfg = PVE::Storage::storage_config($storage_cfg, $storage);
@@ -2190,18 +2229,20 @@ sub mountpoint_mount {
                    if ($scfg->{type} eq 'zfspool') {
                        my $path_arg = $path;
                        $path_arg =~ s!^/+!!;
-                       PVE::Tools::run_command(['mount', '-o', 'ro', '-t', 'zfs', $path_arg, $mount_path]);
+                       PVE::Tools::run_command(['mount', '-o', 'ro', @extra_opts, '-t', 'zfs', $path_arg, $mount_path]);
                    } else {
                        die "cannot mount subvol snapshots for storage type '$scfg->{type}'\n";
                    }
                } else {
-                   PVE::Tools::run_command(['mount', '-o', 'bind', $path, $mount_path]);
+                   if ($mountpoint->{ro}) {
+                       die "read-only bind mounts not supported\n";
+                   }
+                   PVE::Tools::run_command(['mount', '-o', 'bind', @extra_opts, $path, $mount_path]);
                }
            }
            return wantarray ? ($path, 0) : $path;
        } elsif ($format eq 'raw' || $format eq 'iso') {
            my $use_loopdev = 0;
-           my @extra_opts;
            if ($scfg->{path}) {
                push @extra_opts, '-o', 'loop';
                $use_loopdev = 1;
@@ -2225,12 +2266,18 @@ sub mountpoint_mount {
            die "unsupported image format '$format'\n";
        }
     } elsif ($type eq 'device') {
-       PVE::Tools::run_command(['mount', $volid, $mount_path]) if $mount_path;
+       PVE::Tools::run_command(['mount', @extra_opts, $volid, $mount_path]) if $mount_path;
        return wantarray ? ($volid, 0) : $volid;
     } elsif ($type eq 'bind') {
+       if ($mountpoint->{ro}) {
+           die "read-only bind mounts not supported\n";
+           # Theoretically we'd have to execute both:
+           # mount -o bind $a $b
+           # mount -o bind,remount,ro $a $b
+       }
        die "directory '$volid' does not exist\n" if ! -d $volid;
        &$check_mount_path($volid);
-       PVE::Tools::run_command(['mount', '-o', 'bind', $volid, $mount_path]) if $mount_path;
+       PVE::Tools::run_command(['mount', '-o', 'bind', @extra_opts, $volid, $mount_path]) if $mount_path;
        return wantarray ? ($volid, 0) : $volid;
     }