[pve-devel] [PATCH 10/12] vm_deviceplug : implement pending change

Alexandre Derumier aderumier at odiso.com
Thu Oct 30 13:40:31 CET 2014


1) if vm is not running, we apply pending change directly

2) for disk, we remove unused disk on succesfull hotplug
       [CONF]
       unused0: vm-disk-100-2.raw
       [PENDING]
       virtio0: vm-disk-100-2.raw

       ->

       [CONF]
       [PENDING]
       virtio0: vm-disk-100-2.raw

3) for all devices, we apply the pending change to config and remove the pending value

       [CONF]
       [PENDING]
       virtio0: vm-disk-100-2.raw

       ->

       [CONF]
       virtio0: vm-disk-100-2.raw

       [PENDING]

Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 PVE/QemuServer.pm |   64 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 57 insertions(+), 7 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 52bcd1f..6f9dcd8 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1401,6 +1401,19 @@ sub del_volume {
     }
 }
 
+sub del_unused_volume {
+    my ($conf, $volid, $storecfg) = @_;
+
+    foreach my $key (keys %$conf) {
+        next if($key !~ m/^unused/);
+        my $confdrive = PVE::QemuServer::parse_drive($key, $conf->{$key});
+        if (!PVE::QemuServer::drive_is_cdrom($confdrive)) {
+            PVE::QemuServer::cleanup_drive_path($key, $storecfg, $confdrive);
+	    delete $conf->{$key} if $confdrive->{file} eq $volid;
+        }
+    }
+}
+
 my $valid_smbios1_options = {
     manufacturer => '\S+',
     product => '\S+',
@@ -2951,19 +2964,38 @@ sub vm_devices_list {
 }
 
 sub vm_deviceplug {
-    my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
+    my ($storecfg, $conf, $vmid, $deviceid, $device, $optvalue) = @_;
 
-    return 1 if !check_running($vmid);
+    if (!check_running($vmid)){
+	if($conf->{pending}->{$deviceid}){
+	    $conf->{$deviceid} = $optvalue;
+	    delete $conf->{pending}->{$deviceid};
+	    PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+	} 
+    }
 
     my $q35 = machine_type_is_q35($conf);
 
     if ($deviceid eq 'tablet') {
-	qemu_deviceadd($vmid, print_tabletdevice_full($conf));
+
+	eval { qemu_deviceadd($vmid, print_tabletdevice_full($conf->{pending}))};
+
+	if($conf->{pending}->{del}->{$deviceid}) {
+	    delete $conf->{$deviceid};
+	    delete $conf->{pending}->{del}->{$deviceid};
+	} else {
+	    $conf->{$deviceid} = $conf->{pending}->{$deviceid};
+	    delete $conf->{pending}->{$deviceid};
+	}
+
+	PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
 	return 1;
     }
 
     return 1 if !$conf->{hotplug};
 
+    return 1 if ($deviceid =~ m/^(ide|sata)(\d+)$/);
+
     my $devices_list = vm_devices_list($vmid);
     return 1 if defined($devices_list->{$deviceid});
 
@@ -2971,12 +3003,18 @@ sub vm_deviceplug {
 
     if ($deviceid =~ m/^(virtio)(\d+)$/) {
         return undef if !qemu_driveadd($storecfg, $vmid, $device);
-        my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
+        my $devicefull = print_drivedevice_full($storecfg, $conf->{pending}, $vmid, $device);
         qemu_deviceadd($vmid, $devicefull);
         if(!qemu_deviceaddverify($vmid, $deviceid)) {
            qemu_drivedel($vmid, $deviceid);
            return undef;
         }
+
+	#remove unused disk
+	my $drive = PVE::QemuServer::parse_drive($deviceid, $conf->{pending}->{$deviceid});
+	PVE::QemuServer::del_unused_volume($conf, $drive->{file},$storecfg);
+	PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+
     }
 
     if ($deviceid =~ m/^(scsihw)(\d+)$/) {
@@ -2990,16 +3028,21 @@ sub vm_deviceplug {
     if ($deviceid =~ m/^(scsi)(\d+)$/) {
         return undef if !qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device);
         return undef if !qemu_driveadd($storecfg, $vmid, $device);
-        my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device);
+        my $devicefull = print_drivedevice_full($storecfg, $conf->{pending}, $vmid, $device);
         if(!qemu_deviceadd($vmid, $devicefull)) {
            qemu_drivedel($vmid, $deviceid);
            return undef;
         }
+	#remove unused disk
+	my $drive = PVE::QemuServer::parse_drive($deviceid, $conf->{pending}->{$deviceid});
+	PVE::QemuServer::del_unused_volume($conf, $drive->{file},$storecfg);
+	PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+
     }
 
     if ($deviceid =~ m/^(net)(\d+)$/) {
-        return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid);
-        my $netdevicefull = print_netdevice_full($vmid, $conf, $device, $deviceid);
+        return undef if !qemu_netdevadd($vmid, $conf->{pending}, $device, $deviceid);
+        my $netdevicefull = print_netdevice_full($vmid, $conf->{pending}, $device, $deviceid);
         qemu_deviceadd($vmid, $netdevicefull);
         if(!qemu_deviceaddverify($vmid, $deviceid)) {
            qemu_netdevdel($vmid, $deviceid);
@@ -3016,6 +3059,13 @@ sub vm_deviceplug {
 	return undef if !qemu_deviceaddverify($vmid, $deviceid);
     }
 
+    #delete pending device after hotplug
+    if($conf->{pending}->{$deviceid}){
+	$conf->{$deviceid} = $optvalue;
+	delete $conf->{pending}->{$deviceid};
+	PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+    } 
+
     return 1;
 }
 
-- 
1.7.10.4




More information about the pve-devel mailing list