[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!

Wolfgang Link wolfgang at linksystems.org
Tue Nov 25 10:21:38 CET 2014


From: Alexandre Derumier <aderumier at 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 <aderumier at 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';
+    return "${var_run_tmpdir}/$vmid.$sockettype";
 }
 
 sub qga_socket {
@@ -2880,6 +2881,13 @@ 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";
@@ -3473,7 +3481,7 @@ sub vm_mon_cmd_nocheck {
 }
 
 sub vm_qmp_command {
-    my ($vmid, $cmd, $nocheck) = @_;
+    my ($vmid, $cmd, $nocheck, $qga) = @_;
 
     my $res;
 
@@ -3485,12 +3493,12 @@ sub vm_qmp_command {
 
     eval {
 	die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
-	my $sname = qmp_socket($vmid);
+	my $sname = qmp_socket($vmid, $qga);
 	if (-e $sname) {
-	    my $qmpclient = PVE::QMPClient->new();
+	    my $qmpclient = PVE::QMPClient->new(undef, $qga);
 
 	    $res = $qmpclient->cmd($vmid, $cmd, $timeout);
-	} elsif (-e "${var_run_tmpdir}/$vmid.mon") {
+	} elsif (-e "${var_run_tmpdir}/$vmid.mon" && !$qga) {
 	    die "can't execute complex command on old monitor - stop/start your vm to fix the problem\n"
 		if scalar(%{$cmd->{arguments}});
 	    vm_monitor_command($vmid, $cmd->{execute}, $nocheck);
-- 
1.7.10.4




More information about the pve-devel mailing list