]> git.proxmox.com Git - qemu-server.git/commitdiff
qmpclient: improve error handling
authorDietmar Maurer <dietmar@proxmox.com>
Fri, 28 Nov 2014 09:32:40 +0000 (10:32 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Mon, 1 Dec 2014 08:50:12 +0000 (09:50 +0100)
PVE/QMPClient.pm
PVE/QemuServer.pm

index b4d56125df19aa82410ac37dd21ce1dbaeec1cfa..1ed32a6227ea6b2d08b18cb61ea7899057eebf6e 100755 (executable)
@@ -122,8 +122,7 @@ sub cmd {
        }
     }
 
-    $self->queue_execute($timeout);
-
+    $self->queue_execute($timeout, 2);
 
     die "VM $vmid qmp command '$cmd->{execute}' failed - $queue_info->{error}"
        if defined($queue_info->{error});
@@ -162,7 +161,7 @@ my $close_connection = sub {
 
     if (my $fh = delete $queue_info->{fh}) {
        delete $self->{queue_lookup}->{$fh};
-       $self->{mux}->close($fh);       
+       $self->{mux}->close($fh);
     } 
 };
 
@@ -281,8 +280,9 @@ my $check_queue = sub {
 };
 
 # execute all queued command
+
 sub queue_execute {
-    my ($self, $timeout) = @_;
+    my ($self, $timeout, $noerr) = @_;
 
     $timeout = 3 if !$timeout;
 
@@ -303,7 +303,6 @@ sub queue_execute {
            }
        };
        if (my $err = $@) {
-           warn $err;
            $queue_info->{error} = $err;
        }
     }
@@ -320,11 +319,22 @@ sub queue_execute {
     }
 
     # make sure we close everything
+    my $errors = '';
     foreach my $sname (keys %{$self->{queue_info}}) {
-       &$close_connection($self, $self->{queue_info}->{$sname});
+       my $queue_info = $self->{queue_info}->{$sname};
+       &$close_connection($self, $queue_info);
+       if ($queue_info->{error}) {
+           if ($noerr) {
+               warn $queue_info->{error} if $noerr < 2;
+           } else {
+               $errors .= $queue_info->{error}
+           }
+       }
     }
 
     $self->{queue_info} = $self->{queue_lookup} = {};
+
+    die $errors if $errors;
 }
 
 sub mux_close {
@@ -337,8 +347,7 @@ sub mux_close {
        if !$queue_info->{error};
 }
 
-# mux_input is called when input is available on one of
-# the descriptors.
+# mux_input is called when input is available on one of the descriptors.
 sub mux_input {
     my ($self, $mux, $fh, $input) = @_;
 
@@ -370,15 +379,16 @@ sub mux_input {
            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;
            
-           delete $queue_info->{current};
-
            if ($curcmd->{id} ne $cmdid) {
                die "got wrong command id '$cmdid' (expected $curcmd->{id})\n";
            }
 
+           delete $queue_info->{current};
+
            $obj = from_json($jsons[1]);
 
            if (my $callback = $curcmd->{callback}) {
@@ -409,12 +419,12 @@ sub mux_input {
            my $cmdid = $obj->{id};
            die "received responsed without command id\n" if !$cmdid;
 
-           delete $queue_info->{current};
-
            if ($curcmd->{id} ne $cmdid) {
                die "got wrong command id '$cmdid' (expected $curcmd->{id})\n";
            }
 
+           delete $queue_info->{current};
+
            if (my $callback = $curcmd->{callback}) {
                &$callback($vmid, $obj);
            }
@@ -433,6 +443,7 @@ sub mux_timeout {
 
     if (my $queue_info = &$lookup_queue_info($self, $fh)) { 
        $queue_info->{error} = "got timeout\n";
+       $self->{mux}->inbuffer($fh, ''); # clear to avoid warnings
     }
 
     &$check_queue($self);
@@ -440,7 +451,7 @@ sub mux_timeout {
 
 sub mux_eof {
     my ($self, $mux, $fh, $input) = @_;
+
     my $queue_info = &$lookup_queue_info($self, $fh);
     return if !$queue_info;
 
@@ -455,16 +466,29 @@ sub mux_eof {
 
        return if $$input !~ s/^([^\n]+})\n(.*)$/$2/so;
 
-       my @jsons = split("\n", $1);
+       my $raw = $1;
+
+       eval {
+           my $obj = from_json($raw);
 
-       my $obj = from_json($jsons[0]);
+           my $cmdid = $obj->{'return'};
+           die "received responsed without command id\n" if !$cmdid;
 
-       my $cmdid = $obj->{'return'};
-       die "received responsed without command id\n" if !$cmdid;
+           delete $queue_info->{current};
 
-       delete $queue_info->{current};
+           if (my $callback = $curcmd->{callback}) {
+               &$callback($vmid, undef);
+           }
+       };
+       if (my $err = $@) {
+           $queue_info->{error} = $err;
+       }
 
        &$close_connection($self, $queue_info);
+
+       if (scalar(@{$queue_info->{cmds}}) && !$queue_info->{error}) {
+           $queue_info->{error} = "Got EOF but command queue is not empty.\n";
+       }
     }
 }
 
index d4400249db338fb28e491ed2863ee74c8a225659..17857fb8c52c3a8e672f1c4440b5678b2c733978 100644 (file)
@@ -2339,7 +2339,7 @@ sub vmstatus {
        $qmpclient->queue_cmd($vmid, $statuscb, 'query-status');
     }
 
-    $qmpclient->queue_execute();
+    $qmpclient->queue_execute(undef, 1);
 
     foreach my $vmid (keys %$list) {
        next if $opt_vmid && ($vmid ne $opt_vmid);