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