# 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;
}, $class;
$self->{eventcb} = $eventcb if $eventcb;
- $self->{qga} = $qga if $qga;
$mux->set_callback_object($self);
};
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_qga++;
+ return "$$"."0".$cmdid_seq_qga;
+ } else {
+ $cmdid_seq++;
+ return "$$:$cmdid_seq";
+ }
};
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;
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') {
my $qmpcmd = undef;
- if($self->{qga}){
+ if($self->{current}->{$vmid}->{qga}){
my $qmpcmdid =to_json({
execute => 'guest-sync',
foreach my $vmid (keys %{$self->{queue}}) {
next if !scalar(@{$self->{queue}->{$vmid}}); # no commands for the VM
- eval {
- my $fh = &$open_connection($self, $vmid, $timeout);
+ if ($self->{queue}->{$vmid}[0]->{execute} =~ /^guest\-+/){
+ $self->{queue}->{$vmid}[0]->{qga} = "1";
+ }
- if(!$self->{qga}){
+ eval {
+ my $fh = &$open_connection($self, $vmid, $timeout, $self->{queue}->{$vmid}[0]->{qga});
+
+ if(!$self->{queue}->{$vmid}[0]->{qga}){
my $cmd = { execute => 'qmp_capabilities', arguments => {} };
unshift @{$self->{queue}->{$vmid}}, $cmd;
}
sub mux_input {
my ($self, $mux, $fh, $input) = @_;
+ my $vmid = $self->{fhs_lookup}->{$fh};
+ if (!$vmid) {
+ warn "internal error - unable to lookup vmid";
+ return;
+ }
+
+ my $curcmd = $self->{current}->{$vmid};
+ die "unable to lookup current command for VM $vmid\n" if !$curcmd;
+
my $raw;
- if($self->{qga}){
+ if ($curcmd->{qga}) {
return if $$input !~ s/^([^\n]+}\n[^\n]+})\n(.*)$/$2/so;
$raw = $1;
- }else{
+ } 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;
- }
-
eval {
my @jsons = split("\n", $raw);
- if($self->{qga}){
+ if ($curcmd->{qga}) {
die "response is not complete" if @jsons != 2 ;
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) {
});
}
-sub vm_qga_cmd {
- my ($vmid, $execute, %params) = @_;
-
- my $cmd = { execute => $execute, arguments => \%params };
- vm_qmp_command($vmid, $cmd, undef, 1);
-}
-
sub vm_mon_cmd {
my ($vmid, $execute, %params) = @_;
}
sub vm_qmp_command {
- my ($vmid, $cmd, $nocheck, $qga) = @_;
+ my ($vmid, $cmd, $nocheck) = @_;
my $res;
eval {
die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
+ 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();
$res = $qmpclient->cmd($vmid, $cmd, $timeout);
- } elsif (-e "${var_run_tmpdir}/$vmid.mon" && !$qga) {
+ } elsif (-e "${var_run_tmpdir}/$vmid.mon") {
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);