]> git.proxmox.com Git - qemu-server.git/blob - PVE/API2/Qemu/Agent.pm
5141b4e2a50312aa002f275b32bda58ad07bcf32
[qemu-server.git] / PVE / API2 / Qemu / Agent.pm
1 package PVE::API2::Qemu::Agent;
2
3 use strict;
4 use warnings;
5
6 use PVE::RESTHandler;
7 use PVE::JSONSchema qw(get_standard_option);
8 use PVE::QemuServer;
9
10 use base qw(PVE::RESTHandler);
11
12 # list of commands
13 # will generate one api endpoint per command
14 # needs a 'method' property and optionally a 'perms' property (default VM.Monitor)
15 my $guest_agent_commands = {
16 'ping' => {
17 method => 'POST',
18 },
19 'get-time' => {
20 method => 'GET',
21 },
22 'info' => {
23 method => 'GET',
24 },
25 'fsfreeze-status' => {
26 method => 'POST',
27 },
28 'fsfreeze-freeze' => {
29 method => 'POST',
30 },
31 'fsfreeze-thaw' => {
32 method => 'POST',
33 },
34 'fstrim' => {
35 method => 'POST',
36 },
37 'network-get-interfaces' => {
38 method => 'GET',
39 },
40 'get-vcpus' => {
41 method => 'GET',
42 },
43 'get-fsinfo' => {
44 method => 'GET',
45 },
46 'get-memory-blocks' => {
47 method => 'GET',
48 },
49 'get-memory-block-info' => {
50 method => 'GET',
51 },
52 'suspend-hybrid' => {
53 method => 'POST',
54 },
55 'suspend-ram' => {
56 method => 'POST',
57 },
58 'suspend-disk' => {
59 method => 'POST',
60 },
61 'shutdown' => {
62 method => 'POST',
63 },
64 # added since qemu 2.9
65 'get-host-name' => {
66 method => 'GET',
67 },
68 'get-osinfo' => {
69 method => 'GET',
70 },
71 'get-users' => {
72 method => 'GET',
73 },
74 'get-timezone' => {
75 method => 'GET',
76 },
77 };
78
79 __PACKAGE__->register_method({
80 name => 'index',
81 path => '',
82 proxyto => 'node',
83 method => 'GET',
84 description => "Qemu Agent command index.",
85 permissions => {
86 user => 'all',
87 },
88 parameters => {
89 additionalProperties => 1,
90 properties => {
91 node => get_standard_option('pve-node'),
92 vmid => get_standard_option('pve-vmid', {
93 completion => \&PVE::QemuServer::complete_vmid_running }),
94 },
95 },
96 returns => {
97 type => 'array',
98 items => {
99 type => "object",
100 properties => {},
101 },
102 links => [ { rel => 'child', href => '{name}' } ],
103 description => "Returns the list of Qemu Agent commands",
104 },
105 code => sub {
106 my ($param) = @_;
107
108 my $result = [];
109
110 for my $cmd (sort keys %$guest_agent_commands) {
111 push @$result, { name => $cmd };
112 }
113
114 return $result;
115 }});
116
117 sub register_command {
118 my ($class, $command, $method, $perm) = @_;
119
120 die "no method given\n" if !$method;
121 die "no command given\n" if !defined($command);
122
123 my $permission;
124
125 if (ref($perm) eq 'HASH') {
126 $permission = $perm;
127 } else {
128 $perm //= 'VM.Monitor';
129 $permission = { check => [ 'perm', '/vms/{vmid}', [ $perm ]]};
130 }
131
132 my $parameters = {
133 additionalProperties => 0,
134 properties => {
135 node => get_standard_option('pve-node'),
136 vmid => get_standard_option('pve-vmid', {
137 completion => \&PVE::QemuServer::complete_vmid_running }),
138 command => {
139 type => 'string',
140 description => "The QGA command.",
141 enum => [ sort keys %$guest_agent_commands ],
142 },
143 },
144 };
145
146 my $description = "Execute Qemu Guest Agent commands.";
147 my $name = 'agent';
148
149 if ($command ne '') {
150 $description = "Execute $command.";
151 $name = $command;
152 delete $parameters->{properties}->{command};
153 }
154
155 __PACKAGE__->register_method({
156 name => $name,
157 path => $command,
158 method => $method,
159 protected => 1,
160 proxyto => 'node',
161 description => $description,
162 permissions => $permission,
163 parameters => $parameters,
164 returns => {
165 type => 'object',
166 description => "Returns an object with a single `result` property.",
167 },
168 code => sub {
169 my ($param) = @_;
170
171 my $vmid = $param->{vmid};
172
173 my $conf = PVE::QemuConfig->load_config ($vmid); # check if VM exists
174
175 die "No Qemu Guest Agent\n" if !defined($conf->{agent});
176 die "VM $vmid is not running\n" if !PVE::QemuServer::check_running($vmid);
177 die "Qemu Guest Agent is not running\n" if !PVE::QemuServer::qga_check_running($vmid, 1);
178
179 my $cmd = $param->{command} // $command;
180 my $res = PVE::QemuServer::vm_mon_cmd($vmid, "guest-$cmd");
181
182 return { result => $res };
183 }});
184 }
185
186 # old {vmid}/agent POST endpoint, here for compatibility
187 __PACKAGE__->register_command('', 'POST');
188
189 for my $cmd (sort keys %$guest_agent_commands) {
190 my $props = $guest_agent_commands->{$cmd};
191 __PACKAGE__->register_command($cmd, $props->{method}, $props->{perms});
192 }
193
194 1;