[pve-devel] [PATCH v10 qemu-server/cloudinit 8/8] add force_delete to [pending] to bring back -force
Wolfgang Bumiller
w.bumiller at proxmox.com
Tue Aug 11 15:51:55 CEST 2015
The -force flag didn't have any effect since the pending
changes didn't remember it before.
---
PVE/API2/Qemu.pm | 15 ++-----
PVE/QemuServer.pm | 128 +++++++++++++++++++++++++++++++++++++++---------------
2 files changed, 97 insertions(+), 46 deletions(-)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 4dcbb26..b5f817e 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -43,7 +43,7 @@ my $test_deallocate_drive = sub {
if (!PVE::QemuServer::drive_is_cdrom($drive, 1)) {
my $volid = $drive->{file};
- if ( PVE::QemuServer::vm_is_volid_owner($storecfg, $vmid, $volid)) {
+ if (PVE::QemuServer::vm_is_volid_owner($storecfg, $vmid, $volid)) {
if ($force || $key =~ m/^unused/) {
my $sid = PVE::Storage::parse_volume_id($volid);
return $sid;
@@ -222,14 +222,7 @@ my $delete_drive = sub {
if (PVE::QemuServer::vm_is_volid_owner($storecfg, $vmid, $volid)) {
if ($force || $key =~ m/^unused/) {
eval {
- # check if the disk is really unused
- my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
- my $path = PVE::Storage::path($storecfg, $volid);
-
- die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
- if $used_paths->{$path};
-
- PVE::Storage::vdisk_free($storecfg, $volid);
+ PVE::QemuServer::delete_drive($vmid, $storecfg, $conf, $key, $volid);
};
die $@ if $@;
} else {
@@ -964,10 +957,10 @@ my $update_vm_api = sub {
$rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
PVE::QemuServer::vmconfig_register_unused_drive($storecfg, $vmid, $conf, PVE::QemuServer::parse_drive($opt, $conf->{pending}->{$opt}))
if defined($conf->{pending}->{$opt});
- PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt);
+ PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt, $force);
PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
} else {
- PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt);
+ PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt, $force);
PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
}
}
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index da33b04..1fad769 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1517,34 +1517,45 @@ sub vm_is_volid_owner {
return undef;
}
-sub vmconfig_delete_pending_option {
- my ($conf, $key) = @_;
-
- delete $conf->{pending}->{$key};
- my $pending_delete_hash = { $key => 1 };
- foreach my $opt (PVE::Tools::split_list($conf->{pending}->{delete})) {
- $pending_delete_hash->{$opt} = 1;
- }
- $conf->{pending}->{delete} = join(',', keys %$pending_delete_hash);
-}
-
-sub vmconfig_undelete_pending_option {
- my ($conf, $key) = @_;
+sub _vmconfig_undelete_pending_option {
+ my ($conf, $key, $del) = @_;
my $pending_delete_hash = {};
- foreach my $opt (PVE::Tools::split_list($conf->{pending}->{delete})) {
+ foreach my $opt (PVE::Tools::split_list($conf->{pending}->{$del})) {
$pending_delete_hash->{$opt} = 1;
}
delete $pending_delete_hash->{$key};
my @keylist = keys %$pending_delete_hash;
if (scalar(@keylist)) {
- $conf->{pending}->{delete} = join(',', @keylist);
+ $conf->{pending}->{$del} = join(',', @keylist);
} else {
- delete $conf->{pending}->{delete};
+ delete $conf->{pending}->{$del};
}
}
+sub vmconfig_delete_pending_option {
+ my ($conf, $key, $force) = @_;
+
+ my $addto = $force ? 'force_delete' : 'delete';
+ my $removefrom = $force ? 'delete' : 'force_delete';
+
+ _vmconfig_undelete_pending_option($conf, $key, $removefrom);
+
+ delete $conf->{pending}->{$key};
+ my $pending_delete_hash = { $key => 1 };
+ foreach my $opt (PVE::Tools::split_list($conf->{pending}->{$addto})) {
+ $pending_delete_hash->{$opt} = 1;
+ }
+ $conf->{pending}->{$addto} = join(',', keys %$pending_delete_hash);
+}
+
+sub vmconfig_undelete_pending_option {
+ my ($conf, $key) = @_;
+ _vmconfig_undelete_pending_option($conf, $key, 'delete');
+ _vmconfig_undelete_pending_option($conf, $key, 'force_delete');
+}
+
sub vmconfig_register_unused_drive {
my ($storecfg, $vmid, $conf, $drive) = @_;
@@ -1569,20 +1580,22 @@ sub vmconfig_cleanup_pending {
}
# remove delete if option is not set
- my $pending_delete_hash = {};
- foreach my $opt (PVE::Tools::split_list($conf->{pending}->{delete})) {
- if (defined($conf->{$opt})) {
- $pending_delete_hash->{$opt} = 1;
- } else {
- $changes = 1;
+ foreach my $del (qw/force_delete delete/) {
+ my $pending_delete_hash = {};
+ foreach my $opt (PVE::Tools::split_list($conf->{pending}->{$del})) {
+ if (defined($conf->{$opt})) {
+ $pending_delete_hash->{$opt} = 1;
+ } else {
+ $changes = 1;
+ }
}
- }
- my @keylist = keys %$pending_delete_hash;
- if (scalar(@keylist)) {
- $conf->{pending}->{delete} = join(',', @keylist);
- } else {
- delete $conf->{pending}->{delete};
+ my @keylist = keys %$pending_delete_hash;
+ if (scalar(@keylist)) {
+ $conf->{pending}->{$del} = join(',', @keylist);
+ } else {
+ delete $conf->{pending}->{$del};
+ }
}
return $changes;
@@ -2019,6 +2032,13 @@ sub parse_vm_config {
} else {
warn "vm $vmid - propertry 'delete' is only allowed in [PENDING]\n";
}
+ } elsif ($line =~ m/^force_delete:\s*(.*\S)\s*$/) {
+ my $value = $1;
+ if ($section eq 'pending') {
+ $conf->{force_delete} = $value; # we parse this later
+ } else {
+ warn "vm $vmid - propertry 'force_delete' is only allowed in [PENDING]\n";
+ }
} elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
my $key = $1;
my $value = $2;
@@ -2083,8 +2103,8 @@ sub write_vm_config {
next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
$key eq 'snapstate' || $key eq 'pending';
my $value = $cref->{$key};
- if ($key eq 'delete') {
- die "propertry 'delete' is only allowed in [PENDING]\n"
+ if ($key =~ /^(?:force_)?delete$/) {
+ die "propertry '$key' is only allowed in [PENDING]\n"
if !$pending;
# fixme: check syntax?
next;
@@ -3993,8 +4013,8 @@ sub vmconfig_hotplug_pending {
my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
- my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
- foreach my $opt (@delete) {
+ my $delete_opt = sub {
+ my ($opt, $force) = @_;
next if $selection && !$selection->{$opt};
eval {
if ($opt eq 'hotplug') {
@@ -4041,6 +4061,12 @@ sub vmconfig_hotplug_pending {
update_config_nolock($vmid, $conf, 1);
$conf = load_config($vmid); # update/reload
}
+ };
+ foreach my $opt (PVE::Tools::split_list($conf->{pending}->{force_delete})) {
+ &$delete_opt($opt, 1);
+ }
+ foreach my $opt (PVE::Tools::split_list($conf->{pending}->{delete})) {
+ &$delete_opt($opt);
}
foreach my $opt (keys %{$conf->{pending}}) {
@@ -4102,20 +4128,45 @@ sub vmconfig_hotplug_pending {
}
}
+sub delete_drive {
+ my ($vmid, $storecfg, $conf, $key, $volid) = @_;
+
+ # check if the disk is really unused
+ my $used_paths = PVE::QemuServer::get_used_paths($vmid, $storecfg, $conf, 1, $key);
+ my $path = PVE::Storage::path($storecfg, $volid);
+
+ die "unable to delete '$volid' - volume is still in use (snapshot?)\n"
+ if $used_paths->{$path};
+ PVE::Storage::vdisk_free($storecfg, $volid);
+}
+
sub vmconfig_apply_pending {
my ($vmid, $conf, $storecfg) = @_;
# cold plug
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $authuser = $rpcenv->get_user();
- my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
- foreach my $opt (@delete) { # delete
+ my $delete_opt = sub {
+ my ($opt, $force) = @_;
die "internal error" if $opt =~ m/^unused/;
$conf = load_config($vmid); # update/reload
if (!defined($conf->{$opt})) {
vmconfig_undelete_pending_option($conf, $opt);
update_config_nolock($vmid, $conf, 1);
} elsif (valid_drivename($opt)) {
- vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}));
+ my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
+ if ($force) {
+ $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
+ my $volid = $drive->{file};
+ my $sid = PVE::Storage::parse_volume_id($volid);
+ if (PVE::QemuServer::vm_is_volid_owner($storecfg, $vmid, $volid)) {
+ $rpcenv->check($authuser, "/storage/$sid", ['Datastore.AllocateSpace']);
+ delete_drive($vmid, $storecfg, $conf, $opt, $volid);
+ }
+ } else {
+ vmconfig_register_unused_drive($storecfg, $vmid, $conf, $drive);
+ }
vmconfig_undelete_pending_option($conf, $opt);
delete $conf->{$opt};
update_config_nolock($vmid, $conf, 1);
@@ -4124,6 +4175,13 @@ sub vmconfig_apply_pending {
delete $conf->{$opt};
update_config_nolock($vmid, $conf, 1);
}
+ };
+
+ foreach my $opt (PVE::Tools::split_list($conf->{pending}->{force_delete})) {
+ &$delete_opt($opt, 1);
+ }
+ foreach my $opt (PVE::Tools::split_list($conf->{pending}->{delete})) {
+ &$delete_opt($opt);
}
$conf = load_config($vmid); # update/reload
--
2.1.4
More information about the pve-devel
mailing list