[pve-devel] [PATCH v3 7/9] vm_start: apply pending changes
Dietmar Maurer
dietmar at proxmox.com
Mon Nov 17 10:47:23 CET 2014
I move related helper methods into PVE::QemuServer.
Signed-off-by: Dietmar Maurer <dietmar at proxmox.com>
---
PVE/API2/Qemu.pm | 111 ++++-------------------------------------------------
PVE/QemuServer.pm | 103 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 111 insertions(+), 103 deletions(-)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index bfd3e2c..a3dbb06 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -37,26 +37,12 @@ my $resolve_cdrom_alias = sub {
}
};
-my $vm_is_volid_owner = sub {
- my ($storecfg, $vmid, $volid) =@_;
-
- if ($volid !~ m|^/|) {
- my ($path, $owner);
- eval { ($path, $owner) = PVE::Storage::path($storecfg, $volid); };
- if ($owner && ($owner == $vmid)) {
- return 1;
- }
- }
-
- return undef;
-};
-
my $test_deallocate_drive = sub {
my ($storecfg, $vmid, $key, $drive, $force) = @_;
if (!PVE::QemuServer::drive_is_cdrom($drive)) {
my $volid = $drive->{file};
- if (&$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;
@@ -67,44 +53,6 @@ my $test_deallocate_drive = sub {
return undef;
};
-my $pending_delete_option = sub {
- 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);
-};
-
-my $pending_undelete_option = sub {
- my ($conf, $key) = @_;
-
- my $pending_delete_hash = {};
- foreach my $opt (PVE::Tools::split_list($conf->{pending}->{delete})) {
- $pending_delete_hash->{$opt} = 1;
- }
- delete $pending_delete_hash->{$key};
-
- my @keylist = keys %$pending_delete_hash;
- if (scalar(@keylist)) {
- $conf->{pending}->{delete} = join(',', @keylist);
- } else {
- delete $conf->{pending}->{delete};
- }
-};
-
-my $register_unused_drive = sub {
- my ($storecfg, $vmid, $conf, $drive) = @_;
- if (!PVE::QemuServer::drive_is_cdrom($drive)) {
- my $volid = $drive->{file};
- if (&$vm_is_volid_owner($storecfg, $vmid, $volid)) {
- PVE::QemuServer::add_unused_volume($conf, $volid, $vmid);
- }
- }
-};
-
my $check_storage_access = sub {
my ($rpcenv, $authuser, $storecfg, $vmid, $settings, $default_storage) = @_;
@@ -712,7 +660,7 @@ my $delete_drive = sub {
if (!PVE::QemuServer::drive_is_cdrom($drive)) {
my $volid = $drive->{file};
- if (&$vm_is_volid_owner($storecfg, $vmid, $volid)) {
+ if (PVE::QemuServer::vm_is_volid_owner($storecfg, $vmid, $volid)) {
if ($force || $key =~ m/^unused/) {
eval {
# check if the disk is really unused
@@ -905,48 +853,6 @@ my $vmconfig_update_net = sub {
die "error hotplug $opt" if !PVE::QemuServer::vm_deviceplug($storecfg, $conf, $vmid, $opt, $net);
};
-my $vmconfig_apply_pending = sub {
- my ($vmid, $conf, $storecfg, $running) = @_;
-
- my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
- foreach my $opt (@delete) { # delete
- die "internal error" if $opt =~ m/^unused/;
- $conf = PVE::QemuServer::load_config($vmid); # update/reload
- if (!defined($conf->{$opt})) {
- &$pending_undelete_option($conf, $opt);
- PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
- } elsif (PVE::QemuServer::valid_drivename($opt)) {
- &$register_unused_drive($storecfg, $vmid, $conf, PVE::QemuServer::parse_drive($opt, $conf->{$opt}));
- &$pending_undelete_option($conf, $opt);
- delete $conf->{$opt};
- PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
- } else {
- &$pending_undelete_option($conf, $opt);
- delete $conf->{$opt};
- PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
- }
- }
-
- $conf = PVE::QemuServer::load_config($vmid); # update/reload
-
- foreach my $opt (keys %{$conf->{pending}}) { # add/change
- $conf = PVE::QemuServer::load_config($vmid); # update/reload
-
- if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
- # skip if nothing changed
- } elsif (PVE::QemuServer::valid_drivename($opt)) {
- &$register_unused_drive($storecfg, $vmid, $conf, PVE::QemuServer::parse_drive($opt, $conf->{$opt}))
- if defined($conf->{$opt});
- $conf->{$opt} = $conf->{pending}->{$opt};
- } else {
- $conf->{$opt} = $conf->{pending}->{$opt};
- }
-
- delete $conf->{pending}->{$opt};
- PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
- }
-};
-
# POST/PUT {vmid}/config implementation
#
# The original API used PUT (idempotent) an we assumed that all operations
@@ -1068,12 +974,12 @@ my $update_vm_api = sub {
}
} elsif (PVE::QemuServer::valid_drivename($opt)) {
$rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
- &$register_unused_drive($storecfg, $vmid, $conf, PVE::QemuServer::parse_drive($opt, $conf->{pending}->{$opt}))
+ PVE::QemuServer::vmconfig_register_unused_drive($storecfg, $vmid, $conf, PVE::QemuServer::parse_drive($opt, $conf->{pending}->{$opt}))
if defined($conf->{pending}->{$opt});
- &$pending_delete_option($conf, $opt);
+ PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt);
PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
} else {
- &$pending_delete_option($conf, $opt);
+ PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt);
PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
}
}
@@ -1089,14 +995,14 @@ my $update_vm_api = sub {
} else {
$rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
}
- &$register_unused_drive($storecfg, $vmid, $conf, PVE::QemuServer::parse_drive($opt, $conf->{pending}->{$opt}))
+ PVE::QemuServer::vmconfig_register_unused_drive($storecfg, $vmid, $conf, PVE::QemuServer::parse_drive($opt, $conf->{pending}->{$opt}))
if defined($conf->{pending}->{$opt});
&$create_disks($rpcenv, $authuser, $conf->{pending}, $storecfg, $vmid, undef, {$opt => $param->{$opt}});
} else {
$conf->{pending}->{$opt} = $param->{$opt};
}
- &$pending_undelete_option($conf, $opt);
+ PVE::QemuServer::vmconfig_undelete_pending_option($conf, $opt);
PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
}
@@ -1114,12 +1020,11 @@ my $update_vm_api = sub {
return if !scalar(keys %{$conf->{pending}});
my $running = PVE::QemuServer::check_running($vmid);
- die "implement me - vm is running" if $running; # fixme: if $conf->{hotplug};
# apply pending changes
$conf = PVE::QemuServer::load_config($vmid); # update/reload
- &$vmconfig_apply_pending($vmid, $conf, $storecfg, $running);
+ PVE::QemuServer::vmconfig_apply_pending($vmid, $conf, $storecfg, $running);
return; # TODO: remove old code below
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 26b0efc..2dd4558 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1389,6 +1389,59 @@ sub add_unused_volume {
return $key;
}
+sub vm_is_volid_owner {
+ my ($storecfg, $vmid, $volid) = @_;
+
+ if ($volid !~ m|^/|) {
+ my ($path, $owner);
+ eval { ($path, $owner) = PVE::Storage::path($storecfg, $volid); };
+ if ($owner && ($owner == $vmid)) {
+ return 1;
+ }
+ }
+
+ 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) = @_;
+
+ my $pending_delete_hash = {};
+ foreach my $opt (PVE::Tools::split_list($conf->{pending}->{delete})) {
+ $pending_delete_hash->{$opt} = 1;
+ }
+ delete $pending_delete_hash->{$key};
+
+ my @keylist = keys %$pending_delete_hash;
+ if (scalar(@keylist)) {
+ $conf->{pending}->{delete} = join(',', @keylist);
+ } else {
+ delete $conf->{pending}->{delete};
+ }
+}
+
+sub vmconfig_register_unused_drive {
+ my ($storecfg, $vmid, $conf, $drive) = @_;
+
+ if (!drive_is_cdrom($drive)) {
+ my $volid = $drive->{file};
+ if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
+ add_unused_volume($conf, $volid, $vmid);
+ }
+ }
+}
+
my $valid_smbios1_options = {
manufacturer => '\S+',
product => '\S+',
@@ -3379,6 +3432,51 @@ sub set_migration_caps {
vm_mon_cmd_nocheck($vmid, "migrate-set-capabilities", capabilities => $cap_ref);
}
+
+sub vmconfig_apply_pending {
+ my ($vmid, $conf, $storecfg, $running) = @_;
+
+ die "implement me - vm is running" if $running; # fixme: if $conf->{hotplug};
+
+ my @delete = PVE::Tools::split_list($conf->{pending}->{delete});
+ foreach my $opt (@delete) { # delete
+ 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}));
+ vmconfig_undelete_pending_option($conf, $opt);
+ delete $conf->{$opt};
+ update_config_nolock($vmid, $conf, 1);
+ } else {
+ vmconfig_undelete_pending_option($conf, $opt);
+ delete $conf->{$opt};
+ update_config_nolock($vmid, $conf, 1);
+ }
+ }
+
+ $conf = load_config($vmid); # update/reload
+
+ foreach my $opt (keys %{$conf->{pending}}) { # add/change
+ $conf = load_config($vmid); # update/reload
+
+ if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
+ # skip if nothing changed
+ } elsif (valid_drivename($opt)) {
+ vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
+ if defined($conf->{$opt});
+ $conf->{$opt} = $conf->{pending}->{$opt};
+ } else {
+ $conf->{$opt} = $conf->{pending}->{$opt};
+ }
+
+ delete $conf->{pending}->{$opt};
+ update_config_nolock($vmid, $conf, 1);
+ }
+}
+
sub vm_start {
my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused, $forcemachine, $spice_ticket) = @_;
@@ -3391,6 +3489,11 @@ sub vm_start {
die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
+ if (!$statefile && scalar(keys %{$conf->{pending}})) {
+ vmconfig_apply_pending($vmid, $conf, $storecfg, 0);
+ $conf = load_config($vmid); # update/reload
+ }
+
my $defaults = load_defaults();
# set environment variable useful inside network script
--
1.7.10.4
More information about the pve-devel
mailing list