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