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', {
'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,
'lxc.start.order' => 1,
'lxc.group' => 1,
'lxc.environment' => 1,
- 'lxc.' => 1,
- 'lxc.' => 1,
- 'lxc.' => 1,
- 'lxc.' => 1,
};
my $netconf_desc = {
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";
}
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} = {};
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);
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};
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);
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;
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;
}