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_stop {
my ($class, $vmid) = @_;
- PVE::Tools::run_command(['/usr/bin/lxc-stop', '-n', $vmid, '--kill'])
+ PVE::LXC::vm_stop($vmid, 1)
if $class->__snapshot_check_running($vmid);
}
optional => 1,
type => 'string',
description => "Lock/unlock the VM.",
- enum => [qw(migrate backup snapshot rollback)],
+ enum => [qw(mounted migrate backup snapshot rollback)],
},
onboot => {
optional => 1,
ip => {
type => 'string',
format => 'pve-ipv4-config',
- format_description => 'IPv4Format/CIDR',
+ format_description => '(IPv4/CIDR|dhcp|manual)',
description => 'IPv4 address in CIDR format.',
optional => 1,
},
ip6 => {
type => 'string',
format => 'pve-ipv6-config',
- format_description => 'IPv6Format/CIDR',
+ format_description => '(IPv6/CIDR|auto|dhcp|manual)',
description => 'IPv6 address in CIDR format.',
optional => 1,
},
if !$storage_config->{content}->{rootdir};
};
+ my $rescan_volume = sub {
+ my ($mp) = @_;
+ eval {
+ $mp->{size} = PVE::Storage::volume_size_info($storecfg, $mp->{volume}, 5)
+ if !defined($mp->{size});
+ };
+ warn "Could not rescan volume size - $@\n" if $@;
+ };
+
foreach my $opt (keys %$param) {
my $value = $param->{$opt};
my $check_protection_msg = "can't update CT $vmid drive '$opt'";
$conf->{$opt} = $value;
PVE::LXC::write_cgroup_value("cpu", $vmid, "cpu.shares", $value);
} elsif ($opt eq 'description') {
- $conf->{$opt} = PVE::Tools::encode_text($value);
+ $conf->{$opt} = $value;
} elsif ($opt =~ m/^net(\d+)$/) {
my $netid = $1;
my $net = PVE::LXC::Config->parse_lxc_network($value);
if ($mp->{type} eq 'volume') {
&$check_content_type($mp);
$used_volids->{$mp->{volume}} = 1;
+ &$rescan_volume($mp);
+ $conf->{$opt} = PVE::LXC::Config->print_ct_mountpoint($mp);
+ } else {
+ $conf->{$opt} = $value;
}
- $conf->{$opt} = $value;
if (defined($old)) {
my $mp = PVE::LXC::Config->parse_ct_mountpoint($old);
if ($mp->{type} eq 'volume') {
next if $hotplug_error->($opt);
PVE::LXC::Config->check_protection($conf, $check_protection_msg);
my $old = $conf->{$opt};
- $conf->{$opt} = $value;
my $mp = PVE::LXC::Config->parse_ct_rootfs($value);
if ($mp->{type} eq 'volume') {
&$check_content_type($mp);
$used_volids->{$mp->{volume}} = 1;
+ &$rescan_volume($mp);
+ $conf->{$opt} = PVE::LXC::Config->print_ct_mountpoint($mp, 1);
+ } else {
+ $conf->{$opt} = $value;
}
if (defined($old)) {
my $mp = PVE::LXC::Config->parse_ct_rootfs($old);
return 'volume';
}
-sub is_volume_in_use {
- my ($class, $config, $volid, $include_snapshots) = @_;
+my $is_volume_in_use = sub {
+ my ($class, $config, $volid) = @_;
my $used = 0;
$class->foreach_mountpoint($config, sub {
$used = $mountpoint->{type} eq 'volume' && $mountpoint->{volume} eq $volid;
});
- my $snapshots = $config->{snapshots};
- if ($include_snapshots && $snapshots) {
+ return $used;
+};
+
+sub is_volume_in_use_by_snapshots {
+ my ($class, $config, $volid) = @_;
+
+ if (my $snapshots = $config->{snapshots}) {
foreach my $snap (keys %$snapshots) {
- $used ||= $class->is_volume_in_use($snapshots->{$snap}, $volid);
+ return 1 if $is_volume_in_use->($class, $snapshots->{$snap}, $volid);
}
}
- return $used;
+ return 0;
+};
+
+sub is_volume_in_use {
+ my ($class, $config, $volid, $include_snapshots) = @_;
+ return 1 if $is_volume_in_use->($class, $config, $volid);
+ return 1 if $include_snapshots && $class->is_volume_in_use_by_snapshots($config, $volid);
+ return 0;
}
sub has_dev_console {
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);
return if !$volid;
my $mptype = $mountpoint->{type};
- die "unable to replicate mountpoint type '$mptype'\n"
- if $mptype ne 'volume';
+ my $replicate = $mountpoint->{replicate} // 1;
+
+ if ($mptype ne 'volume') {
+ # skip bindmounts if replicate = 0 even for cleanup,
+ # since bind mounts could not have been replicated ever
+ return if !$replicate;
+ die "unable to replicate mountpoint type '$mptype'\n";
+ }
my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, $noerr);
return if !$storeid;
die "unable to replicate volume '$volid', type '$vtype'\n" if $vtype ne 'images';
- return if !$cleanup && defined($mountpoint->{replicate}) && !$mountpoint->{replicate};
+ return if !$cleanup && !$replicate;
if (!PVE::Storage::volume_has_feature($storecfg, 'replicate', $volid)) {
return if $cleanup || $noerr;