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