]> git.proxmox.com Git - pve-container.git/blob - src/PVE/API2/LXC/Status.pm
check for quorum when starting a container
[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::HA::Config;
19 use PVE::JSONSchema qw(get_standard_option);
20 use base qw(PVE::RESTHandler);
21
22 use 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', { completion => \&PVE::LXC::complete_ctid_stopped }),
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 PVE::Cluster::check_cfs_quorum();
133
134 if (PVE::HA::Config::vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
135
136 my $hacmd = sub {
137 my $upid = shift;
138
139 my $service = "ct:$vmid";
140
141 my $cmd = ['ha-manager', 'enable', $service];
142
143 print "Executing HA start for CT $vmid\n";
144
145 PVE::Tools::run_command($cmd);
146
147 return;
148 };
149
150 return $rpcenv->fork_worker('hastart', $vmid, $authuser, $hacmd);
151
152 } else {
153
154 my $realcmd = sub {
155 my $upid = shift;
156
157 syslog('info', "starting CT $vmid: $upid\n");
158
159 my $conf = PVE::LXC::load_config($vmid);
160
161 die "you can't start a CT if it's a template\n"
162 if PVE::LXC::is_template($conf);
163
164 my $storage_cfg = cfs_read_file("storage.cfg");
165
166 PVE::LXC::update_lxc_config($storage_cfg, $vmid, $conf);
167
168 my $cmd = ['lxc-start', '-n', $vmid];
169
170 run_command($cmd);
171
172 return;
173 };
174
175 return $rpcenv->fork_worker('vzstart', $vmid, $authuser, $realcmd);
176 }
177 }});
178
179 __PACKAGE__->register_method({
180 name => 'vm_stop',
181 path => 'stop',
182 method => 'POST',
183 protected => 1,
184 proxyto => 'node',
185 description => "Stop the container.",
186 permissions => {
187 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
188 },
189 parameters => {
190 additionalProperties => 0,
191 properties => {
192 node => get_standard_option('pve-node'),
193 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_running }),
194 },
195 },
196 returns => {
197 type => 'string',
198 },
199 code => sub {
200 my ($param) = @_;
201
202 my $rpcenv = PVE::RPCEnvironment::get();
203
204 my $authuser = $rpcenv->get_user();
205
206 my $node = extract_param($param, 'node');
207
208 my $vmid = extract_param($param, 'vmid');
209
210 die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
211
212 if (PVE::HA::Config::vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
213
214 my $hacmd = sub {
215 my $upid = shift;
216
217 my $service = "ct:$vmid";
218
219 my $cmd = ['ha-manager', 'disable', $service];
220
221 print "Executing HA stop for CT $vmid\n";
222
223 PVE::Tools::run_command($cmd);
224
225 return;
226 };
227
228 return $rpcenv->fork_worker('hastop', $vmid, $authuser, $hacmd);
229
230 } else {
231
232 my $realcmd = sub {
233 my $upid = shift;
234
235 syslog('info', "stopping CT $vmid: $upid\n");
236
237 my $cmd = ['lxc-stop', '-n', $vmid, '--kill'];
238
239 run_command($cmd);
240
241 return;
242 };
243
244 return $rpcenv->fork_worker('vzstop', $vmid, $authuser, $realcmd);
245 }
246 }});
247
248 __PACKAGE__->register_method({
249 name => 'vm_shutdown',
250 path => 'shutdown',
251 method => 'POST',
252 protected => 1,
253 proxyto => 'node',
254 description => "Shutdown the container.",
255 permissions => {
256 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
257 },
258 parameters => {
259 additionalProperties => 0,
260 properties => {
261 node => get_standard_option('pve-node'),
262 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_running }),
263 timeout => {
264 description => "Wait maximal timeout seconds.",
265 type => 'integer',
266 minimum => 0,
267 optional => 1,
268 default => 60,
269 },
270 forceStop => {
271 description => "Make sure the Container stops.",
272 type => 'boolean',
273 optional => 1,
274 default => 0,
275 }
276 },
277 },
278 returns => {
279 type => 'string',
280 },
281 code => sub {
282 my ($param) = @_;
283
284 my $rpcenv = PVE::RPCEnvironment::get();
285
286 my $authuser = $rpcenv->get_user();
287
288 my $node = extract_param($param, 'node');
289
290 my $vmid = extract_param($param, 'vmid');
291
292 my $timeout = extract_param($param, 'timeout');
293
294 die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
295
296 my $realcmd = sub {
297 my $upid = shift;
298
299 syslog('info', "shutdown CT $vmid: $upid\n");
300
301 my $cmd = ['lxc-stop', '-n', $vmid];
302
303 $timeout = 60 if !defined($timeout);
304
305 my $conf = PVE::LXC::load_config($vmid);
306
307 my $storage_cfg = PVE::Storage::config();
308
309 push @$cmd, '--timeout', $timeout;
310
311 eval { run_command($cmd, timeout => $timeout+5); };
312 my $err = $@;
313 if ($err && $param->{forceStop}) {
314 $err = undef;
315 warn "shutdown failed - forcing stop now\n";
316
317 my $cmd = ['lxc-stop', '-n', $vmid, '--kill'];
318 run_command($cmd);
319 }
320
321 # make sure container is stopped
322 $cmd = ['lxc-wait', '-n', $vmid, '-t', 5, '-s', 'STOPPED'];
323 run_command($cmd);
324
325 die $err if $err;
326
327 return;
328 };
329
330 my $upid = $rpcenv->fork_worker('vzshutdown', $vmid, $authuser, $realcmd);
331
332 return $upid;
333 }});
334
335 __PACKAGE__->register_method({
336 name => 'vm_suspend',
337 path => 'suspend',
338 method => 'POST',
339 protected => 1,
340 proxyto => 'node',
341 description => "Suspend the container.",
342 permissions => {
343 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
344 },
345 parameters => {
346 additionalProperties => 0,
347 properties => {
348 node => get_standard_option('pve-node'),
349 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_running }),
350 },
351 },
352 returns => {
353 type => 'string',
354 },
355 code => sub {
356 my ($param) = @_;
357
358 my $rpcenv = PVE::RPCEnvironment::get();
359
360 my $authuser = $rpcenv->get_user();
361
362 my $node = extract_param($param, 'node');
363
364 my $vmid = extract_param($param, 'vmid');
365
366 die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
367
368 my $realcmd = sub {
369 my $upid = shift;
370
371 syslog('info', "suspend CT $vmid: $upid\n");
372
373 my $cmd = ['lxc-checkpoint', '-n', $vmid, '-s', '-D', '/var/liv/vz/dump'];
374
375 run_command($cmd);
376
377 return;
378 };
379
380 my $upid = $rpcenv->fork_worker('vzsuspend', $vmid, $authuser, $realcmd);
381
382 return $upid;
383 }});
384
385 __PACKAGE__->register_method({
386 name => 'vm_resume',
387 path => 'resume',
388 method => 'POST',
389 protected => 1,
390 proxyto => 'node',
391 description => "Resume the container.",
392 permissions => {
393 check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
394 },
395 parameters => {
396 additionalProperties => 0,
397 properties => {
398 node => get_standard_option('pve-node'),
399 vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_stopped }),
400 },
401 },
402 returns => {
403 type => 'string',
404 },
405 code => sub {
406 my ($param) = @_;
407
408 my $rpcenv = PVE::RPCEnvironment::get();
409
410 my $authuser = $rpcenv->get_user();
411
412 my $node = extract_param($param, 'node');
413
414 my $vmid = extract_param($param, 'vmid');
415
416 die "CT $vmid already running\n" if PVE::LXC::check_running($vmid);
417
418 my $realcmd = sub {
419 my $upid = shift;
420
421 syslog('info', "resume CT $vmid: $upid\n");
422
423 my $cmd = ['lxc-checkpoint', '-n', $vmid, '-r', '--foreground',
424 '-D', '/var/liv/vz/dump'];
425
426 run_command($cmd);
427
428 return;
429 };
430
431 my $upid = $rpcenv->fork_worker('vzresume', $vmid, $authuser, $realcmd);
432
433 return $upid;
434 }});
435
436 1;