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