]> git.proxmox.com Git - qemu-server.git/blob - PVE/QemuServer/Agent.pm
add ivshmem device to config
[qemu-server.git] / PVE / QemuServer / Agent.pm
1 package PVE::QemuServer::Agent;
2
3 use strict;
4 use warnings;
5
6 use PVE::QemuServer;
7 use MIME::Base64 qw(decode_base64);
8 use JSON;
9 use base 'Exporter';
10
11 our @EXPORT_OK = qw(
12 check_agent_error
13 agent_available
14 agent_cmd
15 );
16
17 sub check_agent_error {
18 my ($result, $errmsg, $noerr) = @_;
19
20 $errmsg //= '';
21 my $error = '';
22 if (ref($result) eq 'HASH' && $result->{error} && $result->{error}->{desc}) {
23 $error = "Agent error: $result->{error}->{desc}\n";
24 } elsif (!defined($result)) {
25 $error = "Agent error: $errmsg\n";
26 }
27
28 if ($error) {
29 die $error if !$noerr;
30
31 warn $error;
32 return undef;
33 }
34
35 return 1;
36 }
37
38 sub agent_available {
39 my ($vmid, $conf, $noerr) = @_;
40
41 eval {
42 die "No QEMU guest agent configured\n" if !defined($conf->{agent});
43 die "VM $vmid is not running\n" if !PVE::QemuServer::check_running($vmid);
44 die "QEMU guest agent is not running\n" if !PVE::QemuServer::qga_check_running($vmid, 1);
45 };
46
47 if (my $err = $@) {
48 die $err if !$noerr;
49 return undef;
50 }
51
52 return 1;
53 }
54
55 # loads config, checks if available, executes command, checks for errors
56 sub agent_cmd {
57 my ($vmid, $cmd, $params, $errormsg, $noerr) = @_;
58
59 my $conf = PVE::QemuConfig->load_config($vmid); # also checks if VM exists
60 agent_available($vmid, $conf, $noerr);
61
62 my $res = PVE::QemuServer::vm_mon_cmd($vmid, "guest-$cmd", %$params);
63 check_agent_error($res, $errormsg, $noerr);
64
65 return $res;
66 }
67
68 sub qemu_exec {
69 my ($vmid, $cmd) = @_;
70
71
72 my $path = shift @$cmd;
73 my $arguments = $cmd;
74
75 my $args = {
76 path => $path,
77 arg => $arguments,
78 'capture-output' => JSON::true,
79 };
80 my $res = agent_cmd($vmid, "exec", $args, "can't execute command '$path $arguments'");
81
82 return $res;
83 }
84
85 sub qemu_exec_status {
86 my ($vmid, $pid) = @_;
87
88 my $res = agent_cmd($vmid, "exec-status", { pid => $pid }, "can't get exec status for '$pid'");
89
90 if ($res->{'out-data'}) {
91 my $decoded = eval { decode_base64($res->{'out-data'}) };
92 warn $@ if $@;
93 if (defined($decoded)) {
94 $res->{'out-data'} = $decoded;
95 }
96 }
97
98 if ($res->{'err-data'}) {
99 my $decoded = eval { decode_base64($res->{'err-data'}) };
100 warn $@ if $@;
101 if (defined($decoded)) {
102 $res->{'err-data'} = $decoded;
103 }
104 }
105
106 # convert JSON::Boolean to 1/0
107 foreach my $d (keys %$res) {
108 if (JSON::is_bool($res->{$d})) {
109 $res->{$d} = ($res->{$d})? 1 : 0;
110 }
111 }
112
113 return $res;
114 }
115
116 1;