]> git.proxmox.com Git - pve-container.git/blob - src/PVE/API2/LXC/Status.pm
api status: indentation cleanup
[pve-container.git] / src / PVE / API2 / LXC / Status.pm
1 package PVE::API2::LXC::Status;
2
3 use strict;
4 use warnings;
5
6 use PVE::SafeSyslog;
7 use PVE::Tools qw(extract_param run_command);
8 use PVE::Exception qw(raise raise_param_exc);
9 use PVE::INotify;
10 use PVE::Cluster qw(cfs_read_file);
11 use PVE::AccessControl;
12 use PVE::Firewall;
13 use PVE::Storage;
14 use PVE::RESTHandler;
15 use PVE::RPCEnvironment;
16 use PVE::LXC;
17 use PVE::LXC::Create;
18 use PVE::JSONSchema qw(get_standard_option);
19 use base qw(PVE::RESTHandler);
20
21 BEGIN {
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 }
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
60 my $conf = PVE::LXC::Config->load_config($param->{vmid});
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 => {
91 type => 'object',
92 properties => {
93 %$PVE::LXC::vmstatus_return_properties,
94 ha => {
95 description => "HA manager service status.",
96 type => 'object',
97 },
98 },
99 },
100 code => sub {
101 my ($param) = @_;
102
103 # test if VM exists
104 my $conf = PVE::LXC::Config->load_config($param->{vmid});
105
106 my $vmstatus = PVE::LXC::vmstatus($param->{vmid});
107 my $status = $vmstatus->{$param->{vmid}};
108
109 $status->{ha} = PVE::HA::Config::get_service_status("ct:$param->{vmid}");
110
111 return $status;
112 }});
113
114 __PACKAGE__->register_method({
115 name => 'vm_start',
116 path => 'start',
117 method => 'POST',
118 protected => 1,
119 proxyto => 'node',
120 description => "Start the container.",
121 permissions => {
122 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
123 },
124 parameters => {
125 additionalProperties => 0,
126 properties => {
127 node => get_standard_option('pve-node'),
128 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_stopped }),
129 skiplock => get_standard_option('skiplock'),
130 },
131 },
132 returns => {
133 type => 'string',
134 },
135 code => sub {
136 my ($param) = @_;
137
138 my $rpcenv = PVE::RPCEnvironment::get();
139
140 my $authuser = $rpcenv->get_user();
141
142 my $node = extract_param($param, 'node');
143
144 my $vmid = extract_param($param, 'vmid');
145
146 my $skiplock = extract_param($param, 'skiplock');
147 raise_param_exc({ skiplock => "Only root may use this option." })
148 if $skiplock && $authuser ne 'root@pam';
149
150 die "CT $vmid already running\n" if PVE::LXC::check_running($vmid);
151
152 PVE::Cluster::check_cfs_quorum();
153
154 if (PVE::HA::Config::vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
155
156 my $hacmd = sub {
157 my $upid = shift;
158
159 my $service = "ct:$vmid";
160
161 my $cmd = ['ha-manager', 'set', $service, '--state', 'started'];
162
163 print "Requesting HA start for CT $vmid\n";
164
165 PVE::Tools::run_command($cmd);
166
167 return;
168 };
169
170 return $rpcenv->fork_worker('hastart', $vmid, $authuser, $hacmd);
171
172 } else {
173
174 my $lockcmd = sub {
175 my $realcmd = sub {
176 my $upid = shift;
177
178 syslog('info', "starting CT $vmid: $upid\n");
179
180 my $conf = PVE::LXC::Config->load_config($vmid);
181
182 die "you can't start a CT if it's a template\n"
183 if PVE::LXC::Config->is_template($conf);
184
185 if (!$skiplock && !PVE::LXC::Config->has_lock($conf, 'mounted')) {
186 PVE::LXC::Config->check_lock($conf);
187 }
188
189 if ($conf->{unprivileged}) {
190 PVE::LXC::Config->foreach_mountpoint($conf, sub {
191 my ($ms, $mountpoint) = @_;
192 die "Quotas are not supported by unprivileged containers.\n" if $mountpoint->{quota};
193 });
194
195 }
196
197 PVE::LXC::vm_start($vmid, $conf, $skiplock);
198
199 return;
200 };
201
202 return $rpcenv->fork_worker('vzstart', $vmid, $authuser, $realcmd);
203 };
204
205 return PVE::LXC::Config->lock_config($vmid, $lockcmd);
206 }
207 }});
208
209 __PACKAGE__->register_method({
210 name => 'vm_stop',
211 path => 'stop',
212 method => 'POST',
213 protected => 1,
214 proxyto => 'node',
215 description => "Stop the container. This will abruptly stop all processes running in the container.",
216 permissions => {
217 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
218 },
219 parameters => {
220 additionalProperties => 0,
221 properties => {
222 node => get_standard_option('pve-node'),
223 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_running }),
224 skiplock => get_standard_option('skiplock'),
225 },
226 },
227 returns => {
228 type => 'string',
229 },
230 code => sub {
231 my ($param) = @_;
232
233 my $rpcenv = PVE::RPCEnvironment::get();
234
235 my $authuser = $rpcenv->get_user();
236
237 my $node = extract_param($param, 'node');
238
239 my $vmid = extract_param($param, 'vmid');
240
241 my $skiplock = extract_param($param, 'skiplock');
242 raise_param_exc({ skiplock => "Only root may use this option." })
243 if $skiplock && $authuser ne 'root@pam';
244
245 die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
246
247 if (PVE::HA::Config::vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
248
249 my $hacmd = sub {
250 my $upid = shift;
251
252 my $service = "ct:$vmid";
253
254 my $cmd = ['ha-manager', 'set', $service, '--state', 'stopped'];
255
256 print "Requesting HA stop for CT $vmid\n";
257
258 PVE::Tools::run_command($cmd);
259
260 return;
261 };
262
263 return $rpcenv->fork_worker('hastop', $vmid, $authuser, $hacmd);
264
265 } else {
266
267 my $lockcmd = sub {
268 my $realcmd = sub {
269 my $upid = shift;
270
271 syslog('info', "stopping CT $vmid: $upid\n");
272
273 my $conf = PVE::LXC::Config->load_config($vmid);
274
275 if (!$skiplock && !PVE::LXC::Config->has_lock($conf, 'mounted')) {
276 PVE::LXC::Config->check_lock($conf);
277 }
278
279 PVE::LXC::vm_stop($vmid, 1);
280
281 return;
282 };
283
284 return $rpcenv->fork_worker('vzstop', $vmid, $authuser, $realcmd);
285 };
286
287 return PVE::LXC::Config->lock_config($vmid, $lockcmd);
288 }
289 }});
290
291 __PACKAGE__->register_method({
292 name => 'vm_shutdown',
293 path => 'shutdown',
294 method => 'POST',
295 protected => 1,
296 proxyto => 'node',
297 description => "Shutdown the container. This will trigger a clean shutdown " .
298 "of the container, see lxc-stop(1) for details.",
299 permissions => {
300 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
301 },
302 parameters => {
303 additionalProperties => 0,
304 properties => {
305 node => get_standard_option('pve-node'),
306 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_running }),
307 timeout => {
308 description => "Wait maximal timeout seconds.",
309 type => 'integer',
310 minimum => 0,
311 optional => 1,
312 default => 60,
313 },
314 forceStop => {
315 description => "Make sure the Container stops.",
316 type => 'boolean',
317 optional => 1,
318 default => 0,
319 }
320 },
321 },
322 returns => {
323 type => 'string',
324 },
325 code => sub {
326 my ($param) = @_;
327
328 my $rpcenv = PVE::RPCEnvironment::get();
329
330 my $authuser = $rpcenv->get_user();
331
332 my $node = extract_param($param, 'node');
333
334 my $vmid = extract_param($param, 'vmid');
335
336 my $timeout = extract_param($param, 'timeout');
337
338 die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
339
340 if (PVE::HA::Config::vm_is_ha_managed($vmid) &&
341 $rpcenv->{type} ne 'ha') {
342
343 my $hacmd = sub {
344 my $upid = shift;
345
346 my $service = "ct:$vmid";
347
348 my $cmd = ['ha-manager', 'set', $service, '--state', 'stopped'];
349
350 print "Requesting HA stop for CT $vmid\n";
351
352 PVE::Tools::run_command($cmd);
353
354 return;
355 };
356
357 return $rpcenv->fork_worker('hastop', $vmid, $authuser, $hacmd);
358 }
359
360 my $lockcmd = sub {
361 my $realcmd = sub {
362 my $upid = shift;
363
364 syslog('info', "shutdown CT $vmid: $upid\n");
365
366 $timeout = 60 if !defined($timeout);
367
368 my $conf = PVE::LXC::Config->load_config($vmid);
369
370 PVE::LXC::Config->check_lock($conf);
371
372 PVE::LXC::vm_stop($vmid, 0, $timeout, $param->{forceStop});
373
374 return;
375 };
376
377 return $rpcenv->fork_worker('vzshutdown', $vmid, $authuser, $realcmd);
378 };
379
380 return PVE::LXC::Config->lock_config($vmid, $lockcmd);
381 }});
382
383 __PACKAGE__->register_method({
384 name => 'vm_suspend',
385 path => 'suspend',
386 method => 'POST',
387 protected => 1,
388 proxyto => 'node',
389 description => "Suspend the container.",
390 permissions => {
391 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
392 },
393 parameters => {
394 additionalProperties => 0,
395 properties => {
396 node => get_standard_option('pve-node'),
397 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_running }),
398 },
399 },
400 returns => {
401 type => 'string',
402 },
403 code => sub {
404 my ($param) = @_;
405
406 my $rpcenv = PVE::RPCEnvironment::get();
407 my $authuser = $rpcenv->get_user();
408
409 my $node = extract_param($param, 'node');
410 my $vmid = extract_param($param, 'vmid');
411
412 die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
413
414
415
416 my $lockcmd = sub {
417 my $realcmd = sub {
418 my $upid = shift;
419
420 syslog('info', "suspend CT $vmid: $upid\n");
421
422 my $conf = PVE::LXC::Config->load_config($vmid);
423
424 PVE::LXC::Config->check_lock($conf);
425
426 my $cmd = ['lxc-checkpoint', '-n', $vmid, '-s', '-D', '/var/lib/vz/dump'];
427
428 run_command($cmd);
429
430 return;
431 };
432
433 return $rpcenv->fork_worker('vzsuspend', $vmid, $authuser, $realcmd);
434 };
435
436 return PVE::LXC::Config->lock_config($vmid, $lockcmd);
437 }});
438
439 __PACKAGE__->register_method({
440 name => 'vm_resume',
441 path => 'resume',
442 method => 'POST',
443 protected => 1,
444 proxyto => 'node',
445 description => "Resume the container.",
446 permissions => {
447 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
448 },
449 parameters => {
450 additionalProperties => 0,
451 properties => {
452 node => get_standard_option('pve-node'),
453 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_stopped }),
454 },
455 },
456 returns => {
457 type => 'string',
458 },
459 code => sub {
460 my ($param) = @_;
461
462 my $rpcenv = PVE::RPCEnvironment::get();
463 my $authuser = $rpcenv->get_user();
464
465 my $node = extract_param($param, 'node');
466 my $vmid = extract_param($param, 'vmid');
467
468 die "CT $vmid already running\n" if PVE::LXC::check_running($vmid);
469
470
471 my $realcmd = sub {
472 my $upid = shift;
473
474 syslog('info', "resume CT $vmid: $upid\n");
475
476 my $cmd = ['lxc-checkpoint', '-n', $vmid, '-r', '--foreground',
477 '-D', '/var/lib/vz/dump'];
478
479 run_command($cmd);
480
481 return;
482 };
483
484 my $upid = $rpcenv->fork_worker('vzresume', $vmid, $authuser, $realcmd);
485
486 return $upid;
487 }});
488
489 1;