[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