]>
Commit | Line | Data |
---|---|---|
3824765e DC |
1 | package PVE::QemuServer::Agent; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
804fffdf | 5 | |
3824765e | 6 | use PVE::QemuServer; |
8efdf418 DC |
7 | use MIME::Base64 qw(decode_base64); |
8 | use JSON; | |
3824765e DC |
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}) { | |
804fffdf | 23 | $error = "Agent error: $result->{error}->{desc}\n"; |
3824765e | 24 | } elsif (!defined($result)) { |
804fffdf | 25 | $error = "Agent error: $errmsg\n"; |
3824765e DC |
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 { | |
804fffdf | 42 | die "No QEMU guest agent configured\n" if !defined($conf->{agent}); |
3824765e | 43 | die "VM $vmid is not running\n" if !PVE::QemuServer::check_running($vmid); |
804fffdf | 44 | die "QEMU guest agent is not running\n" if !PVE::QemuServer::qga_check_running($vmid, 1); |
3824765e DC |
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 | ||
8efdf418 DC |
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 | ||
3824765e | 116 | 1; |