]> git.proxmox.com Git - qemu-server.git/blame - PVE/API2/Qemu/Agent.pm
implement set-user-password guest agent api call
[qemu-server.git] / PVE / API2 / Qemu / Agent.pm
CommitLineData
b8158701
DC
1package PVE::API2::Qemu::Agent;
2
3use strict;
4use warnings;
5
6use PVE::RESTHandler;
7use PVE::JSONSchema qw(get_standard_option);
8use PVE::QemuServer;
3824765e 9use PVE::QemuServer::Agent qw(agent_available);
b428fb63
DC
10use MIME::Base64 qw(encode_base64 decode_base64);
11use JSON;
b8158701
DC
12
13use base qw(PVE::RESTHandler);
14
ea2bceaf
DC
15# list of commands
16# will generate one api endpoint per command
17# needs a 'method' property and optionally a 'perms' property (default VM.Monitor)
18my $guest_agent_commands = {
19 'ping' => {
20 method => 'POST',
21 },
22 'get-time' => {
e6bd703b 23 method => 'GET',
ea2bceaf
DC
24 },
25 'info' => {
e6bd703b 26 method => 'GET',
ea2bceaf
DC
27 },
28 'fsfreeze-status' => {
29 method => 'POST',
30 },
31 'fsfreeze-freeze' => {
32 method => 'POST',
33 },
34 'fsfreeze-thaw' => {
35 method => 'POST',
36 },
37 'fstrim' => {
38 method => 'POST',
39 },
40 'network-get-interfaces' => {
e6bd703b 41 method => 'GET',
ea2bceaf
DC
42 },
43 'get-vcpus' => {
e6bd703b 44 method => 'GET',
ea2bceaf
DC
45 },
46 'get-fsinfo' => {
e6bd703b 47 method => 'GET',
ea2bceaf
DC
48 },
49 'get-memory-blocks' => {
e6bd703b 50 method => 'GET',
ea2bceaf
DC
51 },
52 'get-memory-block-info' => {
e6bd703b 53 method => 'GET',
ea2bceaf
DC
54 },
55 'suspend-hybrid' => {
56 method => 'POST',
57 },
58 'suspend-ram' => {
59 method => 'POST',
60 },
61 'suspend-disk' => {
62 method => 'POST',
63 },
64 'shutdown' => {
65 method => 'POST',
66 },
5667cc55
DC
67 # added since qemu 2.9
68 'get-host-name' => {
69 method => 'GET',
70 },
71 'get-osinfo' => {
72 method => 'GET',
73 },
74 'get-users' => {
75 method => 'GET',
76 },
77 'get-timezone' => {
78 method => 'GET',
79 },
ea2bceaf
DC
80};
81
ad1f73b9
DC
82__PACKAGE__->register_method({
83 name => 'index',
84 path => '',
85 proxyto => 'node',
86 method => 'GET',
87 description => "Qemu Agent command index.",
88 permissions => {
89 user => 'all',
90 },
91 parameters => {
92 additionalProperties => 1,
93 properties => {
94 node => get_standard_option('pve-node'),
95 vmid => get_standard_option('pve-vmid', {
96 completion => \&PVE::QemuServer::complete_vmid_running }),
97 },
98 },
99 returns => {
100 type => 'array',
101 items => {
102 type => "object",
103 properties => {},
104 },
105 links => [ { rel => 'child', href => '{name}' } ],
106 description => "Returns the list of Qemu Agent commands",
107 },
108 code => sub {
109 my ($param) = @_;
110
111 my $result = [];
112
b428fb63
DC
113 my $cmds = [keys %$guest_agent_commands];
114 push @$cmds, qw(
115 set-user-password
116 );
117
118 for my $cmd ( sort @$cmds) {
ad1f73b9
DC
119 push @$result, { name => $cmd };
120 }
121
122 return $result;
123 }});
124
ea2bceaf
DC
125sub register_command {
126 my ($class, $command, $method, $perm) = @_;
127
128 die "no method given\n" if !$method;
129 die "no command given\n" if !defined($command);
130
131 my $permission;
132
133 if (ref($perm) eq 'HASH') {
134 $permission = $perm;
135 } else {
136 $perm //= 'VM.Monitor';
137 $permission = { check => [ 'perm', '/vms/{vmid}', [ $perm ]]};
138 }
139
140 my $parameters = {
b8158701
DC
141 additionalProperties => 0,
142 properties => {
143 node => get_standard_option('pve-node'),
144 vmid => get_standard_option('pve-vmid', {
ea2bceaf 145 completion => \&PVE::QemuServer::complete_vmid_running }),
b8158701
DC
146 command => {
147 type => 'string',
148 description => "The QGA command.",
ea2bceaf 149 enum => [ sort keys %$guest_agent_commands ],
b8158701
DC
150 },
151 },
ea2bceaf
DC
152 };
153
154 my $description = "Execute Qemu Guest Agent commands.";
155 my $name = 'agent';
156
157 if ($command ne '') {
158 $description = "Execute $command.";
159 $name = $command;
160 delete $parameters->{properties}->{command};
161 }
162
163 __PACKAGE__->register_method({
164 name => $name,
165 path => $command,
166 method => $method,
167 protected => 1,
168 proxyto => 'node',
169 description => $description,
170 permissions => $permission,
171 parameters => $parameters,
172 returns => {
173 type => 'object',
174 description => "Returns an object with a single `result` property.",
175 },
176 code => sub {
177 my ($param) = @_;
178
179 my $vmid = $param->{vmid};
b8158701 180
ea2bceaf 181 my $conf = PVE::QemuConfig->load_config ($vmid); # check if VM exists
b8158701 182
3824765e 183 agent_available($vmid, $conf);
b8158701 184
ea2bceaf
DC
185 my $cmd = $param->{command} // $command;
186 my $res = PVE::QemuServer::vm_mon_cmd($vmid, "guest-$cmd");
b8158701 187
ea2bceaf
DC
188 return { result => $res };
189 }});
190}
b8158701 191
ea2bceaf
DC
192# old {vmid}/agent POST endpoint, here for compatibility
193__PACKAGE__->register_command('', 'POST');
b8158701 194
ea2bceaf
DC
195for my $cmd (sort keys %$guest_agent_commands) {
196 my $props = $guest_agent_commands->{$cmd};
197 __PACKAGE__->register_command($cmd, $props->{method}, $props->{perms});
198}
b8158701 199
b428fb63
DC
200# commands with parameters are complicated and we want to register them manually
201__PACKAGE__->register_method({
202 name => 'set-user-password',
203 path => 'set-user-password',
204 method => 'POST',
205 protected => 1,
206 proxyto => 'node',
207 description => "Sets the password for the given user to the given password",
208 permissions => { check => [ 'perm', '/vms/{vmid}', [ 'VM.Monitor' ]]},
209 parameters => {
210 additionalProperties => 0,
211 properties => {
212 node => get_standard_option('pve-node'),
213 vmid => get_standard_option('pve-vmid', {
214 completion => \&PVE::QemuServer::complete_vmid_running }),
215 username => {
216 type => 'string',
217 description => 'The user to set the password for.'
218 },
219 password => {
220 type => 'string',
221 description => 'The new password.',
222 minLength => 5,
223 maxLength => 64,
224 },
225 crypted => {
226 type => 'boolean',
227 description => 'set to 1 if the password has already been passed through crypt()',
228 optional => 1,
229 default => 0,
230 },
231 },
232 },
233 returns => {
234 type => 'object',
235 description => "Returns an object with a single `result` property.",
236 },
237 code => sub {
238 my ($param) = @_;
239
240 my $vmid = $param->{vmid};
241
242 my $crypted = $param->{crypted} // 0;
243 my $args = {
244 username => $param->{username},
245 password => encode_base64($param->{password}),
246 crypted => $crypted ? JSON::true : JSON::false,
247 };
248 my $res = agent_cmd($vmid, "set-user-password", %$args, 'cannot set user password');
249
250 return { result => $res };
251 }});
252
b8158701 2531;