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