qemu 2.4 feature

Signed-off-by: Alexandre Derumier <aderum...@odiso.com>
---
 PVE/QemuServer.pm | 101 ++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 83 insertions(+), 18 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index f035b67..36bed4a 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -2607,6 +2607,27 @@ sub foreach_dimm {
     }
 }
 
+sub foreach_reverse_dimm {
+    my ($conf, $vmid, $memory, $sockets, $func) = @_;
+
+    my $dimm_id = 253;
+    my $current_size = 4177920;
+    my $dimm_size = 65536;
+    return if $current_size == $memory;
+
+    for (my $j = 0; $j < 8; $j++) {
+       for (my $i = 0; $i < 32; $i++) {
+           my $name = "dimm${dimm_id}";
+           $dimm_id--;
+           my $numanode = $i % $sockets;
+           $current_size -= $dimm_size;
+           &$func($conf, $vmid, $name, $dimm_size, $numanode, $current_size, 
$memory);
+           return  $current_size if $current_size <= $memory;
+       }
+       $dimm_size /= 2;
+    }
+}
+
 sub foreach_drive {
     my ($conf, $vmid, $func) = @_;
 
@@ -3693,33 +3714,77 @@ sub qemu_memory_hotplug {
     my $dimm_memory = $memory - $static_memory;
 
     die "memory can't be lower than $static_memory MB" if $value < 
$static_memory;
-    die "memory unplug is not yet available" if $value < $memory;
     die "you cannot add more memory than $MAX_MEM MB!\n" if $memory > $MAX_MEM;
 
 
     my $sockets = 1;
     $sockets = $conf->{sockets} if $conf->{sockets};
 
-    foreach_dimm($conf, $vmid, $value, $sockets, sub {
-       my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, $memory) 
= @_;
+    if($value > $memory) {
 
-           return if $current_size <= $conf->{memory};
+       foreach_dimm($conf, $vmid, $value, $sockets, sub {
+           my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, 
$memory) = @_;
 
-           eval { vm_mon_cmd($vmid, "object-add", 'qom-type' => 
"memory-backend-ram", id => "mem-$name", props => { size => 
int($dimm_size*1024*1024) } ) };
-           if (my $err = $@) {
-               eval { qemu_objectdel($vmid, "mem-$name"); };
-               die $err;
-           }
+               return if $current_size <= $conf->{memory};
 
-           eval { vm_mon_cmd($vmid, "device_add", driver => "pc-dimm", id => 
"$name", memdev => "mem-$name", node => $numanode) };
-           if (my $err = $@) {
-               eval { qemu_objectdel($vmid, "mem-$name"); };
-               die $err;
-           }
-           #update conf after each succesful module hotplug
-           $conf->{memory} = $current_size;
-           update_config_nolock($vmid, $conf, 1);
-    });
+               eval { vm_mon_cmd($vmid, "object-add", 'qom-type' => 
"memory-backend-ram", id => "mem-$name", props => { size => 
int($dimm_size*1024*1024) } ) };
+               if (my $err = $@) {
+                   eval { qemu_objectdel($vmid, "mem-$name"); };
+                   die $err;
+               }
+
+               eval { vm_mon_cmd($vmid, "device_add", driver => "pc-dimm", id 
=> "$name", memdev => "mem-$name", node => $numanode) };
+               if (my $err = $@) {
+                   eval { qemu_objectdel($vmid, "mem-$name"); };
+                   die $err;
+               }
+               #update conf after each succesful module hotplug
+               $conf->{memory} = $current_size;
+               update_config_nolock($vmid, $conf, 1);
+       });
+
+    } else {
+
+       foreach_reverse_dimm($conf, $vmid, $value, $sockets, sub {
+           my ($conf, $vmid, $name, $dimm_size, $numanode, $current_size, 
$memory) = @_;
+
+               return if $current_size >= $conf->{memory};
+               print "try to unplug memory dimm $name\n";
+
+               my $retry = 0;
+               while (1) {
+                   eval { qemu_devicedel($vmid, $name) };
+                   sleep 3;
+                   my $dimm_list = qemu_dimm_list($vmid);
+                   last if !$dimm_list->{$name};
+                   raise_param_exc({ $name => "error unplug memory module" }) 
if $retry > 5;
+                   $retry++;
+               }
+
+               #update conf after each succesful module unplug
+               $conf->{memory} = $current_size;
+
+               eval { qemu_objectdel($vmid, "mem-$name"); };
+               update_config_nolock($vmid, $conf, 1);
+       });
+    }
+}
+
+sub qemu_dimm_list {
+    my ($vmid) = @_;
+
+    my $dimmarray = vm_mon_cmd_nocheck($vmid, "query-memory-devices");
+    my $dimms = {};
+
+    foreach my $dimm (@$dimmarray) {
+
+        $dimms->{$dimm->{data}->{id}}->{id} = $dimm->{data}->{id};
+        $dimms->{$dimm->{data}->{id}}->{node} = $dimm->{data}->{node};
+        $dimms->{$dimm->{data}->{id}}->{addr} = $dimm->{data}->{addr};
+        $dimms->{$dimm->{data}->{id}}->{size} = $dimm->{data}->{size};
+        $dimms->{$dimm->{data}->{id}}->{slot} = $dimm->{data}->{slot};
+    }
+    return $dimms;
 }
 
 sub qemu_block_set_io_throttle {
-- 
2.1.4

_______________________________________________
pve-devel mailing list
pve-devel@pve.proxmox.com
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to