]> git.proxmox.com Git - qemu-server.git/commitdiff
update_vm rework
authorDerumier Alexandre <aderumier@odiso.com>
Thu, 26 Jan 2012 18:43:48 +0000 (19:43 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Fri, 27 Jan 2012 04:55:00 +0000 (05:55 +0100)
now we write conf after each option.

Signed-off-by: Derumier Alexandre <aderumier@odiso.com>
PVE/API2/Qemu.pm
PVE/QemuServer.pm

index 669be57ff8d6ca7f9cf982a6c546bbf4329aa55c..1e906fde085b6d043f6f7d32d2a0eda54100b9bb 100644 (file)
@@ -437,7 +437,6 @@ __PACKAGE__->register_method({
 
        my $digest = extract_param($param, 'digest');
 
-        my @hotplugerr = ();
        my @paramarr = (); # used for log message
        foreach my $key (keys %$param) {
            push @paramarr, "-$key", $param->{$key};
@@ -456,154 +455,124 @@ __PACKAGE__->register_method({
 
        &$resolve_cdrom_alias($param);
 
-       my $eject = {};
-       my $cdchange = {};
+       my $conf = PVE::QemuServer::load_config($vmid);
 
-       foreach my $opt (keys %$param) {
-           if (PVE::QemuServer::valid_drivename($opt)) {
-               my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt});
-               raise_param_exc({ $opt => "unable to parse drive options" }) if !$drive;
-               if ($drive->{file} eq 'eject') {
-                   $eject->{$opt} = 1;
-                   delete $param->{$opt};
-                   next;
-               }
+       die "checksum missmatch (file change by other user?)\n" 
+          if $digest && $digest ne $conf->{digest};
 
-               PVE::QemuServer::cleanup_drive_path($opt, $storecfg, $drive);
-               $param->{$opt} = PVE::QemuServer::print_drive($vmid, $drive);
+       PVE::QemuServer::check_lock($conf) if !$skiplock;
 
-               if (PVE::QemuServer::drive_is_cdrom($drive)) {
-                   $cdchange->{$opt} = PVE::QemuServer::get_iso_path($storecfg, $vmid, $drive->{file});
-               }
-           }
-       }
+       PVE::Cluster::log_msg('info', $user, "update VM $vmid: " . join (' ', @paramarr));
 
+       #delete
        foreach my $opt (PVE::Tools::split_list($delete)) {
+
            $opt = 'ide2' if $opt eq 'cdrom';
            die "you can't use '-$opt' and '-delete $opt' at the same time\n"
                if defined($param->{$opt});
-       }
 
-       PVE::QemuServer::add_random_macs($param);
-
-       my $vollist = [];
-
-       my $updatefn =  sub {
-
-           my $conf = PVE::QemuServer::load_config($vmid);
-
-           die "checksum missmatch (file change by other user?)\n" 
-               if $digest && $digest ne $conf->{digest};
-
-           PVE::QemuServer::check_lock($conf) if !$skiplock;
-
-           PVE::Cluster::log_msg('info', $user, "update VM $vmid: " . join (' ', @paramarr));
-
-            my @newdelete = ();
-            foreach my $opt (PVE::Tools::split_list($delete)) {
-               if(PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt)) {
-                    push(@newdelete, $opt);
-               }
-               else {
-                    push(@hotplugerr, $opt);
-               }
-            }
-            $delete = join(',', @newdelete) if scalar(@newdelete) > 0;
+           my $unset = {};
 
-           foreach my $opt (keys %$eject) {
-               if ($conf->{$opt}) {
-                   my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
-                   $cdchange->{$opt} = undef if PVE::QemuServer::drive_is_cdrom($drive);
-               } else {
-                   raise_param_exc({ $opt => "eject failed - drive does not exist." });
-               }
-           }
+           if (!PVE::QemuServer::option_exists($opt)) {
+               raise_param_exc({ delete => "unknown option '$opt'" });
+           } 
 
-           foreach my $opt (keys %$param) {
-               next if !PVE::QemuServer::valid_drivename($opt);
-               next if !$conf->{$opt};
-               my $old_drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
-               next if PVE::QemuServer::drive_is_cdrom($old_drive);
-               my $new_drive = PVE::QemuServer::parse_drive($opt, $param->{$opt});
-               if ($new_drive->{file} ne $old_drive->{file}) {
-                   my ($path, $owner);
-                   eval { ($path, $owner) = PVE::Storage::path($storecfg, $old_drive->{file}); };
-                   if ($owner && ($owner == $vmid)) {
-                       PVE::QemuServer::add_unused_volume($conf, $param, $old_drive->{file});
-                   }
-               }
-           }
+           next if !defined($conf->{$opt});
 
-           my $unset = {};
+           die "error hot-unplug $opt" if !PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
 
-           foreach my $opt (PVE::Tools::split_list($delete)) {
-               $opt = 'ide2' if $opt eq 'cdrom';
-               if (!PVE::QemuServer::option_exists($opt)) {
-                   raise_param_exc({ delete => "unknown option '$opt'" });
-               } 
-               next if !defined($conf->{$opt});
-               if (PVE::QemuServer::valid_drivename($opt)) {
-                   my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
-                   if (PVE::QemuServer::drive_is_cdrom($drive)) {
-                       $cdchange->{$opt} = undef;
-                   } else {
-                       my $volid = $drive->{file};
-
-                       if ($volid !~  m|^/|) {
-                           my ($path, $owner);
-                           eval { ($path, $owner) = PVE::Storage::path($storecfg, $volid); };
-                           if ($owner && ($owner == $vmid)) {
-                               if ($force) {
-                                   push @$vollist, $volid;
-                               } else {
-                                   PVE::QemuServer::add_unused_volume($conf, $param, $volid);
-                               }
+           #drive
+           if (PVE::QemuServer::valid_drivename($opt)) {
+               my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
+                #hdd
+               if (!PVE::QemuServer::drive_is_cdrom($drive)) {
+                   my $volid = $drive->{file};
+
+                   if ($volid !~  m|^/|) {
+                       my ($path, $owner);
+                       eval { ($path, $owner) = PVE::Storage::path($storecfg, $volid); };
+                       if ($owner && ($owner == $vmid)) {
+                           if ($force) {
+                               eval { PVE::Storage::vdisk_free($storecfg, $volid); };
+                               # fixme: log ?
+                               warn $@ if $@;
+                           } else {
+                               PVE::QemuServer::add_unused_volume($conf, $volid, $vmid);
                            }
                        }
                    }
-               } elsif ($opt =~ m/^unused/) {
-                   push @$vollist, $conf->{$opt};
-               }
-
-               $unset->{$opt} = 1;
+                 }
+           } elsif ($opt =~ m/^unused/) {
+                   my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
+                    my $volid = $drive->{file};
+                   eval { PVE::Storage::vdisk_free($storecfg, $volid); };
+                   # fixme: log ?
+                   warn $@ if $@;
            }
 
-           PVE::QemuServer::create_disks($storecfg, $vmid, $param, $conf);
-
-            #hotplug disks
-            foreach my $opt (keys %$param) {
-                if($opt =~ m/^(scsi|virtio)(\d+)$/) {
-                   my $device = PVE::QemuServer::parse_drive($opt, $param->{$opt});
-                   if(!PVE::QemuServer::vm_deviceplug($storecfg, $conf, $vmid, $opt, $device)) {
-                       $unset->{$opt} = 1;
-                       PVE::QemuServer::add_unused_volume($param, $device->{file});
-                       push(@hotplugerr, $opt);
-                   }
-                }
-            }
+           $unset->{$opt} = 1;
+           PVE::QemuServer::change_config_nolock($vmid, {}, $unset, 1);
+       }
 
-           PVE::QemuServer::change_config_nolock($vmid, $param, $unset, 1);
 
-           return if !PVE::QemuServer::check_running($vmid);
 
-           foreach my $opt (keys %$cdchange) {
-               my $qdn = PVE::QemuServer::qemu_drive_name($opt, 'cdrom');
-               my $path = $cdchange->{$opt};
-               PVE::QemuServer::vm_monitor_command($vmid, "eject $qdn", 0);
-               PVE::QemuServer::vm_monitor_command($vmid, "change $qdn \"$path\"", 0) if $path;
-           }
-       };
+       #add
+       foreach my $opt (keys %$param) {
 
-       PVE::QemuServer::lock_config($vmid, $updatefn);
+            #drives
+           if (PVE::QemuServer::valid_drivename($opt)) {
+               my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt});
+               raise_param_exc({ $opt => "unable to parse drive options" }) if !$drive;
 
-       foreach my $volid (@$vollist) {
-           eval { PVE::Storage::vdisk_free($storecfg, $volid); };
-           # fixme: log ?
-           warn $@ if $@;
-       }
+               PVE::QemuServer::cleanup_drive_path($opt, $storecfg, $drive);
+               $param->{$opt} = PVE::QemuServer::print_drive($vmid, $drive);
 
-        raise_param_exc({ hotplug => "error hotplug/unplug ".join(',', @hotplugerr)})
-            if scalar(@hotplugerr) > 0;
+                #cdrom
+               if (PVE::QemuServer::drive_is_cdrom($drive) && PVE::QemuServer::check_running($vmid)) {
+                   if ($drive->{file} eq 'none') {
+                        PVE::QemuServer::vm_monitor_command($vmid, "eject -f drive-$opt", 0);
+                       #delete $param->{$opt};
+                   }
+                   else {
+                       my $path = PVE::QemuServer::get_iso_path($storecfg, $vmid, $drive->{file});
+                        PVE::QemuServer::vm_monitor_command($vmid, "eject -f drive-$opt", 0); #force eject if locked
+                       PVE::QemuServer::vm_monitor_command($vmid, "change drive-$opt \"$path\"", 0) if $path;
+                    }
+               }
+               #hdd
+                else {
+                    #swap drive
+                    if ($conf->{$opt}){
+                       my $old_drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
+                       if ($drive->{file} ne $old_drive->{file} && !PVE::QemuServer::drive_is_cdrom($old_drive)) {
+
+                            my ($path, $owner);
+                            eval { ($path, $owner) = PVE::Storage::path($storecfg, $old_drive->{file}); };
+                            if ($owner && ($owner == $vmid)) {
+                               die "error hot-unplug $opt" if !PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
+                                PVE::QemuServer::add_unused_volume($conf, $old_drive->{file}, $vmid);
+                            }
+                        }
+                    }
+                   my $settings = { $opt => $param->{$opt} };
+                   PVE::QemuServer::create_disks($storecfg, $vmid, $settings, $conf);
+                   $param->{$opt} = $settings->{$opt};
+                    #hotplug disks
+                    if(!PVE::QemuServer::vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive)) {
+                       PVE::QemuServer::add_unused_volume($conf,$drive->{file},$vmid);
+                       PVE::QemuServer::change_config_nolock($vmid, {}, { $opt => 1 }, 1);
+                       die "error hotplug $opt - put disk in unused";
+                    }
+                }
+          }
+           #nics
+           if ($opt =~ m/^net(\d+)$/) {
+                my $net = PVE::QemuServer::parse_net($param->{$opt});
+                $param->{$opt} = PVE::QemuServer::print_net($net);
+           }
+
+           PVE::QemuServer::change_config_nolock($vmid, { $opt => $param->{$opt} }, {}, 1);
+       }
 
        return undef;
     }});
index f714cc896b686a46a4ca53bf0748617b74ef0e6a..41d9e3a50194f4adc046589f4dc93e19ca1d8c62 100644 (file)
@@ -1019,7 +1019,7 @@ sub add_random_macs {
 }
 
 sub add_unused_volume {
-    my ($config, $res, $volid) = @_;
+    my ($config, $volid, $vmid) = @_;
 
     my $key;
     for (my $ind = $MAX_UNUSED_DISKS - 1; $ind >= 0; $ind--) {
@@ -1033,7 +1033,8 @@ sub add_unused_volume {
 
     die "To many unused volume - please delete them first.\n" if !$key;
 
-    $res->{$key} = $volid;
+    PVE::QemuServer::change_config_nolock($vmid, { $key => $volid }, {}, 1);
+    $config->{$key} = $volid;
 }
 
 # fixme: remove all thos $noerr parameters?