]> git.proxmox.com Git - pve-manager.git/blame - PVE/API2/VZDump.pm
bump version to 5.4-15
[pve-manager.git] / PVE / API2 / VZDump.pm
CommitLineData
bf58f8dd
DM
1package PVE::API2::VZDump;
2
3use strict;
4use warnings;
31aef761 5use PVE::Exception qw(raise_param_exc);
bf58f8dd
DM
6use PVE::Tools qw(extract_param);
7use PVE::Cluster qw(cfs_register_file cfs_read_file);
8use PVE::INotify;
9use PVE::RPCEnvironment;
10use PVE::AccessControl;
11use PVE::JSONSchema qw(get_standard_option);
12use PVE::Storage;
13use PVE::VZDump;
14
15use Data::Dumper; # fixme: remove
16
17
18use base qw(PVE::RESTHandler);
19
20__PACKAGE__->register_method ({
21 name => 'vzdump',
22 path => '',
23 method => 'POST',
24 description => "Create backup.",
98e84b16 25 permissions => {
eb2d6fd3 26 description => "The user needs 'VM.Backup' permissions on any VM, and 'Datastore.AllocateSpace' on the backup storage. The 'maxfiles', 'tmpdir', 'dumpdir', 'script', 'bwlimit' and 'ionice' parameters are restricted to the 'root\@pam' user.",
98e84b16
DM
27 user => 'all',
28 },
30edfad9 29 protected => 1,
49046e53 30 proxyto => 'node',
bf58f8dd
DM
31 parameters => {
32 additionalProperties => 0,
ac27b58d 33 properties => PVE::VZDump::json_config_properties({
bf58f8dd
DM
34 stdout => {
35 type => 'boolean',
36 description => "Write tar to stdout, not to a file.",
37 optional => 1,
38 },
ac27b58d 39 }),
bf58f8dd
DM
40 },
41 returns => { type => 'string' },
42 code => sub {
43 my ($param) = @_;
44
45 my $rpcenv = PVE::RPCEnvironment::get();
46
47 my $user = $rpcenv->get_user();
48
49 my $nodename = PVE::INotify::nodename();
50
51 if ($rpcenv->{type} ne 'cli') {
52 raise_param_exc({ node => "option is only allowed on the command line interface."})
53 if $param->{node} && $param->{node} ne $nodename;
54
55 raise_param_exc({ stdout => "option is only allowed on the command line interface."})
56 if $param->{stdout};
57 }
58
6d0507a8
FG
59 foreach my $key (qw(maxfiles tmpdir dumpdir script bwlimit ionice)) {
60 raise_param_exc({ $key => "Only root may set this option."})
61 if defined($param->{$key}) && ($user ne 'root@pam');
62 }
63
bf58f8dd
DM
64 # by default we set --rsyncable for gzip
65 local $ENV{GZIP} = "--rsyncable" if !$ENV{GZIP};
66
31aef761 67 PVE::VZDump::verify_vzdump_parameters($param, 1);
bf58f8dd
DM
68
69 # silent exit if we run on wrong node
eab837c4 70 return 'OK' if $param->{node} && $param->{node} ne $nodename;
8682f6fc 71
31aef761
DM
72 my $cmdline = PVE::VZDump::command_line($param);
73
bf58f8dd
DM
74 # convert string lists to arrays
75 my @vmids = PVE::Tools::split_list(extract_param($param, 'vmid'));
76
eab837c4
DM
77 if($param->{stop}){
78 PVE::VZDump::stop_running_backups();
79 return 'OK' if !scalar(@vmids);
80 }
81
a7e42354
DM
82 my $skiplist = [];
83 if (!$param->{all}) {
84 if (!$param->{node}) {
85 my $vmlist = PVE::Cluster::get_vmlist();
86 my @localvmids = ();
87 foreach my $vmid (@vmids) {
88 my $d = $vmlist->{ids}->{$vmid};
89 if ($d && ($d->{node} ne $nodename)) {
90 push @$skiplist, $vmid;
91 } else {
92 push @localvmids, $vmid;
93 }
94 }
95 @vmids = @localvmids;
96 # silent exit if specified VMs run on other nodes
eab837c4 97 return "OK" if !scalar(@vmids);
a7e42354
DM
98 }
99
100 $param->{vmids} = PVE::VZDump::check_vmids(@vmids)
101 }
102
bf58f8dd
DM
103 my @exclude = PVE::Tools::split_list(extract_param($param, 'exclude'));
104 $param->{exclude} = PVE::VZDump::check_vmids(@exclude);
336ec53a 105
bf58f8dd 106 # exclude-path list need to be 0 separated
336ec53a
DM
107 if (defined($param->{'exclude-path'})) {
108 my @expaths = split(/\0/, $param->{'exclude-path'} || '');
109 $param->{'exclude-path'} = [ @expaths ];
110 }
bf58f8dd 111
336ec53a
DM
112 if (defined($param->{mailto})) {
113 my @mailto = PVE::Tools::split_list(extract_param($param, 'mailto'));
114 $param->{mailto} = [ @mailto ];
115 }
bf58f8dd
DM
116
117 die "you can only backup a single VM with option --stdout\n"
118 if $param->{stdout} && scalar(@vmids) != 1;
119
4412265f
DM
120 $rpcenv->check($user, "/storage/$param->{storage}", [ 'Datastore.AllocateSpace' ])
121 if $param->{storage};
122
bf58f8dd 123 my $worker = sub {
eab837c4
DM
124 my $upid = shift;
125
bf58f8dd
DM
126 $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
127 die "interrupted by signal\n";
128 };
129
403761c4
WB
130 my $vzdump = PVE::VZDump->new($cmdline, $param, $skiplist);
131
6ec9de44 132 eval {
eab837c4 133 $vzdump->getlock($upid); # only one process allowed
6ec9de44 134 };
eab837c4
DM
135 if (my $err = $@) {
136 $vzdump->sendmail([], 0, $err);
6ec9de44
SP
137 exit(-1);
138 }
bf58f8dd
DM
139
140 if (defined($param->{ionice})) {
141 if ($param->{ionice} > 7) {
142 PVE::VZDump::run_command(undef, "ionice -c3 -p $$");
143 } else {
144 PVE::VZDump::run_command(undef, "ionice -c2 -n$param->{ionice} -p $$");
145 }
146 }
98e84b16 147 $vzdump->exec_backup($rpcenv, $user);
bf58f8dd
DM
148 };
149
150 open STDOUT, '>/dev/null' if $param->{quiet} && !$param->{stdout};
151 open STDERR, '>/dev/null' if $param->{quiet};
152
153 if ($rpcenv->{type} eq 'cli') {
154 if ($param->{stdout}) {
155
156 open my $saved_stdout, ">&STDOUT"
157 || die "can't dup STDOUT: $!\n";
158
159 open STDOUT, '>&STDERR' ||
160 die "unable to redirect STDOUT: $!\n";
161
162 $param->{stdout} = $saved_stdout;
163 }
164 }
165
742d2ad2
FG
166 my $taskid;
167 $taskid = $vmids[0] if scalar(@vmids) == 1;
168
169 return $rpcenv->fork_worker('vzdump', $taskid, $user, $worker);
bf58f8dd 170 }});
7619e4dd
FG
171
172__PACKAGE__->register_method ({
173 name => 'extractconfig',
174 path => 'extractconfig',
175 method => 'GET',
176 description => "Extract configuration from vzdump backup archive.",
177 permissions => {
178 description => "The user needs 'VM.Backup' permissions on the backed up guest ID, and 'Datastore.AllocateSpace' on the backup storage.",
179 user => 'all',
180 },
181 protected => 1,
182 proxyto => 'node',
183 parameters => {
184 additionalProperties => 0,
185 properties => {
186 node => get_standard_option('pve-node'),
187 volume => {
188 description => "Volume identifier",
189 type => 'string',
190 completion => \&PVE::Storage::complete_volume,
191 },
192 },
193 },
194 returns => { type => 'string' },
195 code => sub {
196 my ($param) = @_;
197
198 my $volume = extract_param($param, 'volume');
199
200 my $rpcenv = PVE::RPCEnvironment::get();
201 my $authuser = $rpcenv->get_user();
202
203 my $storage_cfg = PVE::Storage::config();
989f3c7e 204 PVE::Storage::check_volume_access($rpcenv, $authuser, $storage_cfg, undef, $volume);
7619e4dd
FG
205
206 return PVE::Storage::extract_vzdump_config($storage_cfg, $volume);
207 }});
208
2091;