]> git.proxmox.com Git - pve-container.git/blame - src/PVE/API2/LXC/Status.pm
Use foreach_volume instead of foreach_mountpoint-variants
[pve-container.git] / src / PVE / API2 / LXC / Status.pm
CommitLineData
52389a07
DM
1package PVE::API2::LXC::Status;
2
3use strict;
4use warnings;
5
6use PVE::SafeSyslog;
7use PVE::Tools qw(extract_param run_command);
8use PVE::Exception qw(raise raise_param_exc);
9use PVE::INotify;
10use PVE::Cluster qw(cfs_read_file);
11use PVE::AccessControl;
12use PVE::Firewall;
13use PVE::Storage;
14use PVE::RESTHandler;
15use PVE::RPCEnvironment;
16use PVE::LXC;
17use PVE::LXC::Create;
52389a07 18use PVE::JSONSchema qw(get_standard_option);
17f1dc40 19
52389a07
DM
20use base qw(PVE::RESTHandler);
21
6c2e9377
WB
22BEGIN {
23 if (!$ENV{PVE_GENERATING_DOCS}) {
24 require PVE::HA::Env::PVE2;
25 import PVE::HA::Env::PVE2;
26 require PVE::HA::Config;
27 import PVE::HA::Config;
28 }
29}
52389a07
DM
30
31__PACKAGE__->register_method({
32 name => 'vmcmdidx',
33 path => '',
34 method => 'GET',
35 proxyto => 'node',
36 description => "Directory index",
37 permissions => {
38 user => 'all',
39 },
40 parameters => {
17f1dc40 41 additionalProperties => 0,
52389a07
DM
42 properties => {
43 node => get_standard_option('pve-node'),
44 vmid => get_standard_option('pve-vmid'),
45 },
46 },
47 returns => {
48 type => 'array',
49 items => {
50 type => "object",
51 properties => {
52 subdir => { type => 'string' },
53 },
54 },
55 links => [ { rel => 'child', href => "{subdir}" } ],
56 },
57 code => sub {
58 my ($param) = @_;
59
60 # test if VM exists
67afe46e 61 my $conf = PVE::LXC::Config->load_config($param->{vmid});
52389a07
DM
62
63 my $res = [
64 { subdir => 'current' },
65 { subdir => 'start' },
66 { subdir => 'stop' },
67 { subdir => 'shutdown' },
f5fe1125 68 { subdir => 'reboot' },
52389a07 69 { subdir => 'migrate' },
17f1dc40 70 ];
52389a07
DM
71
72 return $res;
73 }});
74
75__PACKAGE__->register_method({
76 name => 'vm_status',
77 path => 'current',
78 method => 'GET',
79 proxyto => 'node',
17f1dc40 80 protected => 1, # /proc entries are only readable by root
52389a07
DM
81 description => "Get virtual machine status.",
82 permissions => {
83 check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
84 },
85 parameters => {
17f1dc40 86 additionalProperties => 0,
52389a07
DM
87 properties => {
88 node => get_standard_option('pve-node'),
89 vmid => get_standard_option('pve-vmid'),
90 },
91 },
8233d33d
DM
92 returns => {
93 type => 'object',
94 properties => {
95 %$PVE::LXC::vmstatus_return_properties,
96 ha => {
97 description => "HA manager service status.",
98 type => 'object',
99 },
100 },
101 },
52389a07
DM
102 code => sub {
103 my ($param) = @_;
104
105 # test if VM exists
c83c9007
TL
106 my $vmid = $param->{vmid};
107 my $conf = PVE::LXC::Config->load_config($vmid);
52389a07 108
c83c9007
TL
109 my $vmstatus = PVE::LXC::vmstatus($vmid);
110 my $status = $vmstatus->{$vmid};
52389a07 111
c83c9007 112 $status->{ha} = PVE::HA::Config::get_service_status("ct:$vmid");
52389a07
DM
113
114 return $status;
115 }});
116
117__PACKAGE__->register_method({
118 name => 'vm_start',
119 path => 'start',
120 method => 'POST',
121 protected => 1,
122 proxyto => 'node',
123 description => "Start the container.",
124 permissions => {
125 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
126 },
127 parameters => {
17f1dc40 128 additionalProperties => 0,
52389a07
DM
129 properties => {
130 node => get_standard_option('pve-node'),
68e8f3c5 131 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_stopped }),
2de0b3d4 132 skiplock => get_standard_option('skiplock'),
52389a07
DM
133 },
134 },
135 returns => {
136 type => 'string',
137 },
138 code => sub {
139 my ($param) = @_;
140
141 my $rpcenv = PVE::RPCEnvironment::get();
52389a07
DM
142 my $authuser = $rpcenv->get_user();
143
144 my $node = extract_param($param, 'node');
52389a07
DM
145 my $vmid = extract_param($param, 'vmid');
146
2de0b3d4
WB
147 my $skiplock = extract_param($param, 'skiplock');
148 raise_param_exc({ skiplock => "Only root may use this option." })
149 if $skiplock && $authuser ne 'root@pam';
150
52389a07
DM
151 die "CT $vmid already running\n" if PVE::LXC::check_running($vmid);
152
1e56e83e
WB
153 PVE::Cluster::check_cfs_quorum();
154
52389a07
DM
155 if (PVE::HA::Config::vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
156
157 my $hacmd = sub {
158 my $upid = shift;
159
545dd4e1 160 print "Requesting HA start for CT $vmid\n";
52389a07 161
35d2a4e4 162 my $cmd = ['ha-manager', 'set', "ct:$vmid", '--state', 'started'];
52389a07 163 PVE::Tools::run_command($cmd);
52389a07
DM
164 };
165
166 return $rpcenv->fork_worker('hastart', $vmid, $authuser, $hacmd);
167
168 } else {
169
6a4e5293
TL
170 my $realcmd = sub {
171 my $upid = shift;
52389a07 172
6a4e5293 173 syslog('info', "starting CT $vmid: $upid\n");
52389a07 174
6a4e5293 175 my $conf = PVE::LXC::Config->load_config($vmid);
fdf71adb 176
6a4e5293
TL
177 die "you can't start a CT if it's a template\n"
178 if PVE::LXC::Config->is_template($conf);
894aa229 179
6a4e5293
TL
180 if (!$skiplock && !PVE::LXC::Config->has_lock($conf, 'mounted')) {
181 PVE::LXC::Config->check_lock($conf);
182 }
894aa229 183
6a4e5293 184 if ($conf->{unprivileged}) {
015740e6 185 PVE::LXC::Config->foreach_volume($conf, sub {
6a4e5293
TL
186 my ($ms, $mountpoint) = @_;
187 die "Quotas are not supported by unprivileged containers.\n" if $mountpoint->{quota};
188 });
189 }
52389a07 190
6a4e5293
TL
191 PVE::LXC::vm_start($vmid, $conf, $skiplock);
192 };
f053a616 193
6a4e5293 194 my $lockcmd = sub {
f053a616 195 return $rpcenv->fork_worker('vzstart', $vmid, $authuser, $realcmd);
52389a07
DM
196 };
197
67afe46e 198 return PVE::LXC::Config->lock_config($vmid, $lockcmd);
52389a07
DM
199 }
200 }});
201
202__PACKAGE__->register_method({
203 name => 'vm_stop',
204 path => 'stop',
205 method => 'POST',
206 protected => 1,
207 proxyto => 'node',
52eb76e5 208 description => "Stop the container. This will abruptly stop all processes running in the container.",
52389a07
DM
209 permissions => {
210 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
211 },
212 parameters => {
17f1dc40 213 additionalProperties => 0,
52389a07
DM
214 properties => {
215 node => get_standard_option('pve-node'),
68e8f3c5 216 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_running }),
2de0b3d4 217 skiplock => get_standard_option('skiplock'),
52389a07
DM
218 },
219 },
220 returns => {
221 type => 'string',
222 },
223 code => sub {
224 my ($param) = @_;
225
226 my $rpcenv = PVE::RPCEnvironment::get();
227
228 my $authuser = $rpcenv->get_user();
229
230 my $node = extract_param($param, 'node');
231
232 my $vmid = extract_param($param, 'vmid');
233
2de0b3d4
WB
234 my $skiplock = extract_param($param, 'skiplock');
235 raise_param_exc({ skiplock => "Only root may use this option." })
236 if $skiplock && $authuser ne 'root@pam';
237
52389a07
DM
238 die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
239
240 if (PVE::HA::Config::vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
241
242 my $hacmd = sub {
243 my $upid = shift;
244
545dd4e1 245 print "Requesting HA stop for CT $vmid\n";
52389a07 246
f7a6910a 247 my $cmd = ['ha-manager', 'crm-command', 'stop', "ct:$vmid", '0'];
52389a07 248 PVE::Tools::run_command($cmd);
52389a07
DM
249 };
250
251 return $rpcenv->fork_worker('hastop', $vmid, $authuser, $hacmd);
252
253 } else {
254
6a4e5293
TL
255 my $realcmd = sub {
256 my $upid = shift;
fdf71adb 257
6a4e5293 258 syslog('info', "stopping CT $vmid: $upid\n");
fdf71adb 259
6a4e5293
TL
260 my $conf = PVE::LXC::Config->load_config($vmid);
261 if (!$skiplock && !PVE::LXC::Config->has_lock($conf, 'mounted')) {
262 PVE::LXC::Config->check_lock($conf);
263 }
52389a07 264
6a4e5293
TL
265 PVE::LXC::vm_stop($vmid, 1);
266 };
f053a616 267
6a4e5293 268 my $lockcmd = sub {
f053a616 269 return $rpcenv->fork_worker('vzstop', $vmid, $authuser, $realcmd);
52389a07
DM
270 };
271
67afe46e 272 return PVE::LXC::Config->lock_config($vmid, $lockcmd);
52389a07
DM
273 }
274 }});
275
276__PACKAGE__->register_method({
277 name => 'vm_shutdown',
278 path => 'shutdown',
279 method => 'POST',
280 protected => 1,
281 proxyto => 'node',
52eb76e5
EK
282 description => "Shutdown the container. This will trigger a clean shutdown " .
283 "of the container, see lxc-stop(1) for details.",
52389a07
DM
284 permissions => {
285 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
286 },
287 parameters => {
17f1dc40 288 additionalProperties => 0,
52389a07
DM
289 properties => {
290 node => get_standard_option('pve-node'),
68e8f3c5 291 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_running }),
52389a07
DM
292 timeout => {
293 description => "Wait maximal timeout seconds.",
294 type => 'integer',
295 minimum => 0,
296 optional => 1,
297 default => 60,
298 },
299 forceStop => {
300 description => "Make sure the Container stops.",
301 type => 'boolean',
302 optional => 1,
303 default => 0,
304 }
305 },
306 },
307 returns => {
308 type => 'string',
309 },
310 code => sub {
311 my ($param) = @_;
312
313 my $rpcenv = PVE::RPCEnvironment::get();
52389a07
DM
314 my $authuser = $rpcenv->get_user();
315
316 my $node = extract_param($param, 'node');
52389a07
DM
317 my $vmid = extract_param($param, 'vmid');
318
6a4e5293 319 my $timeout = extract_param($param, 'timeout') // 60;
52389a07
DM
320
321 die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
322
35d2a4e4 323 if (PVE::HA::Config::vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
5bcdc2ac
DM
324 my $hacmd = sub {
325 my $upid = shift;
326
545dd4e1 327 print "Requesting HA stop for CT $vmid\n";
5bcdc2ac 328
f7a6910a 329 my $cmd = ['ha-manager', 'crm-command', 'stop', "ct:$vmid", "$timeout"];
5bcdc2ac 330 PVE::Tools::run_command($cmd);
5bcdc2ac
DM
331 };
332
333 return $rpcenv->fork_worker('hastop', $vmid, $authuser, $hacmd);
334 }
335
6a4e5293
TL
336 my $realcmd = sub {
337 my $upid = shift;
52389a07 338
6a4e5293 339 syslog('info', "shutdown CT $vmid: $upid\n");
f053a616 340
6a4e5293
TL
341 my $conf = PVE::LXC::Config->load_config($vmid);
342 PVE::LXC::Config->check_lock($conf);
52389a07 343
6a4e5293
TL
344 PVE::LXC::vm_stop($vmid, 0, $timeout, $param->{forceStop});
345 };
52389a07 346
6a4e5293 347 my $lockcmd = sub {
f053a616
FG
348 return $rpcenv->fork_worker('vzshutdown', $vmid, $authuser, $realcmd);
349 };
52389a07 350
67afe46e 351 return PVE::LXC::Config->lock_config($vmid, $lockcmd);
52389a07
DM
352 }});
353
354__PACKAGE__->register_method({
355 name => 'vm_suspend',
356 path => 'suspend',
357 method => 'POST',
358 protected => 1,
359 proxyto => 'node',
360 description => "Suspend the container.",
361 permissions => {
4de00d82 362 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
52389a07
DM
363 },
364 parameters => {
17f1dc40
TL
365 additionalProperties => 0,
366 properties => {
4de00d82 367 node => get_standard_option('pve-node'),
68e8f3c5 368 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_running }),
17f1dc40 369 },
52389a07
DM
370 },
371 returns => {
17f1dc40 372 type => 'string',
52389a07
DM
373 },
374 code => sub {
4de00d82 375 my ($param) = @_;
52389a07 376
4de00d82
TL
377 my $rpcenv = PVE::RPCEnvironment::get();
378 my $authuser = $rpcenv->get_user();
52389a07 379
4de00d82
TL
380 my $node = extract_param($param, 'node');
381 my $vmid = extract_param($param, 'vmid');
52389a07 382
4de00d82 383 die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
52389a07 384
6a4e5293
TL
385 my $realcmd = sub {
386 my $upid = shift;
52389a07 387
6a4e5293 388 syslog('info', "suspend CT $vmid: $upid\n");
52389a07 389
6a4e5293
TL
390 my $conf = PVE::LXC::Config->load_config($vmid);
391 PVE::LXC::Config->check_lock($conf);
52389a07 392
6a4e5293
TL
393 my $cmd = ['lxc-checkpoint', '-n', $vmid, '-s', '-D', '/var/lib/vz/dump'];
394 run_command($cmd);
395 };
52389a07 396
6a4e5293 397 my $lockcmd = sub {
f053a616
FG
398 return $rpcenv->fork_worker('vzsuspend', $vmid, $authuser, $realcmd);
399 };
52389a07 400
67afe46e 401 return PVE::LXC::Config->lock_config($vmid, $lockcmd);
52389a07
DM
402 }});
403
404__PACKAGE__->register_method({
405 name => 'vm_resume',
406 path => 'resume',
407 method => 'POST',
408 protected => 1,
409 proxyto => 'node',
410 description => "Resume the container.",
411 permissions => {
412 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
413 },
414 parameters => {
17f1dc40
TL
415 additionalProperties => 0,
416 properties => {
417 node => get_standard_option('pve-node'),
68e8f3c5 418 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_stopped }),
17f1dc40 419 },
52389a07
DM
420 },
421 returns => {
17f1dc40 422 type => 'string',
52389a07
DM
423 },
424 code => sub {
4de00d82 425 my ($param) = @_;
52389a07 426
4de00d82
TL
427 my $rpcenv = PVE::RPCEnvironment::get();
428 my $authuser = $rpcenv->get_user();
52389a07 429
4de00d82
TL
430 my $node = extract_param($param, 'node');
431 my $vmid = extract_param($param, 'vmid');
52389a07 432
4de00d82 433 die "CT $vmid already running\n" if PVE::LXC::check_running($vmid);
52389a07 434
6a4e5293
TL
435 my $realcmd = sub {
436 my $upid = shift;
52389a07 437
6a4e5293 438 syslog('info', "resume CT $vmid: $upid\n");
52389a07 439
6a4e5293 440 my $cmd = ['lxc-checkpoint', '-n', $vmid, '-r', '--foreground', '-D', '/var/lib/vz/dump'];
52389a07 441 run_command($cmd);
6a4e5293 442 };
52389a07 443
6a4e5293 444 my $upid = $rpcenv->fork_worker('vzresume', $vmid, $authuser, $realcmd);
52389a07 445
4de00d82 446 return $upid;
52389a07
DM
447 }});
448
f5fe1125
OB
449__PACKAGE__->register_method({
450 name => 'vm_reboot',
451 path => 'reboot',
452 method => 'POST',
453 protected => 1,
454 proxyto => 'node',
455 description => "Reboot the container by shutting it down, and starting it again. Applies pending changes.",
456 permissions => {
457 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
458 },
459 parameters => {
460 additionalProperties => 0,
461 properties => {
462 node => get_standard_option('pve-node'),
463 vmid => get_standard_option('pve-vmid',
464 { completion => \&PVE::LXC::complete_ctid_running }),
465 timeout => {
466 description => "Wait maximal timeout seconds for the shutdown.",
467 type => 'integer',
468 minimum => 0,
469 optional => 1,
470 },
471 },
472 },
473 returns => {
474 type => 'string',
475 },
476 code => sub {
477 my ($param) = @_;
478
479 my $rpcenv = PVE::RPCEnvironment::get();
480 my $authuser = $rpcenv->get_user();
481
482 my $node = extract_param($param, 'node');
483 my $vmid = extract_param($param, 'vmid');
484
485 die "VM $vmid not running\n" if !PVE::LXC::check_running($vmid);
486
487 my $realcmd = sub {
488 my $upid = shift;
489
490 syslog('info', "requesting reboot of CT $vmid: $upid\n");
491 PVE::LXC::vm_reboot($vmid, $param->{timeout});
492 return;
493 };
494
495 return $rpcenv->fork_worker('vzreboot', $vmid, $authuser, $realcmd);
496 }});
497
498
499
52389a07 5001;