I move related helper methods into PVE::QemuServer. Signed-off-by: Dietmar Maurer <diet...@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 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel