Re: [pve-devel] [PATCH 2/2] now if the QMP command starts with guest-+ , it will bind dynamicly to the VMID.qga socket. To test the function vmtime is implemented which return the vm UNIX Time.

2014-11-25 Thread Alexandre DERUMIER
I thought about IP address and disk usage: 

guest-network-get-interfaces 
guest-get-fsinfo 

So maybe 1 call each minute is enough for this ?

But seems guest-get-fsinfo does not return useful data :-/ 

Yes, I only display mountpoint. (could be useful for hot-unplug protection).


Note that both network and fsinfo are not implemented under qga windows 
currently



- Mail original - 

De: Dietmar Maurer diet...@proxmox.com 
À: Alexandre DERUMIER aderum...@odiso.com 
Cc: pve-devel@pve.proxmox.com, Wolfgang Link wolfg...@linksystems.org 
Envoyé: Mardi 25 Novembre 2014 08:09:39 
Objet: RE: [PATCH 2/2] now if the QMP command starts with guest-+ , it will 
bind dynamicly to the VMID.qga socket. To test the function vmtime is 
implemented which return the vm UNIX Time. 

 Maybe pvestatd can save if last qga command was successful (guest 
 agent online) 
 
 what happen here if the guest agent is down ? (for example, when the vm is 
 going to shutdown, stop the guest agent service) 

We get a timeout, and we save that information so that other processes knows 
that guest agent is down. 

 BTW, which qga command is used to get status ? 
 I don't find anything related in 
 http://git.qemu.org/?p=qemu.git;a=blob_plain;f=qga/qapi- 
 schema.json;hb=HEAD 

I thought about IP address and disk usage: 

guest-network-get-interfaces 
guest-get-fsinfo 

But seems guest-get-fsinfo does not return useful data :-/ 
___
pve-devel mailing list
pve-devel@pve.proxmox.com
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] [PATCH 2/2] now if the QMP command starts with guest-+ , it will bind dynamicly to the VMID.qga socket. To test the function vmtime is implemented which return the vm UNIX Time.

2014-11-25 Thread Dietmar Maurer

 I thought about IP address and disk usage:
 
 guest-network-get-interfaces
 guest-get-fsinfo
 
 So maybe 1 call each minute is enough for this ?

yes
 
 But seems guest-get-fsinfo does not return useful data :-/
 
 Yes, I only display mountpoint. (could be useful for hot-unplug protection).
 
 
 Note that both network and fsinfo are not implemented under qga windows
 currently

OK, thanks for that info.
___
pve-devel mailing list
pve-devel@pve.proxmox.com
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] vm_deviceunplug question

2014-11-25 Thread Alexandre DERUMIER
This is because for virtio disk we remove the controller + drive,  (1controller 
- 1 drive)

and for scsi we only remove the drive  (1controller - 256 drives)



- Mail original - 

De: Dietmar Maurer diet...@proxmox.com 
À: Alexandre DERUMIER (aderum...@odiso.com) aderum...@odiso.com 
Cc: pve-devel@pve.proxmox.com 
Envoyé: Mardi 25 Novembre 2014 07:26:22 
Objet: vm_deviceunplug question 



For example, for virtio we call qemu_devicedelverify(): 

if ($deviceid =~ m/^(virtio)(\d+)$/) { 

qemu_devicedel($vmid, $deviceid); 
return undef if !qemu_devicedelverify($vmid, $deviceid); 
return undef if !qemu_drivedel($vmid, $deviceid); 

But for lsi/scsi we simply do: 

if ($deviceid =~ m/^(scsi)(\d+)$/) { 

qemu_devicedel($vmid, $deviceid); 
return undef if !qemu_drivedel($vmid, $deviceid); 

Why don’t we call qemu_devicedelverify() here? 
___
pve-devel mailing list
pve-devel@pve.proxmox.com
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] vm_deviceunplug question

2014-11-25 Thread Dietmar Maurer
 This is because for virtio disk we remove the controller + drive,  
 (1controller - 1
 drive)
 
 and for scsi we only remove the drive  (1controller - 256 drives)

I cannot see that:

3001   if ($deviceid =~ m/^(scsi)(\d+)$/) {
3002 return undef if !qemu_devicedel($vmid, $deviceid);
3003 return undef if !qemu_drivedel($vmid, $deviceid);
3004 }

so you also remove the device using qemu_devicedel()?
What do I miss?
___
pve-devel mailing list
pve-devel@pve.proxmox.com
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v5 02/19] parse_vm_config: correctly handle $descr

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 96eb6ec..e020740 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1782,7 +1782,7 @@ sub parse_vm_config {
 my $res = {
digest = Digest::SHA::sha1_hex($raw),
snapshots = {},
-   pending = {}
+   pending = {},
 };
 
 $filename =~ m|/qemu-server/(\d+)\.conf$|
@@ -1798,10 +1798,12 @@ sub parse_vm_config {
next if $line =~ m/^\s*$/;
 
if ($line =~ m/^\[PENDING\]\s*$/i) {
+   $conf-{description} = $descr if $descr;
+   $descr = '';
$conf = $res-{pending} = {};
next;
 
-   }elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
+   } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
my $snapname = $1;
$conf-{description} = $descr if $descr;
$descr = '';
-- 
1.7.10.4

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


[pve-devel] [PATCH v5 04/19] write_vm_config : write pending change

2014-11-25 Thread Dietmar Maurer
example:

$conf-{pending}-{virtio1}
$conf-{pending}-{delete} = net0,net1

[PENDING]
virtio1: ...
delete: net0,net1

Signed-off-by: Alexandre Derumier aderum...@odiso.com
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   32 +---
 1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 9b03e6a..f6b8ce2 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1826,10 +1826,12 @@ sub parse_vm_config {
my $key = $1;
my $value = $2;
$conf-{$key} = $value;
-   } elsif (($section eq 'pending')  ($line =~ 
m/^delete:\s*(.*\S)\s*$/)) {
+   } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
my $value = $1;
-   foreach my $opt (split(/,/, $value)) {
-   $conf-{del}-{$opt} = 1;
+   if ($section eq 'pending') {
+   $conf-{delete} = $value; # we parse this later
+   } else {
+   warn vm $vmid - propertry 'delete' is only allowed in 
[PENDING]\n;
}
} elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
my $key = $1;
@@ -1893,12 +1895,18 @@ sub write_vm_config {
 my $used_volids = {};
 
 my $cleanup_config = sub {
-   my ($cref, $snapname) = @_;
+   my ($cref, $pending, $snapname) = @_;
 
foreach my $key (keys %$cref) {
next if $key eq 'digest' || $key eq 'description' || $key eq 
'snapshots' ||
-   $key eq 'snapstate';
+   $key eq 'snapstate' || $key eq 'pending';
my $value = $cref-{$key};
+   if ($key eq 'delete') {
+   die propertry 'delete' is only allowed in [PENDING]\n
+   if !$pending;
+   # fixme: check syntax?
+   next;
+   }
eval { $value = check_type($key, $value); };
die unable to parse value of '$key' - $@ if $@;
 
@@ -1912,8 +1920,12 @@ sub write_vm_config {
 };
 
 $cleanup_config($conf);
+
+$cleanup_config($conf-{pending}, 1);
+
 foreach my $snapname (keys %{$conf-{snapshots}}) {
-   $cleanup_config($conf-{snapshots}-{$snapname}, $snapname);
+   die internal error if $snapname eq 'pending';
+   $cleanup_config($conf-{snapshots}-{$snapname}, undef, $snapname);
 }
 
 # remove 'unusedX' settings if we re-add a volume
@@ -1936,13 +1948,19 @@ sub write_vm_config {
}
 
foreach my $key (sort keys %$conf) {
-   next if $key eq 'digest' || $key eq 'description' || $key eq 
'snapshots';
+   next if $key eq 'digest' || $key eq 'description' || $key eq 
'pending' || $key eq 'snapshots';
$raw .= $key: $conf-{$key}\n;
}
return $raw;
 };
 
 my $raw = $generate_raw_config($conf);
+
+if (scalar(keys %{$conf-{pending}})){
+   $raw .= \n[PENDING]\n;
+   $raw .= $generate_raw_config($conf-{pending});
+}
+
 foreach my $snapname (sort keys %{$conf-{snapshots}}) {
$raw .= \n[$snapname]\n;
$raw .= $generate_raw_config($conf-{snapshots}-{$snapname});
-- 
1.7.10.4

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


[pve-devel] [PATCH v5 03/19] parse_vm_config: only allow 'delete' inside [PENDING]

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index e020740..9b03e6a 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1792,22 +1792,24 @@ sub parse_vm_config {
 
 my $conf = $res;
 my $descr = '';
+my $section = '';
 
 my @lines = split(/\n/, $raw);
 foreach my $line (@lines) {
next if $line =~ m/^\s*$/;
 
if ($line =~ m/^\[PENDING\]\s*$/i) {
+   $section = 'pending';
$conf-{description} = $descr if $descr;
$descr = '';
-   $conf = $res-{pending} = {};
+   $conf = $res-{$section} = {};
next;
 
} elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
-   my $snapname = $1;
+   $section = $1;
$conf-{description} = $descr if $descr;
$descr = '';
-   $conf = $res-{snapshots}-{$snapname} = {};
+   $conf = $res-{snapshots}-{$section} = {};
next;
}
 
@@ -1824,9 +1826,8 @@ sub parse_vm_config {
my $key = $1;
my $value = $2;
$conf-{$key} = $value;
-   } elsif ($line =~ m/^(delete):\s*(.*\S)\s*$/) {
-   my $key = $1;
-   my $value = $2;
+   } elsif (($section eq 'pending')  ($line =~ 
m/^delete:\s*(.*\S)\s*$/)) {
+   my $value = $1;
foreach my $opt (split(/,/, $value)) {
$conf-{del}-{$opt} = 1;
}
-- 
1.7.10.4

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


[pve-devel] [PATCH v5 00/19] qemu-server: implement pending changes

2014-11-25 Thread Dietmar Maurer
Based on Alexandres patches (sent to pve-devel list):
  qemu-server : implement pending changes v2
  pending changes hotplug v2

Changes in v5:
- implement network hotplug
- cleanup error handling in vm_deviceunplug and vm_deviceplug
- bug fixes

Changes in v4:

- implement API/CLI to get pending changes
- improve hotplug error handling (see cpu hotplug as example)
- new method to cleanup setting in [PENDING]
- code cleanups

Changes in v3:

- I tried to simplify things by always writing changes into pending 
  section first.

- do not parse 'delete' option parse_vm_config

Todo: implement hotplug disk/net 


Alexandre Derumier (1):
  parse_vm_config : parse pending changes

Dietmar Maurer (18):
  parse_vm_config: correctly handle $descr
  parse_vm_config: only allow 'delete' inside [PENDING]
  write_vm_config : write pending change
  update_vm_api: always write into pending section
  implement vmconfig_apply_pending for stopped VM
  vm_start: apply pending changes
  fix balloon consistency check (consider pending changes)
  implement trivial hotplug
  vmconfig_hotplug_pending: implement tablet hotplug
  vmconfig_cleanup_pending: new method to clenup setting in [PENDING]
  code cleanup, delete trailing white space
  vmconfig_hotplug_pending: improve hotplug error handling
  implement API/CLI to get pending changes
  rename qemu_bridgeadd to qemu_add_pci_bridge
  vmconfig_hotplug_pending: correctly skip values
  vmconfig_hotplug_pending : add update_net
  vm_deviceunplug: raise expection if something fail
  vm_deviceplug: always raise exception on error

 PVE/API2/Qemu.pm  |  234 +++---
 PVE/QemuServer.pm |  576 ++---
 pve-bridge|8 +-
 qm|   27 +++
 4 files changed, 661 insertions(+), 184 deletions(-)

-- 
1.7.10.4

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


[pve-devel] [PATCH v5 09/19] implement trivial hotplug

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   47 ++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 8524180..2a702d2 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3438,11 +3438,56 @@ sub set_migration_caps {
 vm_mon_cmd_nocheck($vmid, migrate-set-capabilities, capabilities = 
$cap_ref);
 }
 
+sub vmconfig_hotplug_pending {
+my ($vmid, $conf, $storecfg) = @_;
+
+my $defaults = PVE::QemuServer::load_defaults();
+
+# commit values which do not have any impact on running VM first
+
+my $changes = 0;
+foreach my $opt (keys %{$conf-{pending}}) { # add/change
+   if ($opt eq 'name' || $opt eq 'hotplug' || $opt eq 'onboot' || $opt eq 
'shares') {
+   $conf-{$opt} = $conf-{pending}-{$opt};
+   delete $conf-{pending}-{$opt};
+   $changes = 1;
+   }
+}
+
+if ($changes) {
+   update_config_nolock($vmid, $conf, 1);
+   $conf = load_config($vmid); # update/reload
+}
+
+$changes = 0;
+
+# allow manual ballooning if shares is set to zero
+
+if (defined($conf-{pending}-{balloon})  defined($conf-{shares})  
($conf-{shares} == 0)) {
+   my $balloon = $conf-{pending}-{balloon} || $conf-{memory} || 
$defaults-{memory};
+   vm_mon_cmd($vmid, balloon, value = $balloon*1024*1024);
+   $conf-{balloon} = $conf-{pending}-{balloon};
+   delete $conf-{pending}-{balloon};
+   $changes = 1;
+}
+
+if ($changes) {
+   update_config_nolock($vmid, $conf, 1);
+   $conf = load_config($vmid); # update/reload
+}
+
+return if !$conf-{hotplug};
+
+# fixme: implement disk/network hotplug here
+
+}
 
 sub vmconfig_apply_pending {
 my ($vmid, $conf, $storecfg, $running) = @_;
 
-die implement me - vm is running if $running; # fixme: if 
$conf-{hotplug};
+return vmconfig_hotplug_pending($vmid, $conf, $storecfg) if $running;
+
+# cold plug
 
 my @delete = PVE::Tools::split_list($conf-{pending}-{delete});
 foreach my $opt (@delete) { # delete
-- 
1.7.10.4

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


[pve-devel] [PATCH v5 01/19] parse_vm_config : parse pending changes

2014-11-25 Thread Dietmar Maurer
From: Alexandre Derumier aderum...@odiso.com

example:

[PENDING]
virtio1:...
delete:net0,net1

$conf-{pending}-{virtio1}
$conf-{pending}-{del}-{net0}
$conf-{pending}-{del}-{net1}

Signed-off-by: Alexandre Derumier aderum...@odiso.com
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index b5aafc3..96eb6ec 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1782,6 +1782,7 @@ sub parse_vm_config {
 my $res = {
digest = Digest::SHA::sha1_hex($raw),
snapshots = {},
+   pending = {}
 };
 
 $filename =~ m|/qemu-server/(\d+)\.conf$|
@@ -1796,7 +1797,11 @@ sub parse_vm_config {
 foreach my $line (@lines) {
next if $line =~ m/^\s*$/;
 
-   if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
+   if ($line =~ m/^\[PENDING\]\s*$/i) {
+   $conf = $res-{pending} = {};
+   next;
+
+   }elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
my $snapname = $1;
$conf-{description} = $descr if $descr;
$descr = '';
@@ -1817,6 +1822,12 @@ sub parse_vm_config {
my $key = $1;
my $value = $2;
$conf-{$key} = $value;
+   } elsif ($line =~ m/^(delete):\s*(.*\S)\s*$/) {
+   my $key = $1;
+   my $value = $2;
+   foreach my $opt (split(/,/, $value)) {
+   $conf-{del}-{$opt} = 1;
+   }
} elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
my $key = $1;
my $value = $2;
-- 
1.7.10.4

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


[pve-devel] [PATCH v5 08/19] fix balloon consistency check (consider pending changes)

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm |5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index d6a70c0..a8841c2 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -945,10 +945,9 @@ my $update_vm_api  = sub {
 
PVE::QemuServer::check_lock($conf) if !$skiplock;
 
-   # fixme: wrong place? howto handle pending changes? @delete ?
if ($param-{memory} || defined($param-{balloon})) {
-   my $maxmem = $param-{memory} || $conf-{memory} || 
$defaults-{memory};
-   my $balloon = defined($param-{balloon}) ?  $param-{balloon} : 
$conf-{balloon};
+   my $maxmem = $param-{memory} || $conf-{pending}-{memory} || 
$conf-{memory} || $defaults-{memory};
+   my $balloon = defined($param-{balloon}) ? $param-{balloon} : 
$conf-{pending}-{balloon} || $conf-{balloon};
 
die balloon value too large (must be smaller than assigned 
memory)\n
if $balloon  $balloon  $maxmem;
-- 
1.7.10.4

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


[pve-devel] [PATCH v5 05/19] update_vm_api: always write into pending section

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm |   99 --
 1 file changed, 97 insertions(+), 2 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 0787074..222c44f 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -951,6 +951,44 @@ my $update_vm_api  = sub {
 
 $check_storage_access($rpcenv, $authuser, $storecfg, $vmid, $param);
 
+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 ($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 $updatefn =  sub {
 
my $conf = PVE::QemuServer::load_config($vmid);
@@ -960,6 +998,7 @@ my $update_vm_api  = sub {
 
PVE::QemuServer::check_lock($conf) if !$skiplock;
 
+   # fixme: wrong place? howto handle pending changes? @delete ?
if ($param-{memory} || defined($param-{balloon})) {
my $maxmem = $param-{memory} || $conf-{memory} || 
$defaults-{memory};
my $balloon = defined($param-{balloon}) ?  $param-{balloon} : 
$conf-{balloon};
@@ -974,11 +1013,67 @@ my $update_vm_api  = sub {
 
print update VM $vmid:  . join (' ', @paramarr) . \n;
 
-   foreach my $opt (@delete) { # delete
+   # write updates to pending section
+
+   foreach my $opt (@delete) {
$conf = PVE::QemuServer::load_config($vmid); # update/reload
-   $vmconfig_delete_option($rpcenv, $authuser, $conf, $storecfg, 
$vmid, $opt, $force);
+   if ($opt =~ m/^unused/) {
+   $rpcenv-check_vm_perm($authuser, $vmid, undef, 
['VM.Config.Disk']);
+   my $drive = PVE::QemuServer::parse_drive($opt, 
$conf-{$opt});
+   if (my $sid = $test_deallocate_drive($storecfg, $vmid, 
$opt, $drive, $force)) {
+   $rpcenv-check($authuser, /storage/$sid, 
['Datastore.AllocateSpace']);
+   $delete_drive($conf, $storecfg, $vmid, $opt, $drive);
+   PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+   }
+   } elsif (PVE::QemuServer::valid_drivename($opt)) {
+   $rpcenv-check_vm_perm($authuser, $vmid, undef, 
['VM.Config.Disk']);
+   $register_unused_drive($conf, 
PVE::QemuServer::parse_drive($opt, $conf-{pending}-{$opt}))
+   if defined($conf-{pending}-{$opt});
+   $pending_delete_option($conf, $opt);
+   PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+   } else {
+   $pending_delete_option($conf, $opt);
+   PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+   }
}
 
+   foreach my $opt (keys %$param) { # add/change
+   $conf = PVE::QemuServer::load_config($vmid); # update/reload
+   next if defined($conf-{pending}-{$opt})  ($param-{$opt} eq 
$conf-{pending}-{$opt}); # skip if nothing changed
+
+   if (PVE::QemuServer::valid_drivename($opt)) {
+   my $drive = PVE::QemuServer::parse_drive($opt, 
$param-{$opt});
+   if (PVE::QemuServer::drive_is_cdrom($drive)) { # CDROM
+   $rpcenv-check_vm_perm($authuser, $vmid, undef, 
['VM.Config.CDROM']);
+   } else {
+   $rpcenv-check_vm_perm($authuser, $vmid, undef, 
['VM.Config.Disk']);
+   }
+   $register_unused_drive($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};
+   }
+   

[pve-devel] [PATCH v5 10/19] vmconfig_hotplug_pending: implement tablet hotplug

2014-11-25 Thread Dietmar Maurer
Remove special case: now, we only hotplug if 'hotplug' is enabled.

Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   71 -
 1 file changed, 59 insertions(+), 12 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 2a702d2..7219353 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -2974,7 +2974,6 @@ sub vm_devices_list {
 my ($vmid) = @_;
 
 my $res = vm_mon_cmd($vmid, 'query-pci');
-
 my $devices = {};
 foreach my $pcibus (@$res) {
foreach my $device (@{$pcibus-{devices}}) {
@@ -2990,6 +2989,14 @@ sub vm_devices_list {
}
 }
 
+my $resmice = vm_mon_cmd($vmid, 'query-mice');
+foreach my $mice (@$resmice) {
+   if ($mice-{name} eq 'QEMU HID Tablet') {
+   $devices-{tablet} = 1;
+   last;
+   }
+}
+
 return $devices;
 }
 
@@ -3000,16 +3007,16 @@ sub vm_deviceplug {
 
 my $q35 = machine_type_is_q35($conf);
 
-if ($deviceid eq 'tablet') {
-   qemu_deviceadd($vmid, print_tabletdevice_full($conf));
-   return 1;
-}
-
 return 1 if !$conf-{hotplug};
 
 my $devices_list = vm_devices_list($vmid);
 return 1 if defined($devices_list-{$deviceid});
 
+if ($deviceid eq 'tablet') {
+   qemu_deviceadd($vmid, print_tabletdevice_full($conf));
+   return 1;
+}
+
 qemu_bridgeadd($storecfg, $conf, $vmid, $deviceid); #add bridge if we need 
it for the device
 
 if ($deviceid =~ m/^(virtio)(\d+)$/) {
@@ -3067,16 +3074,16 @@ sub vm_deviceunplug {
 
 return 1 if !check_running ($vmid);
 
-if ($deviceid eq 'tablet') {
-   qemu_devicedel($vmid, $deviceid);
-   return 1;
-}
-
 return 1 if !$conf-{hotplug};
 
 my $devices_list = vm_devices_list($vmid);
 return 1 if !defined($devices_list-{$deviceid});
 
+if ($deviceid eq 'tablet') {
+   qemu_devicedel($vmid, $deviceid);
+   return 1;
+}
+
 die can't unplug bootdisk if $conf-{bootdisk}  $conf-{bootdisk} eq 
$deviceid;
 
 if ($deviceid =~ m/^(virtio)(\d+)$/) {
@@ -3478,8 +3485,48 @@ sub vmconfig_hotplug_pending {
 
 return if !$conf-{hotplug};
 
-# fixme: implement disk/network hotplug here
+my @delete = PVE::Tools::split_list($conf-{pending}-{delete});
+foreach my $opt (@delete) {
+   if ($opt eq 'tablet') {
+   if ($defaults-{tablet}) {
+   PVE::QemuServer::vm_deviceplug($storecfg, $conf, $vmid, $opt);
+   } else {
+   PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
+   }
+   } else {
+   # skip non-hot-pluggable options
+   next;
+   }
+
+   # save new config if hotplug was successful
+   delete $conf-{$opt};
+   vmconfig_undelete_pending_option($conf, $opt);
+   update_config_nolock($vmid, $conf, 1);
+
+   $conf = load_config($vmid); # update/reload
+}
 
+foreach my $opt (keys %{$conf-{pending}}) {
+   my $value = $conf-{pending}-{$opt};
+
+   if ($opt eq 'tablet') {
+   if ($value == 1) {
+   PVE::QemuServer::vm_deviceplug($storecfg, $conf, $vmid, $opt);
+   } elsif ($value == 0) {
+   PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
+   }
+   } else {
+   # skip non-hot-pluggable options
+   next;
+   }
+
+   # save new config if hotplug was successful
+   $conf-{$opt} = $value;
+   delete $conf-{pending}-{$opt};
+   update_config_nolock($vmid, $conf, 1);
+
+   $conf = load_config($vmid); # update/reload
+}
 }
 
 sub vmconfig_apply_pending {
-- 
1.7.10.4

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


[pve-devel] [PATCH v5 13/19] vmconfig_hotplug_pending: improve hotplug error handling

2014-11-25 Thread Dietmar Maurer
Simplify code, and allow to partially apply pending changes using
a new $selection parameter.

Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm  |   12 -
 PVE/QemuServer.pm |  149 ++---
 2 files changed, 95 insertions(+), 66 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 8c7c076..b116c24 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -961,7 +961,10 @@ my $update_vm_api  = sub {
 
# write updates to pending section
 
+   my $modified = {}; # record what $option we modify
+
foreach my $opt (@delete) {
+   $modified-{$opt} = 1;
$conf = PVE::QemuServer::load_config($vmid); # update/reload
if ($opt =~ m/^unused/) {
$rpcenv-check_vm_perm($authuser, $vmid, undef, 
['VM.Config.Disk']);
@@ -984,6 +987,7 @@ my $update_vm_api  = sub {
}
 
foreach my $opt (keys %$param) { # add/change
+   $modified-{$opt} = 1;
$conf = PVE::QemuServer::load_config($vmid); # update/reload
next if defined($conf-{pending}-{$opt})  ($param-{$opt} eq 
$conf-{pending}-{$opt}); # skip if nothing changed
 
@@ -1017,8 +1021,14 @@ my $update_vm_api  = sub {
# apply pending changes
 
$conf = PVE::QemuServer::load_config($vmid); # update/reload
-   PVE::QemuServer::vmconfig_apply_pending($vmid, $conf, $storecfg, 
$running);
 
+   if ($running) {
+   my $errors = {};
+   PVE::QemuServer::vmconfig_hotplug_pending($vmid, $conf, 
$storecfg, $modified, $errors);
+   raise_param_exc($errors) if scalar(keys %$errors);
+   } else {
+   PVE::QemuServer::vmconfig_apply_pending($vmid, $conf, 
$storecfg, $running);
+   }
return; # TODO: remove old code below
 
foreach my $opt (keys %$param) { # add/change
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index dd06f2f..391376e 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3266,22 +3266,25 @@ sub qemu_netdevdel {
 sub qemu_cpu_hotplug {
 my ($vmid, $conf, $cores) = @_;
 
-die new cores config is not defined if !$cores;
-die you can't add more cores than maxcpus
-   if $conf-{maxcpus}  ($cores  $conf-{maxcpus});
-return if !check_running($vmid);
+my $sockets = $conf-{sockets} || 1;
+die cpu hotplug only works with one socket\n
+   if $sockets  1;
 
-my $currentcores = $conf-{cores} if $conf-{cores};
-die current cores is not defined if !$currentcores;
-die maxcpus is not defined if !$conf-{maxcpus};
-raise_param_exc({ 'cores' = online cpu unplug is not yet possible })
-   if($cores  $currentcores);
+die maxcpus is not defined\n
+   if !$conf-{maxcpus};
+
+die you can't add more cores than maxcpus\n
+   if $cores  $conf-{maxcpus};
+
+my $currentcores = $conf-{cores} || 1;
+die online cpu unplug is not yet possible\n
+   if $cores  $currentcores;
 
 my $currentrunningcores = vm_mon_cmd($vmid, query-cpus);
-raise_param_exc({ 'cores' = cores number if running vm is different than 
configuration })
-   if scalar (@{$currentrunningcores}) != $currentcores;
+die cores number if running vm is different than configuration\n
+   if scalar(@{$currentrunningcores}) != $currentcores;
 
-for(my $i = $currentcores; $i  $cores; $i++) {
+for (my $i = $currentcores; $i  $cores; $i++) {
vm_mon_cmd($vmid, cpu-add, id = int($i));
 }
 }
@@ -3477,12 +3480,23 @@ sub set_migration_caps {
 vm_mon_cmd_nocheck($vmid, migrate-set-capabilities, capabilities = 
$cap_ref);
 }
 
+# hotplug changes in [PENDING]
+# $selection hash can be used to only apply specified options, for
+# example: { cores = 1 } (only apply changed 'cores')
+# $errors ref is used to return error messages
 sub vmconfig_hotplug_pending {
-my ($vmid, $conf, $storecfg) = @_;
+my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
 
 my $defaults = load_defaults();
 
 # commit values which do not have any impact on running VM first
+# Note: those option cannot raise errors, we we do not care about
+# $selection and always apply them.
+
+my $add_error = sub {
+   my ($opt, $msg) = @_;
+   $errors-{$opt} = hotplug problem - $msg;
+};
 
 my $changes = 0;
 foreach my $opt (keys %{$conf-{pending}}) { # add/change
@@ -3498,73 +3512,78 @@ sub vmconfig_hotplug_pending {
$conf = load_config($vmid); # update/reload
 }
 
-$changes = 0;
-
-# allow manual ballooning if shares is set to zero
-
-if (defined($conf-{pending}-{balloon})  defined($conf-{shares})  
($conf-{shares} == 0)) {
-   my $balloon = $conf-{pending}-{balloon} || $conf-{memory} || 
$defaults-{memory};
-   vm_mon_cmd($vmid, balloon, value = $balloon*1024*1024);
-   $conf-{balloon} = $conf-{pending}-{balloon};
-   

[pve-devel] [PATCH v5 17/19] vmconfig_hotplug_pending : add update_net

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Alexandre Derumier aderum...@odiso.com
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm  |   44 ++-
 PVE/QemuServer.pm |   67 -
 pve-bridge|8 +--
 3 files changed, 74 insertions(+), 45 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 98a42fe..ea045c9 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -897,46 +897,6 @@ my $vmconfig_update_disk = sub {
 }
 };
 
-my $vmconfig_update_net = sub {
-my ($rpcenv, $authuser, $conf, $storecfg, $vmid, $opt, $value) = @_;
-
-if ($conf-{$opt}  PVE::QemuServer::check_running($vmid)) {
-   my $oldnet = PVE::QemuServer::parse_net($conf-{$opt});
-   my $newnet = PVE::QemuServer::parse_net($value);
-
-   if($oldnet-{model} ne $newnet-{model}){
-   #if model change, we try to hot-unplug
-die error hot-unplug $opt for update if 
!PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
-   }else{
-
-   if($newnet-{bridge}  $oldnet-{bridge}){
-   my $iface = tap.$vmid.i.$1 if $opt =~ m/net(\d+)/;
-
-   if($newnet-{rate} ne $oldnet-{rate}){
-   PVE::Network::tap_rate_limit($iface, $newnet-{rate});
-   }
-
-   if(($newnet-{bridge} ne $oldnet-{bridge}) || ($newnet-{tag} 
ne $oldnet-{tag}) || ($newnet-{firewall} ne $oldnet-{firewall})){
-   PVE::Network::tap_unplug($iface);
-   PVE::Network::tap_plug($iface, $newnet-{bridge}, 
$newnet-{tag}, $newnet-{firewall});
-   }
-
-   }else{
-   #if bridge/nat mode change, we try to hot-unplug
-   die error hot-unplug $opt for update if 
!PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
-   }
-   }
-
-}
-$conf-{$opt} = $value;
-PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
-$conf = PVE::QemuServer::load_config($vmid); # update/reload
-
-my $net = PVE::QemuServer::parse_net($conf-{$opt});
-
-die error hotplug $opt if !PVE::QemuServer::vm_deviceplug($storecfg, 
$conf, $vmid, $opt, $net);
-};
-
 # POST/PUT {vmid}/config implementation
 #
 # The original API used PUT (idempotent) an we assumed that all operations
@@ -1128,8 +1088,8 @@ my $update_vm_api  = sub {
 
} elsif ($opt =~ m/^net(\d+)$/) { #nics
 
-   $vmconfig_update_net($rpcenv, $authuser, $conf, $storecfg, 
$vmid,
- $opt, $param-{$opt});
+   # $vmconfig_update_net($rpcenv, $authuser, $conf, 
$storecfg, $vmid,
+   # $opt, $param-{$opt});
 
} else {
 
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 6642928..c568dfd 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3032,6 +3032,7 @@ sub vm_devices_list {
 return $devices;
 }
 
+# fixme: this should raise exceptions on error!
 sub vm_deviceplug {
 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
 
@@ -3073,7 +3074,7 @@ sub vm_deviceplug {
 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);
-if(!qemu_deviceadd($vmid, $devicefull)) {
+if(!qemu_deviceadd($vmid, $devicefull)) { # fixme: use 
qemu_deviceaddverify?
qemu_drivedel($vmid, $deviceid);
return undef;
 }
@@ -3101,6 +3102,7 @@ sub vm_deviceplug {
 return 1;
 }
 
+# fixme: this should raise exceptions on error!
 sub vm_deviceunplug {
 my ($vmid, $conf, $deviceid) = @_;
 
@@ -3532,6 +3534,9 @@ sub vmconfig_hotplug_pending {
} elsif ($opt eq 'cores') {
die skip\n if !$hotplug;
qemu_cpu_hotplug($vmid, $conf, 1);
+   } elsif ($opt =~ m/^net(\d+)$/) {
+   die skip\n if !$hotplug;
+   vm_deviceunplug($vmid, $conf, $opt);
} else {
die skip\n;
}
@@ -3566,6 +3571,9 @@ sub vmconfig_hotplug_pending {
# allow manual ballooning if shares is set to zero
my $balloon = $conf-{pending}-{balloon} || $conf-{memory} || 
$defaults-{memory};
vm_mon_cmd($vmid, balloon, value = $balloon*1024*1024);
+   } elsif ($opt =~ m/^net(\d+)$/) { 
+   # some changes can be done without hotplug
+   vmconfig_update_net($storecfg, $conf, $vmid, $opt, $value);
} else {
die skip\n;  # skip non-hot-pluggable options
}
@@ -3626,6 +3634,63 @@ sub vmconfig_apply_pending {
 }
 }
 
+my $safe_num_ne = sub {
+my ($a, $b) = @_;
+
+return 0 if !defined($a)  !defined($b);
+return 1 if !defined($a);
+return 1 if !defined($b);
+
+return $a != $b;
+};
+
+my $safe_string_ne = sub 

[pve-devel] [PATCH v5 11/19] vmconfig_cleanup_pending: new method to clenup setting in [PENDING]

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm  |8 +---
 PVE/QemuServer.pm |   32 
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index a8841c2..8c7c076 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -1006,14 +1006,8 @@ my $update_vm_api  = sub {
}
 
# remove pending changes when nothing changed
-   my $changes;
$conf = PVE::QemuServer::load_config($vmid); # update/reload
-   foreach my $opt (keys %{$conf-{pending}}) { # add/change
-   if (defined($conf-{$opt})  ($conf-{pending}-{$opt} eq  
$conf-{$opt})) {
-   $changes = 1;
-   delete $conf-{pending}-{$opt};
-   }
-   }
+   my $changes = PVE::QemuServer::vmconfig_cleanup_pending($conf);
PVE::QemuServer::update_config_nolock($vmid, $conf, 1) if $changes;
 
return if !scalar(keys %{$conf-{pending}});
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 7219353..2644117 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1442,6 +1442,38 @@ sub vmconfig_register_unused_drive {
 }
 }
 
+sub vmconfig_cleanup_pending {
+my ($conf) = @_;
+
+# remove pending changes when nothing changed
+my $changes;
+foreach my $opt (keys %{$conf-{pending}}) {
+   if (defined($conf-{$opt})  ($conf-{pending}-{$opt} eq  
$conf-{$opt})) {
+   $changes = 1;
+   delete $conf-{pending}-{$opt};
+   }
+}
+
+# remove delete if option is not set
+my $pending_delete_hash = {};
+foreach my $opt (PVE::Tools::split_list($conf-{pending}-{delete})) {
+   if (defined($conf-{$opt})) {
+   $pending_delete_hash-{$opt} = 1;
+   } else {
+   $changes = 1;
+   }
+}
+
+my @keylist = keys %$pending_delete_hash;
+if (scalar(@keylist)) {
+   $conf-{pending}-{delete} = join(',', @keylist);
+} else {
+   delete $conf-{pending}-{delete};
+}
+
+return $changes;
+}
+
 my $valid_smbios1_options = {
 manufacturer = '\S+',
 product = '\S+',
-- 
1.7.10.4

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


[pve-devel] [PATCH v5 06/19] implement vmconfig_apply_pending for stopped VM

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm |  191 ++
 1 file changed, 119 insertions(+), 72 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 222c44f..41d75d0 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -37,6 +37,73 @@ 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 ($force || $key =~ m/^unused/) {
+   my $sid = PVE::Storage::parse_volume_id($volid);
+   return $sid;
+   }
+   }
+}
+
+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) = @_;
@@ -639,36 +706,6 @@ __PACKAGE__-register_method({
return $conf;
 }});
 
-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 ($force || $key =~ m/^unused/) {
-   my $sid = PVE::Storage::parse_volume_id($volid);
-   return $sid;
-   }
-   }
-}
-
-return undef;
-};
-
 my $delete_drive = sub {
 my ($conf, $storecfg, $vmid, $key, $drive, $force) = @_;
 
@@ -868,6 +905,48 @@ 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});
+   

[pve-devel] [PATCH v5 14/19] implement API/CLI to get pending changes

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm |   86 +-
 qm   |   27 +
 2 files changed, 112 insertions(+), 1 deletion(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index b116c24..98a42fe 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -624,7 +624,7 @@ __PACKAGE__-register_method({
 path = '{vmid}/config',
 method = 'GET',
 proxyto = 'node',
-description = Get virtual machine configuration.,
+description = Get current virtual machine configuration. This does not 
include pending configuration changes (see 'pending' API).,
 permissions = {
check = ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
 },
@@ -650,10 +650,94 @@ __PACKAGE__-register_method({
my $conf = PVE::QemuServer::load_config($param-{vmid});
 
delete $conf-{snapshots};
+   delete $conf-{pending};
 
return $conf;
 }});
 
+__PACKAGE__-register_method({
+name = 'vm_pending',
+path = '{vmid}/pending',
+method = 'GET',
+proxyto = 'node',
+description = Get virtual machine configuration, including pending 
changes.,
+permissions = {
+   check = ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
+},
+parameters = {
+   additionalProperties = 0,
+   properties = {
+   node = get_standard_option('pve-node'),
+   vmid = get_standard_option('pve-vmid'),
+   },
+},
+returns = {
+   type = array,
+   items = {
+   type = object,
+   properties = {
+   key = {
+   description = Configuration option name.,
+   type = 'string',
+   },
+   value = {
+   description = Current value.,
+   type = 'string',
+   optional = 1,
+   },
+   pending = {
+   description = Pending value.,
+   type = 'string',
+   optional = 1,
+   },
+   delete = {
+   description = Indicated a pending delete request.,
+   type = 'boolean',
+   optional = 1,
+   },
+   },
+   },
+},
+code = sub {
+   my ($param) = @_;
+
+   my $conf = PVE::QemuServer::load_config($param-{vmid});
+
+   my $pending_delete_hash = {};
+   foreach my $opt (PVE::Tools::split_list($conf-{pending}-{delete})) {
+   $pending_delete_hash-{$opt} = 1;
+   }
+
+   my $res = [];
+
+   foreach my $opt (keys $conf) {
+   next if ref($conf-{$opt});
+   my $item = { key = $opt };
+   $item-{value} = $conf-{$opt} if defined($conf-{$opt});
+   $item-{pending} = $conf-{pending}-{$opt} if 
defined($conf-{pending}-{$opt});
+   $item-{delete} = 1 if $pending_delete_hash-{$opt};
+   push @$res, $item;
+   }
+
+   foreach my $opt (keys $conf-{pending}) {
+   next if $opt eq 'delete';
+   next if ref($conf-{pending}-{$opt}); # just to be sure
+   next if $conf-{$opt};
+   my $item = { key = $opt };
+   $item-{pending} = $conf-{pending}-{$opt};
+   push @$res, $item;
+   }
+
+   foreach my $opt (PVE::Tools::split_list($conf-{pending}-{delete})) {
+   next if $conf-{pending}-{$opt}; # just to be sure
+   next if $conf-{$opt};
+   my $item = { key = $opt, delete = 1};
+   push @$res, $item;
+   }
+
+   return $res;
+}});
+
 my $delete_drive = sub {
 my ($conf, $storecfg, $vmid, $key, $drive, $force) = @_;
 
diff --git a/qm b/qm
index cea223e..249117c 100755
--- a/qm
+++ b/qm
@@ -437,6 +437,33 @@ my $cmddef = {
}
}],

+pending = [ PVE::API2::Qemu, 'vm_pending', ['vmid'],
+   { node = $nodename }, sub {
+   my $data = shift;
+   foreach my $item (sort { $a-{key} cmp $b-{key}} @$data) {
+   my $k = $item-{key};
+   next if $k eq 'digest';
+   my $v = $item-{value};
+   my $p = $item-{pending};
+   if ($k eq 'description') {
+   $v = PVE::Tools::encode_text($v) if defined($v);
+   $p = PVE::Tools::encode_text($p) if defined($p);
+   }
+   if (defined($v)) {
+   if ($item-{delete}) {
+   print del $k: $v\n;
+   } elsif (defined($p)) {
+   print cur $k: $v\n;
+   print new $k: $p\n;
+   } else {
+   print cur $k: $v\n;
+   }
+   } elsif (defined($p)) {
+   print new $k: $p\n;
+  

[pve-devel] [PATCH v5 07/19] vm_start: apply pending changes

2014-11-25 Thread Dietmar Maurer
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 41d75d0..d6a70c0 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 

[pve-devel] [PATCH v5 19/19] vm_deviceplug: always raise exception on error

2014-11-25 Thread Dietmar Maurer

Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   92 -
 1 file changed, 49 insertions(+), 43 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 14989f8..243d069 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3032,73 +3032,80 @@ sub vm_devices_list {
 return $devices;
 }
 
-# fixme: this should raise exceptions on error!
 sub vm_deviceplug {
 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
 
-return 1 if !check_running($vmid);
+die internal error if !$conf-{hotplug};
 
 my $q35 = machine_type_is_q35($conf);
 
-return 1 if !$conf-{hotplug};
-
 my $devices_list = vm_devices_list($vmid);
 return 1 if defined($devices_list-{$deviceid});
 
+qemu_add_pci_bridge($storecfg, $conf, $vmid, $deviceid); # add PCI bridge 
if we need it for the device
+
 if ($deviceid eq 'tablet') {
+
qemu_deviceadd($vmid, print_tabletdevice_full($conf));
-   return 1;
-}
 
-qemu_add_pci_bridge($storecfg, $conf, $vmid, $deviceid); # add PCI bridge 
if we need it for the device
+} elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
 
-if ($deviceid =~ m/^(virtio)(\d+)$/) {
-return undef if !qemu_driveadd($storecfg, $vmid, $device);
+qemu_driveadd($storecfg, $vmid, $device);
 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, 
$device);
+
 qemu_deviceadd($vmid, $devicefull);
-if(!qemu_deviceaddverify($vmid, $deviceid)) {
+   eval { qemu_deviceaddverify($vmid, $deviceid); };
+   if (my $err = $@) {
eval { qemu_drivedel($vmid, $deviceid); };
warn $@ if $@;
-   return undef;
+   die $err;
 }
-}
 
-if ($deviceid =~ m/^(scsihw)(\d+)$/) {
+} elsif ($deviceid =~ m/^(scsihw)(\d+)$/) {
+
 my $scsihw = defined($conf-{scsihw}) ? $conf-{scsihw} : lsi;
 my $pciaddr = print_pci_addr($deviceid);
 my $devicefull = $scsihw,id=$deviceid$pciaddr;
+
 qemu_deviceadd($vmid, $devicefull);
-return undef if(!qemu_deviceaddverify($vmid, $deviceid));
-}
+qemu_deviceaddverify($vmid, $deviceid);
 
-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);
-if(!qemu_deviceadd($vmid, $devicefull)) { # fixme: use 
qemu_deviceaddverify?
+} elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
+
+qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device);
+qemu_driveadd($storecfg, $vmid, $device);
+
+   my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, 
$device);
+   eval { qemu_deviceadd($vmid, $devicefull); };
+   if (my $err = $@) {
eval { qemu_drivedel($vmid, $deviceid); };
warn $@ if $@;
-   return undef;
+   die $err;
 }
-}
 
-if ($deviceid =~ m/^(net)(\d+)$/) {
+} elsif ($deviceid =~ m/^(net)(\d+)$/) {
+
 return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid);
 my $netdevicefull = print_netdevice_full($vmid, $conf, $device, 
$deviceid);
 qemu_deviceadd($vmid, $netdevicefull);
-if(!qemu_deviceaddverify($vmid, $deviceid)) {
-   qemu_netdevdel($vmid, $deviceid);
-   return undef;
+eval { qemu_deviceaddverify($vmid, $deviceid); };
+   if (my $err = $@) {
+   eval { qemu_netdevdel($vmid, $deviceid); };
+   warn $@ if $@;
+   die $err;
 }
-}
 
+} elsif (!$q35  $deviceid =~ m/^(pci\.)(\d+)$/) {
 
-if (!$q35  $deviceid =~ m/^(pci\.)(\d+)$/) {
my $bridgeid = $2;
my $pciaddr = print_pci_addr($deviceid);
my $devicefull = 
pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr;
+   
qemu_deviceadd($vmid, $devicefull);
-   return undef if !qemu_deviceaddverify($vmid, $deviceid);
+   qemu_deviceaddverify($vmid, $deviceid);
+
+} else {
+   die can't hotplug device '$deviceid'\n;   
 }
 
 return 1;
@@ -3154,26 +3161,24 @@ sub qemu_deviceadd {
 my %options =  split(/[=,]/, $devicefull);
 
 vm_mon_cmd($vmid, device_add , %options);
-return 1;
 }
 
 sub qemu_devicedel {
-my($vmid, $deviceid) = @_;
+my ($vmid, $deviceid) = @_;
 
 my $ret = vm_mon_cmd($vmid, device_del, id = $deviceid);
 }
 
 sub qemu_driveadd {
-my($storecfg, $vmid, $device) = @_;
+my ($storecfg, $vmid, $device) = @_;
 
 my $drive = print_drive_full($storecfg, $vmid, $device);
 my $ret = vm_human_monitor_command($vmid, drive_add auto $drive);
+
 # If the command succeeds qemu prints: OK
-if ($ret !~ m/OK/s) {
-syslog(err, adding drive failed: $ret);
-return undef;
-}
-return 1;
+return 1 if $ret =~ 

[pve-devel] [PATCH v5 18/19] vm_deviceunplug: raise expection if something fail

2014-11-25 Thread Dietmar Maurer

Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   81 +++--
 1 file changed, 42 insertions(+), 39 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index c568dfd..14989f8 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3057,8 +3057,9 @@ sub vm_deviceplug {
 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, 
$device);
 qemu_deviceadd($vmid, $devicefull);
 if(!qemu_deviceaddverify($vmid, $deviceid)) {
-   qemu_drivedel($vmid, $deviceid);
-   return undef;
+   eval { qemu_drivedel($vmid, $deviceid); };
+   warn $@ if $@;
+   return undef;
 }
 }
 
@@ -3075,8 +3076,9 @@ sub vm_deviceplug {
 return undef if !qemu_driveadd($storecfg, $vmid, $device);
 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, 
$device);
 if(!qemu_deviceadd($vmid, $devicefull)) { # fixme: use 
qemu_deviceaddverify?
-   qemu_drivedel($vmid, $deviceid);
-   return undef;
+   eval { qemu_drivedel($vmid, $deviceid); };
+   warn $@ if $@;
+   return undef;
 }
 }
 
@@ -3106,39 +3108,40 @@ sub vm_deviceplug {
 sub vm_deviceunplug {
 my ($vmid, $conf, $deviceid) = @_;
 
-return 1 if !check_running ($vmid);
-
-return 1 if !$conf-{hotplug};
+die internal error if !$conf-{hotplug};
 
 my $devices_list = vm_devices_list($vmid);
 return 1 if !defined($devices_list-{$deviceid});
 
+die can't unplug bootdisk if $conf-{bootdisk}  $conf-{bootdisk} eq 
$deviceid;
+
 if ($deviceid eq 'tablet') {
+
qemu_devicedel($vmid, $deviceid);
-   return 1;
-}
 
-die can't unplug bootdisk if $conf-{bootdisk}  $conf-{bootdisk} eq 
$deviceid;
+} elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
 
-if ($deviceid =~ m/^(virtio)(\d+)$/) {
 qemu_devicedel($vmid, $deviceid);
-return undef if !qemu_devicedelverify($vmid, $deviceid);
-return undef if !qemu_drivedel($vmid, $deviceid);
-}
-
-if ($deviceid =~ m/^(lsi)(\d+)$/) {
-return undef if !qemu_devicedel($vmid, $deviceid);
-}
+qemu_devicedelverify($vmid, $deviceid);
+qemu_drivedel($vmid, $deviceid);
+   
+} elsif ($deviceid =~ m/^(lsi)(\d+)$/) {
+
+   qemu_devicedel($vmid, $deviceid);
+
+} elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
 
-if ($deviceid =~ m/^(scsi)(\d+)$/) {
-return undef if !qemu_devicedel($vmid, $deviceid);
-return undef if !qemu_drivedel($vmid, $deviceid);
-}
+qemu_devicedel($vmid, $deviceid);
+qemu_drivedel($vmid, $deviceid);
+
+} elsif ($deviceid =~ m/^(net)(\d+)$/) {
 
-if ($deviceid =~ m/^(net)(\d+)$/) {
 qemu_devicedel($vmid, $deviceid);
-return undef if !qemu_devicedelverify($vmid, $deviceid);
-return undef if !qemu_netdevdel($vmid, $deviceid);
+qemu_devicedelverify($vmid, $deviceid);
+qemu_netdevdel($vmid, $deviceid);
+
+} else {
+   die can't unplug device '$deviceid'\n;
 }
 
 return 1;
@@ -3156,8 +3159,8 @@ sub qemu_deviceadd {
 
 sub qemu_devicedel {
 my($vmid, $deviceid) = @_;
+
 my $ret = vm_mon_cmd($vmid, device_del, id = $deviceid);
-return 1;
 }
 
 sub qemu_driveadd {
@@ -3178,14 +3181,13 @@ sub qemu_drivedel {
 
 my $ret = vm_human_monitor_command($vmid, drive_del drive-$deviceid);
 $ret =~ s/^\s+//;
-if ($ret =~ m/Device \'.*?\' not found/s) {
-# NB: device not found errors mean the drive was auto-deleted and we 
ignore the error
-}
-elsif ($ret ne ) {
-  syslog(err, deleting drive $deviceid failed : $ret);
-  return undef;
-}
-return 1;
+
+return 1 if $ret eq ;
+  
+# NB: device not found errors mean the drive was auto-deleted and we 
ignore the error
+return 1 if $ret =~ m/Device \'.*?\' not found/s; 
+
+die deleting drive $deviceid failed : $ret\n;
 }
 
 sub qemu_deviceaddverify {
@@ -3202,16 +3204,18 @@ sub qemu_deviceaddverify {
 
 
 sub qemu_devicedelverify {
-my ($vmid,$deviceid) = @_;
+my ($vmid, $deviceid) = @_;
+
+# need to verify that the device is correctly removed as device_del 
+# is async and empty return is not reliable
 
-#need to verify the device is correctly remove as device_del is async and 
empty return is not reliable
 for (my $i = 0; $i = 5; $i++) {
  my $devices_list = vm_devices_list($vmid);
  return 1 if !defined($devices_list-{$deviceid});
  sleep 1;
 }
-syslog(err, error on hot-unplugging device $deviceid);
-return undef;
+
+die error on hot-unplugging device '$deviceid'\n;
 }
 
 sub qemu_findorcreatescsihw {
@@ -3266,7 +3270,6 @@ sub qemu_netdevdel {
 my ($vmid, $deviceid) = @_;
 
 vm_mon_cmd($vmid, netdev_del, id = $deviceid);
-return 1;
 }
 
 sub qemu_cpu_hotplug {
-- 
1.7.10.4


[pve-devel] [PATCH v5 15/19] rename qemu_bridgeadd to qemu_add_pci_bridge

2014-11-25 Thread Dietmar Maurer
To make it obvious that we add a PCI device, and not a network bridge.

Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 391376e..a8828be 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3049,7 +3049,7 @@ sub vm_deviceplug {
return 1;
 }
 
-qemu_bridgeadd($storecfg, $conf, $vmid, $deviceid); #add bridge if we need 
it for the device
+qemu_add_pci_bridge($storecfg, $conf, $vmid, $deviceid); # add PCI bridge 
if we need it for the device
 
 if ($deviceid =~ m/^(virtio)(\d+)$/) {
 return undef if !qemu_driveadd($storecfg, $vmid, $device);
@@ -3226,23 +3226,27 @@ sub qemu_findorcreatescsihw {
 return 1;
 }
 
-sub qemu_bridgeadd {
+sub qemu_add_pci_bridge {
 my ($storecfg, $conf, $vmid, $device) = @_;
 
 my $bridges = {};
-my $bridgeid = undef;
+
+my $bridgeid;
+
 print_pci_addr($device, $bridges);
 
 while (my ($k, $v) = each %$bridges) {
$bridgeid = $k;
 }
-return if !$bridgeid || $bridgeid  1;
+return if !defined($bridgeid) || $bridgeid  1;
+
 my $bridge = pci.$bridgeid;
 my $devices_list = vm_devices_list($vmid);
 
-if(!defined($devices_list-{$bridge})) {
+if (!defined($devices_list-{$bridge})) {
return undef if !vm_deviceplug($storecfg, $conf, $vmid, $bridge);
 }
+
 return 1;
 }
 
-- 
1.7.10.4

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


[pve-devel] [PATCH v5 16/19] vmconfig_hotplug_pending: correctly skip values

2014-11-25 Thread Dietmar Maurer
Do not use $skip variable (simply raise an exception)

Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   26 +++---
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index a8828be..6642928 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3521,26 +3521,24 @@ sub vmconfig_hotplug_pending {
 my @delete = PVE::Tools::split_list($conf-{pending}-{delete});
 foreach my $opt (@delete) {
next if $selection  !$selection-{$opt};
-   my $skip;
eval {
if ($opt eq 'tablet') {
-   return undef if !$hotplug;
+   die skip\n if !$hotplug;
if ($defaults-{tablet}) {
vm_deviceplug($storecfg, $conf, $vmid, $opt);
} else {
vm_deviceunplug($vmid, $conf, $opt);
}
} elsif ($opt eq 'cores') {
-   return undef if !$hotplug;
+   die skip\n if !$hotplug;
qemu_cpu_hotplug($vmid, $conf, 1);
} else {
-   $skip = 1; # skip non-hot-pluggable options
-   return undef;
+   die skip\n;
}
};
if (my $err = $@) {
-   $add_error($opt, $err);
-   } elsif (!$skip) {
+   $add_error($opt, $err) if $err ne skip\n;
+   } else {
# save new config if hotplug was successful
delete $conf-{$opt};
vmconfig_undelete_pending_option($conf, $opt);
@@ -3552,31 +3550,29 @@ sub vmconfig_hotplug_pending {
 foreach my $opt (keys %{$conf-{pending}}) {
next if $selection  !$selection-{$opt};
my $value = $conf-{pending}-{$opt};
-   my $skip;
eval {
if ($opt eq 'tablet') {
-   return undef if !$hotplug;
+   die skip\n if !$hotplug;
if ($value == 1) {
vm_deviceplug($storecfg, $conf, $vmid, $opt);
} elsif ($value == 0) {
vm_deviceunplug($vmid, $conf, $opt);
}
} elsif ($opt eq 'cores') {
-   return undef if !$hotplug;
+   die skip\n if !$hotplug;
qemu_cpu_hotplug($vmid, $conf, $value);
} elsif ($opt eq 'balloon') {
-   return undef if !(defined($conf-{shares})  ($conf-{shares} 
== 0));
+   die skip\n if !(defined($conf-{shares})  ($conf-{shares} 
== 0));
# allow manual ballooning if shares is set to zero
my $balloon = $conf-{pending}-{balloon} || $conf-{memory} || 
$defaults-{memory};
vm_mon_cmd($vmid, balloon, value = $balloon*1024*1024);
} else {
-   $skip = 1; # skip non-hot-pluggable options
-   return undef;
+   die skip\n;  # skip non-hot-pluggable options
}
};
if (my $err = $@) {
-   $add_error($opt, $err);
-   } elsif (!$skip) {
+   $add_error($opt, $err) if $err ne skip\n;
+   } else {
# save new config if hotplug was successful
$conf-{$opt} = $value;
delete $conf-{pending}-{$opt};
-- 
1.7.10.4

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


[pve-devel] [PATCH 2/2] now if the QMP command starts with guest-+ , it will bind dynamicly to the VMID.qga socket.

2014-11-25 Thread Wolfgang Link
Signed-off-by: Wolfgang Link wolfg...@linksystems.org
---
 PVE/QMPClient.pm  |   54 +
 PVE/QemuServer.pm |   16 +---
 2 files changed, 39 insertions(+), 31 deletions(-)

diff --git a/PVE/QMPClient.pm b/PVE/QMPClient.pm
index 9674d00..b5684b6 100755
--- a/PVE/QMPClient.pm
+++ b/PVE/QMPClient.pm
@@ -20,7 +20,7 @@ use Data::Dumper;
 # Note: kvm can onyl handle 1 connection, so we close connections asap
 
 sub new {
-my ($class, $eventcb, $qga) = @_;
+my ($class, $eventcb) = @_;
 
 my $mux = new IO::Multiplex;
 
@@ -34,7 +34,6 @@ sub new {
 }, $class;
 
 $self-{eventcb} = $eventcb if $eventcb;
-$self-{qga} = $qga if $qga;
 
 $mux-set_callback_object($self);
 
@@ -106,9 +105,18 @@ sub cmd {
 };
 
 my $cmdid_seq = 0;
+my $cmdid_seq_qga = 0;
+
 my $next_cmdid = sub {
-$cmdid_seq++;
-return $$.0.$cmdid_seq;
+my ($qga) = @_;
+
+if($qga){
+   $cmdid_seq++;
+   return $$:$cmdid_seq;
+} else {
+   $cmdid_seq_qga++;
+   return $$.0.$cmdid_seq_qga;
+}
 };
 
 my $close_connection = sub {
@@ -124,9 +132,9 @@ my $close_connection = sub {
 };
 
 my $open_connection = sub {
-my ($self, $vmid, $timeout) = @_;
+my ($self, $vmid, $timeout, $qga) = @_;
 
-my $sname = PVE::QemuServer::qmp_socket($vmid, $self-{qga});
+my $sname = PVE::QemuServer::qmp_socket($vmid, $qga);
 
 $timeout = 1 if !$timeout;
 
@@ -181,7 +189,8 @@ my $check_queue = sub {
eval {
 
my $cmd = $self-{current}-{$vmid} = shift 
@{$self-{queue}-{$vmid}};
-   $cmd-{id} = $next_cmdid();
+
+   $cmd-{id} = $next_cmdid($cmd-{qga});
 
my $fd = -1;
if ($cmd-{execute} eq 'add-fd' || $cmd-{execute} eq 'getfd') {
@@ -191,7 +200,7 @@ my $check_queue = sub {
 
my $qmpcmd = undef;
 
-   if($self-{qga}){
+   if($self-{current}-{$vmid}-{qga}){
 
my $qmpcmdid =to_json({
execute = 'guest-sync',
@@ -242,11 +251,15 @@ sub queue_execute {
 # open all necessary connections
 foreach my $vmid (keys %{$self-{queue}}) {
next if !scalar(@{$self-{queue}-{$vmid}}); # no commands for the VM
+   
+   if ($self-{queue}-{$vmid}[0]-{execute} =~ /^guest\-+/){
+   $self-{queue}-{$vmid}[0]-{qga} = 1;
+   }
 
eval {
-   my $fh = $open_connection($self, $vmid, $timeout);
+   my $fh = $open_connection($self, $vmid, $timeout, 
$self-{queue}-{$vmid}[0]-{qga});
   
-if(!$self-{qga}){
+if(!$self-{queue}-{$vmid}[0]-{qga}){
 my $cmd = { execute = 'qmp_capabilities', arguments = {} };
 unshift @{$self-{queue}-{$vmid}}, $cmd;
 
@@ -290,16 +303,17 @@ sub mux_close {
 # the descriptors.
 sub mux_input {
 my ($self, $mux, $fh, $input) = @_;
-   
-if($self-{qga}){
-   return if $$input !~ m/}\n(.+)}\n$/;
-}else{
-   return if $$input !~ m/}\r\n$/;
-}
 
-my $raw = $$input;
+my $vmid = $self-{fhs_lookup}-{$fh};
+my $raw;
+if ($self-{current}-{$vmid}-{qga}) {
+   return if $$input !~ s/^([^\n]+}\n[^\n]+})\n(.*)$/$2/so;
+   $raw = $1;
+} else {
+   return if $$input !~ s/^([^\n]+})\r?\n(.*)$/$2/so;
+   $raw = $1;
+}
 
-my $vmid = $self-{fhs_lookup}-{$fh};
 if (!$vmid) {
warn internal error - unable to lookup vmid;
return;
@@ -308,7 +322,7 @@ sub mux_input {
 eval {
my @jsons = split(\n, $raw);
 
-   if($self-{qga}){
+   if($self-{current}-{$vmid}-{qga}){
 
die response is not complete if @jsons != 2 ;
 
@@ -328,7 +342,7 @@ sub mux_input {
$obj = from_json($jsons[1]);
 
if (my $callback = $curcmd-{callback}) {
-   $callback($vmid, $obj);
+   $callback($vmid, $obj);   
}
 
return;
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index d740564..ab02b93 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -2881,13 +2881,6 @@ sub qga_socket {
 return ${var_run_tmpdir}/$vmid.qga;
 }
 
-sub vm_qga_cmd {
-my ($vmid, $execute, %params) = @_;
-
-my $cmd = { execute = $execute, arguments = \%params };
-vm_qmp_command($vmid, $cmd, undef, 1);
-}
-
 sub pidfile_name {
 my ($vmid) = @_;
 return ${var_run_tmpdir}/$vmid.pid;
@@ -3481,7 +3474,7 @@ sub vm_mon_cmd_nocheck {
 }
 
 sub vm_qmp_command {
-my ($vmid, $cmd, $nocheck, $qga) = @_;
+my ($vmid, $cmd, $nocheck) = @_;
 
 my $res;
 
@@ -3493,12 +3486,13 @@ sub vm_qmp_command {
 
 eval {
die VM $vmid not running\n if !check_running($vmid, $nocheck);
-   my $sname = qmp_socket($vmid, $qga);
+   my $qga = ($cmd-{execute} =~ /^guest\-+/)?1:0;
+   my $sname = qmp_socket($vmid,$qga);
if (-e $sname) {
-   my $qmpclient = PVE::QMPClient-new(undef, $qga);
+   my $qmpclient = PVE::QMPClient-new();
 
   

[pve-devel] [PATCH 1/2] This are the condensed changes form http://pve.proxmox.com/pipermail/pve-devel/2013-March/006913.html is added to see the orgin work!

2014-11-25 Thread Wolfgang Link
From: Alexandre Derumier aderum...@odiso.com

This patch series add code to send command to quest guest agent.

The procotol is qmp, so I have reuse as much as possible the current qmpclient

the only big difference is that we can't pass an id to a request, so we must 
send a guest-sync command with an id before the real command

command

{ execute: guest-sync, arguments: { id: 123456 } 
}{execute:guest-ping}

result

{ return: 123456}\n{return: {}}


Signed-off-by: Alexandre Derumier aderum...@odiso.com
---
 PVE/QMPClient.pm  |   77 -
 PVE/QemuServer.pm |   20 +-
 2 files changed, 78 insertions(+), 19 deletions(-)

diff --git a/PVE/QMPClient.pm b/PVE/QMPClient.pm
index 4e24419..9674d00 100755
--- a/PVE/QMPClient.pm
+++ b/PVE/QMPClient.pm
@@ -20,7 +20,7 @@ use Data::Dumper;
 # Note: kvm can onyl handle 1 connection, so we close connections asap
 
 sub new {
-my ($class, $eventcb) = @_;
+my ($class, $eventcb, $qga) = @_;
 
 my $mux = new IO::Multiplex;
 
@@ -34,6 +34,7 @@ sub new {
 }, $class;
 
 $self-{eventcb} = $eventcb if $eventcb;
+$self-{qga} = $qga if $qga;
 
 $mux-set_callback_object($self);
 
@@ -107,7 +108,7 @@ sub cmd {
 my $cmdid_seq = 0;
 my $next_cmdid = sub {
 $cmdid_seq++;
-return $$:$cmdid_seq;
+return $$.0.$cmdid_seq;
 };
 
 my $close_connection = sub {
@@ -125,7 +126,7 @@ my $close_connection = sub {
 my $open_connection = sub {
 my ($self, $vmid, $timeout) = @_;
 
-my $sname = PVE::QemuServer::qmp_socket($vmid);
+my $sname = PVE::QemuServer::qmp_socket($vmid, $self-{qga});
 
 $timeout = 1 if !$timeout;
 
@@ -188,10 +189,27 @@ my $check_queue = sub {
delete $cmd-{arguments}-{fd};
}
 
-   my $qmpcmd = to_json({
-   execute = $cmd-{execute},
-   arguments = $cmd-{arguments},
-   id = $cmd-{id}});
+   my $qmpcmd = undef;
+
+   if($self-{qga}){
+
+   my $qmpcmdid =to_json({
+   execute = 'guest-sync',
+   arguments = { id = int($cmd-{id})}});
+
+   $qmpcmd = to_json({
+   execute = $cmd-{execute},
+   arguments = $cmd-{arguments}});
+
+   $qmpcmd = $qmpcmdid.$qmpcmd;
+
+   }else{
+
+   $qmpcmd = to_json({
+   execute = $cmd-{execute},
+   arguments = $cmd-{arguments},
+   id = $cmd-{id}});
+   }
 
if ($fd = 0) {
my $ret = PVE::IPCC::sendfd(fileno($fh), $fd, $qmpcmd);
@@ -227,16 +245,19 @@ sub queue_execute {
 
eval {
my $fh = $open_connection($self, $vmid, $timeout);
-   my $cmd = { execute = 'qmp_capabilities', arguments = {} };
-   unshift @{$self-{queue}-{$vmid}}, $cmd;
+  
+if(!$self-{qga}){
+my $cmd = { execute = 'qmp_capabilities', arguments = {} };
+unshift @{$self-{queue}-{$vmid}}, $cmd;
+
$self-{mux}-set_timeout($fh, $timeout);
};
if (my $err = $@) {
warn $err;
$self-{errors}-{$vmid} = $err;
}
+   }
 }
-
 my $running;
 
 for (;;) {
@@ -269,10 +290,14 @@ sub mux_close {
 # the descriptors.
 sub mux_input {
 my ($self, $mux, $fh, $input) = @_;
+   
+if($self-{qga}){
+   return if $$input !~ m/}\n(.+)}\n$/;
+}else{
+   return if $$input !~ m/}\r\n$/;
+}
 
-return if $$input !~ s/^(.*})\r\n(.*)$/$2/so;
-
-my $raw = $1;
+my $raw = $$input;
 
 my $vmid = $self-{fhs_lookup}-{$fh};
 if (!$vmid) {
@@ -283,6 +308,32 @@ sub mux_input {
 eval {
my @jsons = split(\n, $raw);
 
+   if($self-{qga}){
+
+   die response is not complete if @jsons != 2 ;
+
+   my $obj = from_json($jsons[0]);
+   my $cmdid = $obj-{return};
+   die received responsed without command id\n if !$cmdid;
+
+   my $curcmd = $self-{current}-{$vmid};
+   die unable to lookup current command for VM $vmid\n if !$curcmd;
+
+   delete $self-{current}-{$vmid};
+
+   if ($curcmd-{id} ne $cmdid) {
+   die got wrong command id '$cmdid' (expected $curcmd-{id})\n;
+   }
+
+   $obj = from_json($jsons[1]);
+
+   if (my $callback = $curcmd-{callback}) {
+   $callback($vmid, $obj);
+   }
+
+   return;
+   }
+
foreach my $json (@jsons) {
my $obj = from_json($json);
next if defined($obj-{QMP}); # skip monitor greeting
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 2970598..d740564 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -2871,8 +2871,9 @@ sub spice_port {
 }
 
 sub qmp_socket {
-my ($vmid) = @_;
-return ${var_run_tmpdir}/$vmid.qmp;
+my ($vmid, $qga) = @_;
+my $sockettype = $qga ? 'qga' : 'qmp';
+  

Re: [pve-devel] vm_deviceunplug question

2014-11-25 Thread Alexandre DERUMIER
I cannot see that: 

3001 if ($deviceid =~ m/^(scsi)(\d+)$/) { 
3002 return undef if !qemu_devicedel($vmid, $deviceid); 
3003 return undef if !qemu_drivedel($vmid, $deviceid); 
3004 } 

so you also remove the device using qemu_devicedel()? 
What do I miss? 


for virtio:

-device virtio-blk-pci,drive=drive-virtio0,id=virtio0,bus=pci.0,addr=0xa
-drive 
file=/var/lib/vz/images/115/vm-115-disk-34.raw,if=none,id=drive-virtio4,format=raw,aio=native,cache=none,detect-zeroes=on

we remove virtio-blk-pci device and drive. (so we check that the pci 
device|controller is unplugged - need acpi hotplug)


for scsi:

-device virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5 
-drive file=/var/lib/vz/images/115/vm-115-disk-34.raw,if=none,id=drive-scsi0
-device 
scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0


we remove scsi-hd device and drive. (this is not a pci device|controler,so we 
don't need to check if removal is ok).




- Mail original - 

De: Dietmar Maurer diet...@proxmox.com 
À: Alexandre DERUMIER aderum...@odiso.com 
Cc: pve-devel@pve.proxmox.com 
Envoyé: Mardi 25 Novembre 2014 10:10:45 
Objet: RE: vm_deviceunplug question 

 This is because for virtio disk we remove the controller + drive, 
 (1controller - 1 
 drive) 
 
 and for scsi we only remove the drive (1controller - 256 drives) 

I cannot see that: 

3001 if ($deviceid =~ m/^(scsi)(\d+)$/) { 
3002 return undef if !qemu_devicedel($vmid, $deviceid); 
3003 return undef if !qemu_drivedel($vmid, $deviceid); 
3004 } 

so you also remove the device using qemu_devicedel()? 
What do I miss? 
___
pve-devel mailing list
pve-devel@pve.proxmox.com
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] vm_deviceunplug question

2014-11-25 Thread Dietmar Maurer
 for scsi:
 
 -device virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5
 -drive file=/var/lib/vz/images/115/vm-115-disk-34.raw,if=none,id=drive-scsi0
 -device scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-
 scsi0,id=scsi0
 
 
 we remove scsi-hd device and drive. (this is not a pci device|controler,so we
 don't need to check if removal is ok).

Ah, OK -  thank for the explanation.

Please can you also review the latest hotplug changes, especially the
error handling? I think we get better error messages this way.

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


Re: [pve-devel] vm_deviceunplug question

2014-11-25 Thread Alexandre DERUMIER
Please can you also review the latest hotplug changes, especially the
error handling? I think we get better error messages this way.

Yes, I wanted to fix that since a long time, thanks.

About network hotplug,
I have exception if I try to change the bridge for example, and conf-{hotplug} 
= 0.

I think this is because be always call   

vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);

at the end of vmconfig_update_net.



- Mail original - 

De: Dietmar Maurer diet...@proxmox.com 
À: Alexandre DERUMIER aderum...@odiso.com 
Cc: pve-devel@pve.proxmox.com 
Envoyé: Mardi 25 Novembre 2014 10:46:33 
Objet: RE: vm_deviceunplug question 

 for scsi: 
 
 -device virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5 
 -drive file=/var/lib/vz/images/115/vm-115-disk-34.raw,if=none,id=drive-scsi0 
 -device scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive- 
 scsi0,id=scsi0 
 
 
 we remove scsi-hd device and drive. (this is not a pci device|controler,so we 
 don't need to check if removal is ok). 

Ah, OK - thank for the explanation. 

Please can you also review the latest hotplug changes, especially the 
error handling? I think we get better error messages this way. 
___
pve-devel mailing list
pve-devel@pve.proxmox.com
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


Re: [pve-devel] vm_deviceunplug question

2014-11-25 Thread Dietmar Maurer
 Yes, I wanted to fix that since a long time, thanks.

OK

 About network hotplug,
 I have exception if I try to change the bridge for example, and 
 conf-{hotplug} =
 0.
 
 I think this is because be always call
 
 vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
 
 at the end of vmconfig_update_net.

OK, will try to fix.
___
pve-devel mailing list
pve-devel@pve.proxmox.com
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


[pve-devel] [PATCH v6 04/22] write_vm_config : write pending change

2014-11-25 Thread Dietmar Maurer
example:

$conf-{pending}-{virtio1}
$conf-{pending}-{delete} = net0,net1

[PENDING]
virtio1: ...
delete: net0,net1

Signed-off-by: Alexandre Derumier aderum...@odiso.com
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   32 +---
 1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 9b03e6a..f6b8ce2 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1826,10 +1826,12 @@ sub parse_vm_config {
my $key = $1;
my $value = $2;
$conf-{$key} = $value;
-   } elsif (($section eq 'pending')  ($line =~ 
m/^delete:\s*(.*\S)\s*$/)) {
+   } elsif ($line =~ m/^delete:\s*(.*\S)\s*$/) {
my $value = $1;
-   foreach my $opt (split(/,/, $value)) {
-   $conf-{del}-{$opt} = 1;
+   if ($section eq 'pending') {
+   $conf-{delete} = $value; # we parse this later
+   } else {
+   warn vm $vmid - propertry 'delete' is only allowed in 
[PENDING]\n;
}
} elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
my $key = $1;
@@ -1893,12 +1895,18 @@ sub write_vm_config {
 my $used_volids = {};
 
 my $cleanup_config = sub {
-   my ($cref, $snapname) = @_;
+   my ($cref, $pending, $snapname) = @_;
 
foreach my $key (keys %$cref) {
next if $key eq 'digest' || $key eq 'description' || $key eq 
'snapshots' ||
-   $key eq 'snapstate';
+   $key eq 'snapstate' || $key eq 'pending';
my $value = $cref-{$key};
+   if ($key eq 'delete') {
+   die propertry 'delete' is only allowed in [PENDING]\n
+   if !$pending;
+   # fixme: check syntax?
+   next;
+   }
eval { $value = check_type($key, $value); };
die unable to parse value of '$key' - $@ if $@;
 
@@ -1912,8 +1920,12 @@ sub write_vm_config {
 };
 
 $cleanup_config($conf);
+
+$cleanup_config($conf-{pending}, 1);
+
 foreach my $snapname (keys %{$conf-{snapshots}}) {
-   $cleanup_config($conf-{snapshots}-{$snapname}, $snapname);
+   die internal error if $snapname eq 'pending';
+   $cleanup_config($conf-{snapshots}-{$snapname}, undef, $snapname);
 }
 
 # remove 'unusedX' settings if we re-add a volume
@@ -1936,13 +1948,19 @@ sub write_vm_config {
}
 
foreach my $key (sort keys %$conf) {
-   next if $key eq 'digest' || $key eq 'description' || $key eq 
'snapshots';
+   next if $key eq 'digest' || $key eq 'description' || $key eq 
'pending' || $key eq 'snapshots';
$raw .= $key: $conf-{$key}\n;
}
return $raw;
 };
 
 my $raw = $generate_raw_config($conf);
+
+if (scalar(keys %{$conf-{pending}})){
+   $raw .= \n[PENDING]\n;
+   $raw .= $generate_raw_config($conf-{pending});
+}
+
 foreach my $snapname (sort keys %{$conf-{snapshots}}) {
$raw .= \n[$snapname]\n;
$raw .= $generate_raw_config($conf-{snapshots}-{$snapname});
-- 
1.7.10.4

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


[pve-devel] [PATCH v6 11/22] vmconfig_cleanup_pending: new method to clenup setting in [PENDING]

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm  |8 +---
 PVE/QemuServer.pm |   32 
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index a8841c2..8c7c076 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -1006,14 +1006,8 @@ my $update_vm_api  = sub {
}
 
# remove pending changes when nothing changed
-   my $changes;
$conf = PVE::QemuServer::load_config($vmid); # update/reload
-   foreach my $opt (keys %{$conf-{pending}}) { # add/change
-   if (defined($conf-{$opt})  ($conf-{pending}-{$opt} eq  
$conf-{$opt})) {
-   $changes = 1;
-   delete $conf-{pending}-{$opt};
-   }
-   }
+   my $changes = PVE::QemuServer::vmconfig_cleanup_pending($conf);
PVE::QemuServer::update_config_nolock($vmid, $conf, 1) if $changes;
 
return if !scalar(keys %{$conf-{pending}});
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 7219353..2644117 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1442,6 +1442,38 @@ sub vmconfig_register_unused_drive {
 }
 }
 
+sub vmconfig_cleanup_pending {
+my ($conf) = @_;
+
+# remove pending changes when nothing changed
+my $changes;
+foreach my $opt (keys %{$conf-{pending}}) {
+   if (defined($conf-{$opt})  ($conf-{pending}-{$opt} eq  
$conf-{$opt})) {
+   $changes = 1;
+   delete $conf-{pending}-{$opt};
+   }
+}
+
+# remove delete if option is not set
+my $pending_delete_hash = {};
+foreach my $opt (PVE::Tools::split_list($conf-{pending}-{delete})) {
+   if (defined($conf-{$opt})) {
+   $pending_delete_hash-{$opt} = 1;
+   } else {
+   $changes = 1;
+   }
+}
+
+my @keylist = keys %$pending_delete_hash;
+if (scalar(@keylist)) {
+   $conf-{pending}-{delete} = join(',', @keylist);
+} else {
+   delete $conf-{pending}-{delete};
+}
+
+return $changes;
+}
+
 my $valid_smbios1_options = {
 manufacturer = '\S+',
 product = '\S+',
-- 
1.7.10.4

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


[pve-devel] [PATCH v6 02/22] parse_vm_config: correctly handle $descr

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 96eb6ec..e020740 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1782,7 +1782,7 @@ sub parse_vm_config {
 my $res = {
digest = Digest::SHA::sha1_hex($raw),
snapshots = {},
-   pending = {}
+   pending = {},
 };
 
 $filename =~ m|/qemu-server/(\d+)\.conf$|
@@ -1798,10 +1798,12 @@ sub parse_vm_config {
next if $line =~ m/^\s*$/;
 
if ($line =~ m/^\[PENDING\]\s*$/i) {
+   $conf-{description} = $descr if $descr;
+   $descr = '';
$conf = $res-{pending} = {};
next;
 
-   }elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
+   } elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
my $snapname = $1;
$conf-{description} = $descr if $descr;
$descr = '';
-- 
1.7.10.4

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


[pve-devel] [PATCH v6 01/22] parse_vm_config : parse pending changes

2014-11-25 Thread Dietmar Maurer
From: Alexandre Derumier aderum...@odiso.com

example:

[PENDING]
virtio1:...
delete:net0,net1

$conf-{pending}-{virtio1}
$conf-{pending}-{del}-{net0}
$conf-{pending}-{del}-{net1}

Signed-off-by: Alexandre Derumier aderum...@odiso.com
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index b5aafc3..96eb6ec 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1782,6 +1782,7 @@ sub parse_vm_config {
 my $res = {
digest = Digest::SHA::sha1_hex($raw),
snapshots = {},
+   pending = {}
 };
 
 $filename =~ m|/qemu-server/(\d+)\.conf$|
@@ -1796,7 +1797,11 @@ sub parse_vm_config {
 foreach my $line (@lines) {
next if $line =~ m/^\s*$/;
 
-   if ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
+   if ($line =~ m/^\[PENDING\]\s*$/i) {
+   $conf = $res-{pending} = {};
+   next;
+
+   }elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
my $snapname = $1;
$conf-{description} = $descr if $descr;
$descr = '';
@@ -1817,6 +1822,12 @@ sub parse_vm_config {
my $key = $1;
my $value = $2;
$conf-{$key} = $value;
+   } elsif ($line =~ m/^(delete):\s*(.*\S)\s*$/) {
+   my $key = $1;
+   my $value = $2;
+   foreach my $opt (split(/,/, $value)) {
+   $conf-{del}-{$opt} = 1;
+   }
} elsif ($line =~ m/^([a-z][a-z_]*\d*):\s*(\S+)\s*$/) {
my $key = $1;
my $value = $2;
-- 
1.7.10.4

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


[pve-devel] [PATCH v6 06/22] implement vmconfig_apply_pending for stopped VM

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm |  191 ++
 1 file changed, 119 insertions(+), 72 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 222c44f..41d75d0 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -37,6 +37,73 @@ 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 ($force || $key =~ m/^unused/) {
+   my $sid = PVE::Storage::parse_volume_id($volid);
+   return $sid;
+   }
+   }
+}
+
+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) = @_;
@@ -639,36 +706,6 @@ __PACKAGE__-register_method({
return $conf;
 }});
 
-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 ($force || $key =~ m/^unused/) {
-   my $sid = PVE::Storage::parse_volume_id($volid);
-   return $sid;
-   }
-   }
-}
-
-return undef;
-};
-
 my $delete_drive = sub {
 my ($conf, $storecfg, $vmid, $key, $drive, $force) = @_;
 
@@ -868,6 +905,48 @@ 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});
+   

[pve-devel] [PATCH v6 03/22] parse_vm_config: only allow 'delete' inside [PENDING]

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index e020740..9b03e6a 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1792,22 +1792,24 @@ sub parse_vm_config {
 
 my $conf = $res;
 my $descr = '';
+my $section = '';
 
 my @lines = split(/\n/, $raw);
 foreach my $line (@lines) {
next if $line =~ m/^\s*$/;
 
if ($line =~ m/^\[PENDING\]\s*$/i) {
+   $section = 'pending';
$conf-{description} = $descr if $descr;
$descr = '';
-   $conf = $res-{pending} = {};
+   $conf = $res-{$section} = {};
next;
 
} elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
-   my $snapname = $1;
+   $section = $1;
$conf-{description} = $descr if $descr;
$descr = '';
-   $conf = $res-{snapshots}-{$snapname} = {};
+   $conf = $res-{snapshots}-{$section} = {};
next;
}
 
@@ -1824,9 +1826,8 @@ sub parse_vm_config {
my $key = $1;
my $value = $2;
$conf-{$key} = $value;
-   } elsif ($line =~ m/^(delete):\s*(.*\S)\s*$/) {
-   my $key = $1;
-   my $value = $2;
+   } elsif (($section eq 'pending')  ($line =~ 
m/^delete:\s*(.*\S)\s*$/)) {
+   my $value = $1;
foreach my $opt (split(/,/, $value)) {
$conf-{del}-{$opt} = 1;
}
-- 
1.7.10.4

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


[pve-devel] [PATCH v6 00/22] qemu-server: implement pending changes

2014-11-25 Thread Dietmar Maurer
Based on Alexandres patches (sent to pve-devel list):
  qemu-server : implement pending changes v2
  pending changes hotplug v2

Changes in v6:
- implement disk hotplug
- vmconfig_update_net: do not call vm_deviceplug() if hotplug == 0
- remove unused code

Changes in v5:
- implement network hotplug
- cleanup error handling in vm_deviceunplug and vm_deviceplug
- bug fixes

Changes in v4:

- implement API/CLI to get pending changes
- improve hotplug error handling (see cpu hotplug as example)
- new method to cleanup setting in [PENDING]
- code cleanups

Changes in v3:
- I tried to simplify things by always writing changes into pending
  section first.
- do not parse 'delete' option parse_vm_config

TODO: test

Alexandre Derumier (1):
  parse_vm_config : parse pending changes

Dietmar Maurer (21):
  parse_vm_config: correctly handle $descr
  parse_vm_config: only allow 'delete' inside [PENDING]
  write_vm_config : write pending change
  update_vm_api: always write into pending section
  implement vmconfig_apply_pending for stopped VM
  vm_start: apply pending changes
  fix balloon consistency check (consider pending changes)
  implement trivial hotplug
  vmconfig_hotplug_pending: implement tablet hotplug
  vmconfig_cleanup_pending: new method to clenup setting in [PENDING]
  code cleanup, delete trailing white space
  vmconfig_hotplug_pending: improve hotplug error handling
  implement API/CLI to get pending changes
  rename qemu_bridgeadd to qemu_add_pci_bridge
  vmconfig_hotplug_pending: correctly skip values
  vmconfig_hotplug_pending : add update_net
  vm_deviceunplug: raise expection if something fail
  vm_deviceplug: always raise exception on error
  vmconfig_hotplug_pending : add update_disk
  vmconfig_update_net: do not call vm_deviceplug() if hotplug == 0
  remove unused code

 PVE/API2/Qemu.pm  |  424 ++---
 PVE/QemuServer.pm |  674 -
 pve-bridge|8 +-
 qm|   27 +++
 4 files changed, 769 insertions(+), 364 deletions(-)

-- 
1.7.10.4

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


[pve-devel] [PATCH v6 12/22] code cleanup, delete trailing white space

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 2644117..dd06f2f 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3480,7 +3480,7 @@ sub set_migration_caps {
 sub vmconfig_hotplug_pending {
 my ($vmid, $conf, $storecfg) = @_;
 
-my $defaults = PVE::QemuServer::load_defaults();
+my $defaults = load_defaults();
 
 # commit values which do not have any impact on running VM first
 
@@ -3521,9 +3521,9 @@ sub vmconfig_hotplug_pending {
 foreach my $opt (@delete) {
if ($opt eq 'tablet') {
if ($defaults-{tablet}) {
-   PVE::QemuServer::vm_deviceplug($storecfg, $conf, $vmid, $opt);
+   vm_deviceplug($storecfg, $conf, $vmid, $opt);
} else {
-   PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
+   vm_deviceunplug($vmid, $conf, $opt);
}
} else {
# skip non-hot-pluggable options
@@ -3543,9 +3543,9 @@ sub vmconfig_hotplug_pending {
 
if ($opt eq 'tablet') {
if ($value == 1) {
-   PVE::QemuServer::vm_deviceplug($storecfg, $conf, $vmid, $opt);
+   vm_deviceplug($storecfg, $conf, $vmid, $opt);
} elsif ($value == 0) {
-   PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
+   vm_deviceunplug($vmid, $conf, $opt);
}
} else {
# skip non-hot-pluggable options
@@ -3691,15 +3691,15 @@ sub vm_start {
if ($migratedfrom) {
 
eval {
-   PVE::QemuServer::set_migration_caps($vmid);
+   set_migration_caps($vmid);
};
warn $@ if $@;
 
if ($spice_port) {
print spice listens on port $spice_port\n;
if ($spice_ticket) {
-   PVE::QemuServer::vm_mon_cmd_nocheck($vmid, set_password, 
protocol = 'spice', password = $spice_ticket);
-   PVE::QemuServer::vm_mon_cmd_nocheck($vmid, 
expire_password, protocol = 'spice', time = +30);
+   vm_mon_cmd_nocheck($vmid, set_password, protocol = 
'spice', password = $spice_ticket);
+   vm_mon_cmd_nocheck($vmid, expire_password, protocol = 
'spice', time = +30);
}
}
 
@@ -4763,7 +4763,7 @@ sub restore_tar_archive {
 my $storecfg = cfs_read_file('storage.cfg');
 
 # destroy existing data - keep empty config
-my $vmcfgfn = PVE::QemuServer::config_file($vmid);
+my $vmcfgfn = config_file($vmid);
 destroy_vm($storecfg, $vmid, 1) if -f $vmcfgfn;
 
 my $tocmd = /usr/lib/qemu-server/qmextract;
@@ -5567,7 +5567,7 @@ sub get_current_qemu_machine {
 my ($vmid) = @_;
 
 my $cmd = { execute = 'query-machines', arguments = {} };
-my $res = PVE::QemuServer::vm_qmp_command($vmid, $cmd);
+my $res = vm_qmp_command($vmid, $cmd);
 
 my ($current, $default);
 foreach my $e (@$res) {
-- 
1.7.10.4

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


[pve-devel] [PATCH v6 05/22] update_vm_api: always write into pending section

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm |   99 --
 1 file changed, 97 insertions(+), 2 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 0787074..222c44f 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -951,6 +951,44 @@ my $update_vm_api  = sub {
 
 $check_storage_access($rpcenv, $authuser, $storecfg, $vmid, $param);
 
+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 ($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 $updatefn =  sub {
 
my $conf = PVE::QemuServer::load_config($vmid);
@@ -960,6 +998,7 @@ my $update_vm_api  = sub {
 
PVE::QemuServer::check_lock($conf) if !$skiplock;
 
+   # fixme: wrong place? howto handle pending changes? @delete ?
if ($param-{memory} || defined($param-{balloon})) {
my $maxmem = $param-{memory} || $conf-{memory} || 
$defaults-{memory};
my $balloon = defined($param-{balloon}) ?  $param-{balloon} : 
$conf-{balloon};
@@ -974,11 +1013,67 @@ my $update_vm_api  = sub {
 
print update VM $vmid:  . join (' ', @paramarr) . \n;
 
-   foreach my $opt (@delete) { # delete
+   # write updates to pending section
+
+   foreach my $opt (@delete) {
$conf = PVE::QemuServer::load_config($vmid); # update/reload
-   $vmconfig_delete_option($rpcenv, $authuser, $conf, $storecfg, 
$vmid, $opt, $force);
+   if ($opt =~ m/^unused/) {
+   $rpcenv-check_vm_perm($authuser, $vmid, undef, 
['VM.Config.Disk']);
+   my $drive = PVE::QemuServer::parse_drive($opt, 
$conf-{$opt});
+   if (my $sid = $test_deallocate_drive($storecfg, $vmid, 
$opt, $drive, $force)) {
+   $rpcenv-check($authuser, /storage/$sid, 
['Datastore.AllocateSpace']);
+   $delete_drive($conf, $storecfg, $vmid, $opt, $drive);
+   PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+   }
+   } elsif (PVE::QemuServer::valid_drivename($opt)) {
+   $rpcenv-check_vm_perm($authuser, $vmid, undef, 
['VM.Config.Disk']);
+   $register_unused_drive($conf, 
PVE::QemuServer::parse_drive($opt, $conf-{pending}-{$opt}))
+   if defined($conf-{pending}-{$opt});
+   $pending_delete_option($conf, $opt);
+   PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+   } else {
+   $pending_delete_option($conf, $opt);
+   PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+   }
}
 
+   foreach my $opt (keys %$param) { # add/change
+   $conf = PVE::QemuServer::load_config($vmid); # update/reload
+   next if defined($conf-{pending}-{$opt})  ($param-{$opt} eq 
$conf-{pending}-{$opt}); # skip if nothing changed
+
+   if (PVE::QemuServer::valid_drivename($opt)) {
+   my $drive = PVE::QemuServer::parse_drive($opt, 
$param-{$opt});
+   if (PVE::QemuServer::drive_is_cdrom($drive)) { # CDROM
+   $rpcenv-check_vm_perm($authuser, $vmid, undef, 
['VM.Config.CDROM']);
+   } else {
+   $rpcenv-check_vm_perm($authuser, $vmid, undef, 
['VM.Config.Disk']);
+   }
+   $register_unused_drive($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};
+   }
+   

[pve-devel] [PATCH v6 21/22] vmconfig_update_net: do not call vm_deviceplug() if hotplug == 0

2014-11-25 Thread Dietmar Maurer

Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 4a44ac8..24c77ef 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3699,10 +3699,16 @@ sub vmconfig_update_net {
PVE::Network::tap_unplug($iface);
PVE::Network::tap_plug($iface, $newnet-{bridge}, 
$newnet-{tag}, $newnet-{firewall});
}
+
+   return 1;
}
 }
 
-vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
+if ($conf-{hotplug}) {
+   vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet);
+} else {
+   die skip\n;
+}
 }
 
 sub vmconfig_update_disk {
-- 
1.7.10.4

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


[pve-devel] [PATCH v6 20/22] vmconfig_hotplug_pending : add update_disk

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Alexandre Derumier aderum...@odiso.com
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm  |   94 ++---
 PVE/QemuServer.pm |   92 +++
 2 files changed, 94 insertions(+), 92 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index ea045c9..064d7ad 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -807,96 +807,6 @@ my $vmconfig_delete_option = sub {
 PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
 };
 
-my $safe_num_ne = sub {
-my ($a, $b) = @_;
-
-return 0 if !defined($a)  !defined($b);
-return 1 if !defined($a);
-return 1 if !defined($b);
-
-return $a != $b;
-};
-
-my $vmconfig_update_disk = sub {
-my ($rpcenv, $authuser, $conf, $storecfg, $vmid, $opt, $value, $force) = 
@_;
-
-my $drive = PVE::QemuServer::parse_drive($opt, $value);
-
-if (PVE::QemuServer::drive_is_cdrom($drive)) { #cdrom
-   $rpcenv-check_vm_perm($authuser, $vmid, undef, ['VM.Config.CDROM']);
-} else {
-   $rpcenv-check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
-}
-
-if ($conf-{$opt}) {
-
-   if (my $old_drive = PVE::QemuServer::parse_drive($opt, $conf-{$opt}))  
{
-
-   my $media = $drive-{media} || 'disk';
-   my $oldmedia = $old_drive-{media} || 'disk';
-   die unable to change media type\n if $media ne $oldmedia;
-
-   if (!PVE::QemuServer::drive_is_cdrom($old_drive) 
-   ($drive-{file} ne $old_drive-{file})) {  # delete old disks
-
-   $vmconfig_delete_option($rpcenv, $authuser, $conf, $storecfg, 
$vmid, $opt, $force);
-   $conf = PVE::QemuServer::load_config($vmid); # update/reload
-   }
-
-if($safe_num_ne($drive-{mbps}, $old_drive-{mbps}) ||
-   $safe_num_ne($drive-{mbps_rd}, $old_drive-{mbps_rd}) ||
-   $safe_num_ne($drive-{mbps_wr}, $old_drive-{mbps_wr}) ||
-   $safe_num_ne($drive-{iops}, $old_drive-{iops}) ||
-   $safe_num_ne($drive-{iops_rd}, $old_drive-{iops_rd}) ||
-   $safe_num_ne($drive-{iops_wr}, $old_drive-{iops_wr}) ||
-   $safe_num_ne($drive-{mbps_max}, $old_drive-{mbps_max}) ||
-   $safe_num_ne($drive-{mbps_rd_max}, $old_drive-{mbps_rd_max}) 
||
-   $safe_num_ne($drive-{mbps_wr_max}, $old_drive-{mbps_wr_max}) 
||
-   $safe_num_ne($drive-{iops_max}, $old_drive-{iops_max}) ||
-   $safe_num_ne($drive-{iops_rd_max}, $old_drive-{iops_rd_max}) 
||
-   $safe_num_ne($drive-{iops_wr_max}, 
$old_drive-{iops_wr_max})) {
-   PVE::QemuServer::qemu_block_set_io_throttle($vmid,drive-$opt,
-  ($drive-{mbps} || 
0)*1024*1024,
-  ($drive-{mbps_rd} 
|| 0)*1024*1024,
-  ($drive-{mbps_wr} 
|| 0)*1024*1024,
-  $drive-{iops} || 0,
-  $drive-{iops_rd} || 
0,
-  $drive-{iops_wr} || 
0,
-  ($drive-{mbps_max} 
|| 0)*1024*1024,
-  
($drive-{mbps_rd_max} || 0)*1024*1024,
-  
($drive-{mbps_wr_max} || 0)*1024*1024,
-  $drive-{iops_max} 
|| 0,
-  
$drive-{iops_rd_max} || 0,
-  
$drive-{iops_wr_max} || 0)
-  if !PVE::QemuServer::drive_is_cdrom($drive);
-}
-   }
-}
-
-$create_disks($rpcenv, $authuser, $conf, $storecfg, $vmid, undef, {$opt 
= $value});
-PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
-
-$conf = PVE::QemuServer::load_config($vmid); # update/reload
-$drive = PVE::QemuServer::parse_drive($opt, $conf-{$opt});
-
-if (PVE::QemuServer::drive_is_cdrom($drive)) { # cdrom
-
-   if (PVE::QemuServer::check_running($vmid)) {
-   if ($drive-{file} eq 'none') {
-   PVE::QemuServer::vm_mon_cmd($vmid, eject,force = 
JSON::true,device = drive-$opt);
-   } else {
-   my $path = PVE::QemuServer::get_iso_path($storecfg, $vmid, 
$drive-{file});
-   PVE::QemuServer::vm_mon_cmd($vmid, eject,force = 
JSON::true,device = drive-$opt); #force eject if locked
-   PVE::QemuServer::vm_mon_cmd($vmid, change,device = 
drive-$opt,target = $path) if $path;
-   }
-   }
-
-} else { # hotplug new disks
-
-   die error hotplug $opt if !PVE::QemuServer::vm_deviceplug($storecfg, 
$conf, $vmid, $opt, $drive);
-

[pve-devel] [PATCH v6 22/22] remove unused code

2014-11-25 Thread Dietmar Maurer

Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm |  138 --
 1 file changed, 29 insertions(+), 109 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 064d7ad..3d1a7e7 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -188,6 +188,34 @@ my $create_disks = sub {
 return $vollist;
 };
 
+my $delete_drive = sub {
+my ($conf, $storecfg, $vmid, $key, $drive, $force) = @_;
+
+if (!PVE::QemuServer::drive_is_cdrom($drive)) {
+   my $volid = $drive-{file};
+
+   if (PVE::QemuServer::vm_is_volid_owner($storecfg, $vmid, $volid)) {
+   if ($force || $key =~ m/^unused/) {
+   eval {
+   # check if the disk is really unused
+   my $used_paths = PVE::QemuServer::get_used_paths($vmid, 
$storecfg, $conf, 1, $key);
+   my $path = PVE::Storage::path($storecfg, $volid);
+
+   die unable to delete '$volid' - volume is still in use 
(snapshot?)\n
+   if $used_paths-{$path};
+
+   PVE::Storage::vdisk_free($storecfg, $volid);
+   };
+   die $@ if $@;
+   } else {
+   PVE::QemuServer::add_unused_volume($conf, $volid, $vmid);
+   }
+   }
+}
+
+delete $conf-{$key};
+};
+
 my $check_vm_modify_config_perm = sub {
 my ($rpcenv, $authuser, $vmid, $pool, $key_list) = @_;
 
@@ -738,75 +766,6 @@ __PACKAGE__-register_method({
return $res;
 }});
 
-my $delete_drive = sub {
-my ($conf, $storecfg, $vmid, $key, $drive, $force) = @_;
-
-if (!PVE::QemuServer::drive_is_cdrom($drive)) {
-   my $volid = $drive-{file};
-
-   if (PVE::QemuServer::vm_is_volid_owner($storecfg, $vmid, $volid)) {
-   if ($force || $key =~ m/^unused/) {
-   eval {
-   # check if the disk is really unused
-   my $used_paths = PVE::QemuServer::get_used_paths($vmid, 
$storecfg, $conf, 1, $key);
-   my $path = PVE::Storage::path($storecfg, $volid);
-
-   die unable to delete '$volid' - volume is still in use 
(snapshot?)\n
-   if $used_paths-{$path};
-
-   PVE::Storage::vdisk_free($storecfg, $volid);
-   };
-   die $@ if $@;
-   } else {
-   PVE::QemuServer::add_unused_volume($conf, $volid, $vmid);
-   }
-   }
-}
-
-delete $conf-{$key};
-};
-
-my $vmconfig_delete_option = sub {
-my ($rpcenv, $authuser, $conf, $storecfg, $vmid, $opt, $force) = @_;
-
-return if !defined($conf-{$opt});
-
-my $isDisk = PVE::QemuServer::valid_drivename($opt)|| ($opt =~ m/^unused/);
-
-if ($isDisk) {
-   $rpcenv-check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
-
-   my $drive = PVE::QemuServer::parse_drive($opt, $conf-{$opt});
-   if (my $sid = $test_deallocate_drive($storecfg, $vmid, $opt, $drive, 
$force)) {
-   $rpcenv-check($authuser, /storage/$sid, 
['Datastore.AllocateSpace']);
-   }
-}
-
-my $unplugwarning = ;
-if ($conf-{ostype}  $conf-{ostype} eq 'l26') {
-   $unplugwarning = brverify that you have acpiphp  pci_hotplug 
modules loaded in your guest VM;
-} elsif ($conf-{ostype}  $conf-{ostype} eq 'l24') {
-   $unplugwarning = brkernel 2.4 don't support hotplug, please disable 
hotplug in options;
-} elsif (!$conf-{ostype} || ($conf-{ostype}  $conf-{ostype} eq 
'other')) {
-   $unplugwarning = brverify that your guest support acpi hotplug;
-}
-
-if ($opt eq 'tablet') {
-   PVE::QemuServer::vm_deviceplug(undef, $conf, $vmid, $opt);
-} else {
-die error hot-unplug $opt $unplugwarning if 
!PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
-}
-
-if ($isDisk) {
-   my $drive = PVE::QemuServer::parse_drive($opt, $conf-{$opt});
-   $delete_drive($conf, $storecfg, $vmid, $opt, $drive, $force);
-} else {
-   delete $conf-{$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
@@ -983,47 +942,8 @@ my $update_vm_api  = sub {
} else {
PVE::QemuServer::vmconfig_apply_pending($vmid, $conf, 
$storecfg, $running);
}
-   return; # TODO: remove old code below
-
-   foreach my $opt (keys %$param) { # add/change
-
-   $conf = PVE::QemuServer::load_config($vmid); # update/reload
-
-   next if $conf-{$opt}  ($param-{$opt} eq $conf-{$opt}); # 
skip if nothing changed
 
-   if (PVE::QemuServer::valid_drivename($opt)) {
-
-   #$vmconfig_update_disk($rpcenv, $authuser, $conf, 
$storecfg, $vmid,
-   #  $opt, $param-{$opt}, $force);
-
-   } elsif ($opt =~ m/^net(\d+)$/) { #nics
-
- 

[pve-devel] [PATCH v6 19/22] vm_deviceplug: always raise exception on error

2014-11-25 Thread Dietmar Maurer

Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   92 -
 1 file changed, 49 insertions(+), 43 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 14989f8..243d069 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3032,73 +3032,80 @@ sub vm_devices_list {
 return $devices;
 }
 
-# fixme: this should raise exceptions on error!
 sub vm_deviceplug {
 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
 
-return 1 if !check_running($vmid);
+die internal error if !$conf-{hotplug};
 
 my $q35 = machine_type_is_q35($conf);
 
-return 1 if !$conf-{hotplug};
-
 my $devices_list = vm_devices_list($vmid);
 return 1 if defined($devices_list-{$deviceid});
 
+qemu_add_pci_bridge($storecfg, $conf, $vmid, $deviceid); # add PCI bridge 
if we need it for the device
+
 if ($deviceid eq 'tablet') {
+
qemu_deviceadd($vmid, print_tabletdevice_full($conf));
-   return 1;
-}
 
-qemu_add_pci_bridge($storecfg, $conf, $vmid, $deviceid); # add PCI bridge 
if we need it for the device
+} elsif ($deviceid =~ m/^(virtio)(\d+)$/) {
 
-if ($deviceid =~ m/^(virtio)(\d+)$/) {
-return undef if !qemu_driveadd($storecfg, $vmid, $device);
+qemu_driveadd($storecfg, $vmid, $device);
 my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, 
$device);
+
 qemu_deviceadd($vmid, $devicefull);
-if(!qemu_deviceaddverify($vmid, $deviceid)) {
+   eval { qemu_deviceaddverify($vmid, $deviceid); };
+   if (my $err = $@) {
eval { qemu_drivedel($vmid, $deviceid); };
warn $@ if $@;
-   return undef;
+   die $err;
 }
-}
 
-if ($deviceid =~ m/^(scsihw)(\d+)$/) {
+} elsif ($deviceid =~ m/^(scsihw)(\d+)$/) {
+
 my $scsihw = defined($conf-{scsihw}) ? $conf-{scsihw} : lsi;
 my $pciaddr = print_pci_addr($deviceid);
 my $devicefull = $scsihw,id=$deviceid$pciaddr;
+
 qemu_deviceadd($vmid, $devicefull);
-return undef if(!qemu_deviceaddverify($vmid, $deviceid));
-}
+qemu_deviceaddverify($vmid, $deviceid);
 
-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);
-if(!qemu_deviceadd($vmid, $devicefull)) { # fixme: use 
qemu_deviceaddverify?
+} elsif ($deviceid =~ m/^(scsi)(\d+)$/) {
+
+qemu_findorcreatescsihw($storecfg,$conf, $vmid, $device);
+qemu_driveadd($storecfg, $vmid, $device);
+
+   my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, 
$device);
+   eval { qemu_deviceadd($vmid, $devicefull); };
+   if (my $err = $@) {
eval { qemu_drivedel($vmid, $deviceid); };
warn $@ if $@;
-   return undef;
+   die $err;
 }
-}
 
-if ($deviceid =~ m/^(net)(\d+)$/) {
+} elsif ($deviceid =~ m/^(net)(\d+)$/) {
+
 return undef if !qemu_netdevadd($vmid, $conf, $device, $deviceid);
 my $netdevicefull = print_netdevice_full($vmid, $conf, $device, 
$deviceid);
 qemu_deviceadd($vmid, $netdevicefull);
-if(!qemu_deviceaddverify($vmid, $deviceid)) {
-   qemu_netdevdel($vmid, $deviceid);
-   return undef;
+eval { qemu_deviceaddverify($vmid, $deviceid); };
+   if (my $err = $@) {
+   eval { qemu_netdevdel($vmid, $deviceid); };
+   warn $@ if $@;
+   die $err;
 }
-}
 
+} elsif (!$q35  $deviceid =~ m/^(pci\.)(\d+)$/) {
 
-if (!$q35  $deviceid =~ m/^(pci\.)(\d+)$/) {
my $bridgeid = $2;
my $pciaddr = print_pci_addr($deviceid);
my $devicefull = 
pci-bridge,id=pci.$bridgeid,chassis_nr=$bridgeid$pciaddr;
+   
qemu_deviceadd($vmid, $devicefull);
-   return undef if !qemu_deviceaddverify($vmid, $deviceid);
+   qemu_deviceaddverify($vmid, $deviceid);
+
+} else {
+   die can't hotplug device '$deviceid'\n;   
 }
 
 return 1;
@@ -3154,26 +3161,24 @@ sub qemu_deviceadd {
 my %options =  split(/[=,]/, $devicefull);
 
 vm_mon_cmd($vmid, device_add , %options);
-return 1;
 }
 
 sub qemu_devicedel {
-my($vmid, $deviceid) = @_;
+my ($vmid, $deviceid) = @_;
 
 my $ret = vm_mon_cmd($vmid, device_del, id = $deviceid);
 }
 
 sub qemu_driveadd {
-my($storecfg, $vmid, $device) = @_;
+my ($storecfg, $vmid, $device) = @_;
 
 my $drive = print_drive_full($storecfg, $vmid, $device);
 my $ret = vm_human_monitor_command($vmid, drive_add auto $drive);
+
 # If the command succeeds qemu prints: OK
-if ($ret !~ m/OK/s) {
-syslog(err, adding drive failed: $ret);
-return undef;
-}
-return 1;
+return 1 if $ret =~ 

[pve-devel] [PATCH v6 13/22] vmconfig_hotplug_pending: improve hotplug error handling

2014-11-25 Thread Dietmar Maurer
Simplify code, and allow to partially apply pending changes using
a new $selection parameter.

Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm  |   12 -
 PVE/QemuServer.pm |  149 ++---
 2 files changed, 95 insertions(+), 66 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 8c7c076..b116c24 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -961,7 +961,10 @@ my $update_vm_api  = sub {
 
# write updates to pending section
 
+   my $modified = {}; # record what $option we modify
+
foreach my $opt (@delete) {
+   $modified-{$opt} = 1;
$conf = PVE::QemuServer::load_config($vmid); # update/reload
if ($opt =~ m/^unused/) {
$rpcenv-check_vm_perm($authuser, $vmid, undef, 
['VM.Config.Disk']);
@@ -984,6 +987,7 @@ my $update_vm_api  = sub {
}
 
foreach my $opt (keys %$param) { # add/change
+   $modified-{$opt} = 1;
$conf = PVE::QemuServer::load_config($vmid); # update/reload
next if defined($conf-{pending}-{$opt})  ($param-{$opt} eq 
$conf-{pending}-{$opt}); # skip if nothing changed
 
@@ -1017,8 +1021,14 @@ my $update_vm_api  = sub {
# apply pending changes
 
$conf = PVE::QemuServer::load_config($vmid); # update/reload
-   PVE::QemuServer::vmconfig_apply_pending($vmid, $conf, $storecfg, 
$running);
 
+   if ($running) {
+   my $errors = {};
+   PVE::QemuServer::vmconfig_hotplug_pending($vmid, $conf, 
$storecfg, $modified, $errors);
+   raise_param_exc($errors) if scalar(keys %$errors);
+   } else {
+   PVE::QemuServer::vmconfig_apply_pending($vmid, $conf, 
$storecfg, $running);
+   }
return; # TODO: remove old code below
 
foreach my $opt (keys %$param) { # add/change
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index dd06f2f..391376e 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3266,22 +3266,25 @@ sub qemu_netdevdel {
 sub qemu_cpu_hotplug {
 my ($vmid, $conf, $cores) = @_;
 
-die new cores config is not defined if !$cores;
-die you can't add more cores than maxcpus
-   if $conf-{maxcpus}  ($cores  $conf-{maxcpus});
-return if !check_running($vmid);
+my $sockets = $conf-{sockets} || 1;
+die cpu hotplug only works with one socket\n
+   if $sockets  1;
 
-my $currentcores = $conf-{cores} if $conf-{cores};
-die current cores is not defined if !$currentcores;
-die maxcpus is not defined if !$conf-{maxcpus};
-raise_param_exc({ 'cores' = online cpu unplug is not yet possible })
-   if($cores  $currentcores);
+die maxcpus is not defined\n
+   if !$conf-{maxcpus};
+
+die you can't add more cores than maxcpus\n
+   if $cores  $conf-{maxcpus};
+
+my $currentcores = $conf-{cores} || 1;
+die online cpu unplug is not yet possible\n
+   if $cores  $currentcores;
 
 my $currentrunningcores = vm_mon_cmd($vmid, query-cpus);
-raise_param_exc({ 'cores' = cores number if running vm is different than 
configuration })
-   if scalar (@{$currentrunningcores}) != $currentcores;
+die cores number if running vm is different than configuration\n
+   if scalar(@{$currentrunningcores}) != $currentcores;
 
-for(my $i = $currentcores; $i  $cores; $i++) {
+for (my $i = $currentcores; $i  $cores; $i++) {
vm_mon_cmd($vmid, cpu-add, id = int($i));
 }
 }
@@ -3477,12 +3480,23 @@ sub set_migration_caps {
 vm_mon_cmd_nocheck($vmid, migrate-set-capabilities, capabilities = 
$cap_ref);
 }
 
+# hotplug changes in [PENDING]
+# $selection hash can be used to only apply specified options, for
+# example: { cores = 1 } (only apply changed 'cores')
+# $errors ref is used to return error messages
 sub vmconfig_hotplug_pending {
-my ($vmid, $conf, $storecfg) = @_;
+my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
 
 my $defaults = load_defaults();
 
 # commit values which do not have any impact on running VM first
+# Note: those option cannot raise errors, we we do not care about
+# $selection and always apply them.
+
+my $add_error = sub {
+   my ($opt, $msg) = @_;
+   $errors-{$opt} = hotplug problem - $msg;
+};
 
 my $changes = 0;
 foreach my $opt (keys %{$conf-{pending}}) { # add/change
@@ -3498,73 +3512,78 @@ sub vmconfig_hotplug_pending {
$conf = load_config($vmid); # update/reload
 }
 
-$changes = 0;
-
-# allow manual ballooning if shares is set to zero
-
-if (defined($conf-{pending}-{balloon})  defined($conf-{shares})  
($conf-{shares} == 0)) {
-   my $balloon = $conf-{pending}-{balloon} || $conf-{memory} || 
$defaults-{memory};
-   vm_mon_cmd($vmid, balloon, value = $balloon*1024*1024);
-   $conf-{balloon} = $conf-{pending}-{balloon};
-   

[pve-devel] [PATCH v6 09/22] implement trivial hotplug

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   47 ++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 8524180..2a702d2 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3438,11 +3438,56 @@ sub set_migration_caps {
 vm_mon_cmd_nocheck($vmid, migrate-set-capabilities, capabilities = 
$cap_ref);
 }
 
+sub vmconfig_hotplug_pending {
+my ($vmid, $conf, $storecfg) = @_;
+
+my $defaults = PVE::QemuServer::load_defaults();
+
+# commit values which do not have any impact on running VM first
+
+my $changes = 0;
+foreach my $opt (keys %{$conf-{pending}}) { # add/change
+   if ($opt eq 'name' || $opt eq 'hotplug' || $opt eq 'onboot' || $opt eq 
'shares') {
+   $conf-{$opt} = $conf-{pending}-{$opt};
+   delete $conf-{pending}-{$opt};
+   $changes = 1;
+   }
+}
+
+if ($changes) {
+   update_config_nolock($vmid, $conf, 1);
+   $conf = load_config($vmid); # update/reload
+}
+
+$changes = 0;
+
+# allow manual ballooning if shares is set to zero
+
+if (defined($conf-{pending}-{balloon})  defined($conf-{shares})  
($conf-{shares} == 0)) {
+   my $balloon = $conf-{pending}-{balloon} || $conf-{memory} || 
$defaults-{memory};
+   vm_mon_cmd($vmid, balloon, value = $balloon*1024*1024);
+   $conf-{balloon} = $conf-{pending}-{balloon};
+   delete $conf-{pending}-{balloon};
+   $changes = 1;
+}
+
+if ($changes) {
+   update_config_nolock($vmid, $conf, 1);
+   $conf = load_config($vmid); # update/reload
+}
+
+return if !$conf-{hotplug};
+
+# fixme: implement disk/network hotplug here
+
+}
 
 sub vmconfig_apply_pending {
 my ($vmid, $conf, $storecfg, $running) = @_;
 
-die implement me - vm is running if $running; # fixme: if 
$conf-{hotplug};
+return vmconfig_hotplug_pending($vmid, $conf, $storecfg) if $running;
+
+# cold plug
 
 my @delete = PVE::Tools::split_list($conf-{pending}-{delete});
 foreach my $opt (@delete) { # delete
-- 
1.7.10.4

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


[pve-devel] [PATCH v6 14/22] implement API/CLI to get pending changes

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm |   86 +-
 qm   |   27 +
 2 files changed, 112 insertions(+), 1 deletion(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index b116c24..98a42fe 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -624,7 +624,7 @@ __PACKAGE__-register_method({
 path = '{vmid}/config',
 method = 'GET',
 proxyto = 'node',
-description = Get virtual machine configuration.,
+description = Get current virtual machine configuration. This does not 
include pending configuration changes (see 'pending' API).,
 permissions = {
check = ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
 },
@@ -650,10 +650,94 @@ __PACKAGE__-register_method({
my $conf = PVE::QemuServer::load_config($param-{vmid});
 
delete $conf-{snapshots};
+   delete $conf-{pending};
 
return $conf;
 }});
 
+__PACKAGE__-register_method({
+name = 'vm_pending',
+path = '{vmid}/pending',
+method = 'GET',
+proxyto = 'node',
+description = Get virtual machine configuration, including pending 
changes.,
+permissions = {
+   check = ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
+},
+parameters = {
+   additionalProperties = 0,
+   properties = {
+   node = get_standard_option('pve-node'),
+   vmid = get_standard_option('pve-vmid'),
+   },
+},
+returns = {
+   type = array,
+   items = {
+   type = object,
+   properties = {
+   key = {
+   description = Configuration option name.,
+   type = 'string',
+   },
+   value = {
+   description = Current value.,
+   type = 'string',
+   optional = 1,
+   },
+   pending = {
+   description = Pending value.,
+   type = 'string',
+   optional = 1,
+   },
+   delete = {
+   description = Indicated a pending delete request.,
+   type = 'boolean',
+   optional = 1,
+   },
+   },
+   },
+},
+code = sub {
+   my ($param) = @_;
+
+   my $conf = PVE::QemuServer::load_config($param-{vmid});
+
+   my $pending_delete_hash = {};
+   foreach my $opt (PVE::Tools::split_list($conf-{pending}-{delete})) {
+   $pending_delete_hash-{$opt} = 1;
+   }
+
+   my $res = [];
+
+   foreach my $opt (keys $conf) {
+   next if ref($conf-{$opt});
+   my $item = { key = $opt };
+   $item-{value} = $conf-{$opt} if defined($conf-{$opt});
+   $item-{pending} = $conf-{pending}-{$opt} if 
defined($conf-{pending}-{$opt});
+   $item-{delete} = 1 if $pending_delete_hash-{$opt};
+   push @$res, $item;
+   }
+
+   foreach my $opt (keys $conf-{pending}) {
+   next if $opt eq 'delete';
+   next if ref($conf-{pending}-{$opt}); # just to be sure
+   next if $conf-{$opt};
+   my $item = { key = $opt };
+   $item-{pending} = $conf-{pending}-{$opt};
+   push @$res, $item;
+   }
+
+   foreach my $opt (PVE::Tools::split_list($conf-{pending}-{delete})) {
+   next if $conf-{pending}-{$opt}; # just to be sure
+   next if $conf-{$opt};
+   my $item = { key = $opt, delete = 1};
+   push @$res, $item;
+   }
+
+   return $res;
+}});
+
 my $delete_drive = sub {
 my ($conf, $storecfg, $vmid, $key, $drive, $force) = @_;
 
diff --git a/qm b/qm
index cea223e..249117c 100755
--- a/qm
+++ b/qm
@@ -437,6 +437,33 @@ my $cmddef = {
}
}],

+pending = [ PVE::API2::Qemu, 'vm_pending', ['vmid'],
+   { node = $nodename }, sub {
+   my $data = shift;
+   foreach my $item (sort { $a-{key} cmp $b-{key}} @$data) {
+   my $k = $item-{key};
+   next if $k eq 'digest';
+   my $v = $item-{value};
+   my $p = $item-{pending};
+   if ($k eq 'description') {
+   $v = PVE::Tools::encode_text($v) if defined($v);
+   $p = PVE::Tools::encode_text($p) if defined($p);
+   }
+   if (defined($v)) {
+   if ($item-{delete}) {
+   print del $k: $v\n;
+   } elsif (defined($p)) {
+   print cur $k: $v\n;
+   print new $k: $p\n;
+   } else {
+   print cur $k: $v\n;
+   }
+   } elsif (defined($p)) {
+   print new $k: $p\n;
+  

[pve-devel] [PATCH v6 15/22] rename qemu_bridgeadd to qemu_add_pci_bridge

2014-11-25 Thread Dietmar Maurer
To make it obvious that we add a PCI device, and not a network bridge.

Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 391376e..a8828be 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3049,7 +3049,7 @@ sub vm_deviceplug {
return 1;
 }
 
-qemu_bridgeadd($storecfg, $conf, $vmid, $deviceid); #add bridge if we need 
it for the device
+qemu_add_pci_bridge($storecfg, $conf, $vmid, $deviceid); # add PCI bridge 
if we need it for the device
 
 if ($deviceid =~ m/^(virtio)(\d+)$/) {
 return undef if !qemu_driveadd($storecfg, $vmid, $device);
@@ -3226,23 +3226,27 @@ sub qemu_findorcreatescsihw {
 return 1;
 }
 
-sub qemu_bridgeadd {
+sub qemu_add_pci_bridge {
 my ($storecfg, $conf, $vmid, $device) = @_;
 
 my $bridges = {};
-my $bridgeid = undef;
+
+my $bridgeid;
+
 print_pci_addr($device, $bridges);
 
 while (my ($k, $v) = each %$bridges) {
$bridgeid = $k;
 }
-return if !$bridgeid || $bridgeid  1;
+return if !defined($bridgeid) || $bridgeid  1;
+
 my $bridge = pci.$bridgeid;
 my $devices_list = vm_devices_list($vmid);
 
-if(!defined($devices_list-{$bridge})) {
+if (!defined($devices_list-{$bridge})) {
return undef if !vm_deviceplug($storecfg, $conf, $vmid, $bridge);
 }
+
 return 1;
 }
 
-- 
1.7.10.4

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


[pve-devel] [PATCH v6 17/22] vmconfig_hotplug_pending : add update_net

2014-11-25 Thread Dietmar Maurer
Signed-off-by: Alexandre Derumier aderum...@odiso.com
Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/API2/Qemu.pm  |   44 ++-
 PVE/QemuServer.pm |   67 -
 pve-bridge|8 +--
 3 files changed, 74 insertions(+), 45 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 98a42fe..ea045c9 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -897,46 +897,6 @@ my $vmconfig_update_disk = sub {
 }
 };
 
-my $vmconfig_update_net = sub {
-my ($rpcenv, $authuser, $conf, $storecfg, $vmid, $opt, $value) = @_;
-
-if ($conf-{$opt}  PVE::QemuServer::check_running($vmid)) {
-   my $oldnet = PVE::QemuServer::parse_net($conf-{$opt});
-   my $newnet = PVE::QemuServer::parse_net($value);
-
-   if($oldnet-{model} ne $newnet-{model}){
-   #if model change, we try to hot-unplug
-die error hot-unplug $opt for update if 
!PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
-   }else{
-
-   if($newnet-{bridge}  $oldnet-{bridge}){
-   my $iface = tap.$vmid.i.$1 if $opt =~ m/net(\d+)/;
-
-   if($newnet-{rate} ne $oldnet-{rate}){
-   PVE::Network::tap_rate_limit($iface, $newnet-{rate});
-   }
-
-   if(($newnet-{bridge} ne $oldnet-{bridge}) || ($newnet-{tag} 
ne $oldnet-{tag}) || ($newnet-{firewall} ne $oldnet-{firewall})){
-   PVE::Network::tap_unplug($iface);
-   PVE::Network::tap_plug($iface, $newnet-{bridge}, 
$newnet-{tag}, $newnet-{firewall});
-   }
-
-   }else{
-   #if bridge/nat mode change, we try to hot-unplug
-   die error hot-unplug $opt for update if 
!PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
-   }
-   }
-
-}
-$conf-{$opt} = $value;
-PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
-$conf = PVE::QemuServer::load_config($vmid); # update/reload
-
-my $net = PVE::QemuServer::parse_net($conf-{$opt});
-
-die error hotplug $opt if !PVE::QemuServer::vm_deviceplug($storecfg, 
$conf, $vmid, $opt, $net);
-};
-
 # POST/PUT {vmid}/config implementation
 #
 # The original API used PUT (idempotent) an we assumed that all operations
@@ -1128,8 +1088,8 @@ my $update_vm_api  = sub {
 
} elsif ($opt =~ m/^net(\d+)$/) { #nics
 
-   $vmconfig_update_net($rpcenv, $authuser, $conf, $storecfg, 
$vmid,
- $opt, $param-{$opt});
+   # $vmconfig_update_net($rpcenv, $authuser, $conf, 
$storecfg, $vmid,
+   # $opt, $param-{$opt});
 
} else {
 
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 6642928..c568dfd 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3032,6 +3032,7 @@ sub vm_devices_list {
 return $devices;
 }
 
+# fixme: this should raise exceptions on error!
 sub vm_deviceplug {
 my ($storecfg, $conf, $vmid, $deviceid, $device) = @_;
 
@@ -3073,7 +3074,7 @@ sub vm_deviceplug {
 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);
-if(!qemu_deviceadd($vmid, $devicefull)) {
+if(!qemu_deviceadd($vmid, $devicefull)) { # fixme: use 
qemu_deviceaddverify?
qemu_drivedel($vmid, $deviceid);
return undef;
 }
@@ -3101,6 +3102,7 @@ sub vm_deviceplug {
 return 1;
 }
 
+# fixme: this should raise exceptions on error!
 sub vm_deviceunplug {
 my ($vmid, $conf, $deviceid) = @_;
 
@@ -3532,6 +3534,9 @@ sub vmconfig_hotplug_pending {
} elsif ($opt eq 'cores') {
die skip\n if !$hotplug;
qemu_cpu_hotplug($vmid, $conf, 1);
+   } elsif ($opt =~ m/^net(\d+)$/) {
+   die skip\n if !$hotplug;
+   vm_deviceunplug($vmid, $conf, $opt);
} else {
die skip\n;
}
@@ -3566,6 +3571,9 @@ sub vmconfig_hotplug_pending {
# allow manual ballooning if shares is set to zero
my $balloon = $conf-{pending}-{balloon} || $conf-{memory} || 
$defaults-{memory};
vm_mon_cmd($vmid, balloon, value = $balloon*1024*1024);
+   } elsif ($opt =~ m/^net(\d+)$/) { 
+   # some changes can be done without hotplug
+   vmconfig_update_net($storecfg, $conf, $vmid, $opt, $value);
} else {
die skip\n;  # skip non-hot-pluggable options
}
@@ -3626,6 +3634,63 @@ sub vmconfig_apply_pending {
 }
 }
 
+my $safe_num_ne = sub {
+my ($a, $b) = @_;
+
+return 0 if !defined($a)  !defined($b);
+return 1 if !defined($a);
+return 1 if !defined($b);
+
+return $a != $b;
+};
+
+my $safe_string_ne = sub 

[pve-devel] [PATCH v6 16/22] vmconfig_hotplug_pending: correctly skip values

2014-11-25 Thread Dietmar Maurer
Do not use $skip variable (simply raise an exception)

Signed-off-by: Dietmar Maurer diet...@proxmox.com
---
 PVE/QemuServer.pm |   26 +++---
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index a8828be..6642928 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3521,26 +3521,24 @@ sub vmconfig_hotplug_pending {
 my @delete = PVE::Tools::split_list($conf-{pending}-{delete});
 foreach my $opt (@delete) {
next if $selection  !$selection-{$opt};
-   my $skip;
eval {
if ($opt eq 'tablet') {
-   return undef if !$hotplug;
+   die skip\n if !$hotplug;
if ($defaults-{tablet}) {
vm_deviceplug($storecfg, $conf, $vmid, $opt);
} else {
vm_deviceunplug($vmid, $conf, $opt);
}
} elsif ($opt eq 'cores') {
-   return undef if !$hotplug;
+   die skip\n if !$hotplug;
qemu_cpu_hotplug($vmid, $conf, 1);
} else {
-   $skip = 1; # skip non-hot-pluggable options
-   return undef;
+   die skip\n;
}
};
if (my $err = $@) {
-   $add_error($opt, $err);
-   } elsif (!$skip) {
+   $add_error($opt, $err) if $err ne skip\n;
+   } else {
# save new config if hotplug was successful
delete $conf-{$opt};
vmconfig_undelete_pending_option($conf, $opt);
@@ -3552,31 +3550,29 @@ sub vmconfig_hotplug_pending {
 foreach my $opt (keys %{$conf-{pending}}) {
next if $selection  !$selection-{$opt};
my $value = $conf-{pending}-{$opt};
-   my $skip;
eval {
if ($opt eq 'tablet') {
-   return undef if !$hotplug;
+   die skip\n if !$hotplug;
if ($value == 1) {
vm_deviceplug($storecfg, $conf, $vmid, $opt);
} elsif ($value == 0) {
vm_deviceunplug($vmid, $conf, $opt);
}
} elsif ($opt eq 'cores') {
-   return undef if !$hotplug;
+   die skip\n if !$hotplug;
qemu_cpu_hotplug($vmid, $conf, $value);
} elsif ($opt eq 'balloon') {
-   return undef if !(defined($conf-{shares})  ($conf-{shares} 
== 0));
+   die skip\n if !(defined($conf-{shares})  ($conf-{shares} 
== 0));
# allow manual ballooning if shares is set to zero
my $balloon = $conf-{pending}-{balloon} || $conf-{memory} || 
$defaults-{memory};
vm_mon_cmd($vmid, balloon, value = $balloon*1024*1024);
} else {
-   $skip = 1; # skip non-hot-pluggable options
-   return undef;
+   die skip\n;  # skip non-hot-pluggable options
}
};
if (my $err = $@) {
-   $add_error($opt, $err);
-   } elsif (!$skip) {
+   $add_error($opt, $err) if $err ne skip\n;
+   } else {
# save new config if hotplug was successful
$conf-{$opt} = $value;
delete $conf-{pending}-{$opt};
-- 
1.7.10.4

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


[pve-devel] [PATCH v6 07/22] vm_start: apply pending changes

2014-11-25 Thread Dietmar Maurer
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 41d75d0..d6a70c0 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 

[pve-devel] Qemu-Guest-Agent implementing problems

2014-11-25 Thread Wolfgang
Hi at all,

I have some problems by implementing the qga.

There are 4 commands (guest-shutdown, guest-suspend-disk,
guest-suspend-ram, guest-suspend-hybrid) which does NOT return a response
on success.
How should i handle this.
Have anyone an Idea?

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


Re: [pve-devel] [PATCH v6 21/22] vmconfig_update_net: do not call vm_deviceplug() if hotplug == 0

2014-11-25 Thread Alexandre DERUMIER
Ok, It's working fine now

- Mail original - 

De: Dietmar Maurer diet...@proxmox.com 
À: pve-devel@pve.proxmox.com 
Envoyé: Mardi 25 Novembre 2014 12:24:28 
Objet: [pve-devel] [PATCH v6 21/22] vmconfig_update_net: do not call 
vm_deviceplug() if hotplug == 0 


Signed-off-by: Dietmar Maurer diet...@proxmox.com 
--- 
PVE/QemuServer.pm | 8 +++- 
1 file changed, 7 insertions(+), 1 deletion(-) 

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm 
index 4a44ac8..24c77ef 100644 
--- a/PVE/QemuServer.pm 
+++ b/PVE/QemuServer.pm 
@@ -3699,10 +3699,16 @@ sub vmconfig_update_net { 
PVE::Network::tap_unplug($iface); 
PVE::Network::tap_plug($iface, $newnet-{bridge}, $newnet-{tag}, 
$newnet-{firewall}); 
} 
+ 
+ return 1; 
} 
} 

- vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet); 
+ if ($conf-{hotplug}) { 
+ vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet); 
+ } else { 
+ die skip\n; 
+ } 
} 

sub vmconfig_update_disk { 
-- 
1.7.10.4 

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


Re: [pve-devel] Qemu-Guest-Agent implementing problems

2014-11-25 Thread Dietmar Maurer
I guess we need to use the 'mux_eof' callback for that case. 
See 'man IO::Multiplex' for details.

 There are 4 commands (guest-shutdown, guest-suspend-disk, guest-suspend-
 ram, guest-suspend-hybrid) which does NOT return a response on success.
 How should i handle this.
 Have anyone an Idea?
___
pve-devel mailing list
pve-devel@pve.proxmox.com
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel