]>
Commit | Line | Data |
---|---|---|
ac27b58d DM |
1 | package PVE::API2::Backup; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
52878b0a | 5 | use Digest::SHA; |
ac27b58d DM |
6 | |
7 | use PVE::SafeSyslog; | |
8 | use PVE::Tools qw(extract_param); | |
2424074e | 9 | use PVE::Cluster qw(cfs_lock_file cfs_read_file cfs_write_file); |
ac27b58d DM |
10 | use PVE::RESTHandler; |
11 | use PVE::RPCEnvironment; | |
12 | use PVE::JSONSchema; | |
13 | use PVE::Storage; | |
14 | use PVE::Exception qw(raise_param_exc); | |
15 | use PVE::VZDump; | |
2424074e | 16 | use PVE::VZDump::Common; |
ac27b58d DM |
17 | |
18 | use base qw(PVE::RESTHandler); | |
19 | ||
ac27b58d DM |
20 | PVE::JSONSchema::register_format('pve-day-of-week', \&verify_day_of_week); |
21 | sub verify_day_of_week { | |
22 | my ($value, $noerr) = @_; | |
23 | ||
24 | return $value if $value =~ m/^(mon|tue|wed|thu|fri|sat|sun)$/; | |
25 | ||
26 | return undef if $noerr; | |
27 | ||
28 | die "invalid day '$value'\n"; | |
29 | } | |
30 | ||
43b2494b SR |
31 | my $vzdump_job_id_prop = { |
32 | type => 'string', | |
33 | description => "The job ID.", | |
34 | maxLength => 50 | |
35 | }; | |
ac27b58d | 36 | |
2617768f TL |
37 | my $assert_param_permission = sub { |
38 | my ($param, $user) = @_; | |
39 | return if $user eq 'root@pam'; # always OK | |
40 | ||
41 | for my $key (qw(tmpdir dumpdir script)) { | |
42 | raise_param_exc({ $key => "Only root may set this option."}) if exists $param->{$key}; | |
43 | } | |
44 | }; | |
45 | ||
ac27b58d | 46 | __PACKAGE__->register_method({ |
60e049c2 TM |
47 | name => 'index', |
48 | path => '', | |
ac27b58d DM |
49 | method => 'GET', |
50 | description => "List vzdump backup schedule.", | |
937515d6 DM |
51 | permissions => { |
52 | check => ['perm', '/', ['Sys.Audit']], | |
53 | }, | |
ac27b58d DM |
54 | parameters => { |
55 | additionalProperties => 0, | |
56 | properties => {}, | |
57 | }, | |
58 | returns => { | |
59 | type => 'array', | |
60 | items => { | |
61 | type => "object", | |
62 | properties => { | |
43b2494b | 63 | id => $vzdump_job_id_prop |
ac27b58d DM |
64 | }, |
65 | }, | |
66 | links => [ { rel => 'child', href => "{id}" } ], | |
67 | }, | |
68 | code => sub { | |
69 | my ($param) = @_; | |
70 | ||
71 | my $rpcenv = PVE::RPCEnvironment::get(); | |
72 | my $user = $rpcenv->get_user(); | |
73 | ||
b0905e3a | 74 | my $data = cfs_read_file('vzdump.cron'); |
ac27b58d DM |
75 | |
76 | my $res = $data->{jobs} || []; | |
77 | ||
78 | return $res; | |
79 | }}); | |
80 | ||
81 | __PACKAGE__->register_method({ | |
60e049c2 TM |
82 | name => 'create_job', |
83 | path => '', | |
ac27b58d DM |
84 | method => 'POST', |
85 | protected => 1, | |
86 | description => "Create new vzdump backup job.", | |
937515d6 DM |
87 | permissions => { |
88 | check => ['perm', '/', ['Sys.Modify']], | |
f0bbc084 | 89 | description => "The 'tmpdir', 'dumpdir' and 'script' parameters are additionally restricted to the 'root\@pam' user.", |
937515d6 | 90 | }, |
ac27b58d DM |
91 | parameters => { |
92 | additionalProperties => 0, | |
2424074e | 93 | properties => PVE::VZDump::Common::json_config_properties({ |
7625ea19 DM |
94 | starttime => { |
95 | type => 'string', | |
96 | description => "Job Start time.", | |
97 | pattern => '\d{1,2}:\d{1,2}', | |
98 | typetext => 'HH:MM', | |
ac27b58d DM |
99 | }, |
100 | dow => { | |
101 | type => 'string', format => 'pve-day-of-week-list', | |
102 | optional => 1, | |
103 | description => "Day of week selection.", | |
104 | default => 'mon,tue,wed,thu,fri,sat,sun', | |
105 | }, | |
4341db1d TL |
106 | enabled => { |
107 | type => 'boolean', | |
108 | optional => 1, | |
109 | description => "Enable or disable the job.", | |
110 | default => '1', | |
111 | }, | |
ac27b58d DM |
112 | }), |
113 | }, | |
114 | returns => { type => 'null' }, | |
115 | code => sub { | |
116 | my ($param) = @_; | |
117 | ||
118 | my $rpcenv = PVE::RPCEnvironment::get(); | |
119 | my $user = $rpcenv->get_user(); | |
120 | ||
2617768f | 121 | $assert_param_permission->($param, $user); |
f0bbc084 | 122 | |
c92c54d5 TL |
123 | if (my $pool = $param->{pool}) { |
124 | $rpcenv->check_pool_exist($pool); | |
125 | $rpcenv->check($user, "/pool/$pool", ['VM.Backup']); | |
126 | } | |
127 | ||
128 | ||
200cef80 CE |
129 | my $create_job = sub { |
130 | my $data = cfs_read_file('vzdump.cron'); | |
ac27b58d | 131 | |
200cef80 CE |
132 | $param->{dow} = 'mon,tue,wed,thu,fri,sat,sun' if !defined($param->{dow}); |
133 | $param->{enabled} = 1 if !defined($param->{enabled}); | |
134 | PVE::VZDump::verify_vzdump_parameters($param, 1); | |
ac27b58d | 135 | |
200cef80 | 136 | push @{$data->{jobs}}, $param; |
ac27b58d | 137 | |
200cef80 CE |
138 | cfs_write_file('vzdump.cron', $data); |
139 | }; | |
140 | cfs_lock_file('vzdump.cron', undef, $create_job); | |
141 | die "$@" if ($@); | |
ac27b58d DM |
142 | |
143 | return undef; | |
144 | }}); | |
145 | ||
146 | __PACKAGE__->register_method({ | |
60e049c2 TM |
147 | name => 'read_job', |
148 | path => '{id}', | |
ac27b58d DM |
149 | method => 'GET', |
150 | description => "Read vzdump backup job definition.", | |
937515d6 DM |
151 | permissions => { |
152 | check => ['perm', '/', ['Sys.Audit']], | |
153 | }, | |
ac27b58d DM |
154 | parameters => { |
155 | additionalProperties => 0, | |
156 | properties => { | |
43b2494b | 157 | id => $vzdump_job_id_prop |
ac27b58d DM |
158 | }, |
159 | }, | |
160 | returns => { | |
161 | type => 'object', | |
162 | }, | |
163 | code => sub { | |
164 | my ($param) = @_; | |
165 | ||
166 | my $rpcenv = PVE::RPCEnvironment::get(); | |
167 | my $user = $rpcenv->get_user(); | |
168 | ||
b0905e3a | 169 | my $data = cfs_read_file('vzdump.cron'); |
ac27b58d DM |
170 | |
171 | my $jobs = $data->{jobs} || []; | |
172 | ||
173 | foreach my $job (@$jobs) { | |
174 | return $job if $job->{id} eq $param->{id}; | |
175 | } | |
176 | ||
177 | raise_param_exc({ id => "No such job '$param->{id}'" }); | |
178 | ||
179 | }}); | |
180 | ||
181 | __PACKAGE__->register_method({ | |
60e049c2 TM |
182 | name => 'delete_job', |
183 | path => '{id}', | |
ac27b58d DM |
184 | method => 'DELETE', |
185 | description => "Delete vzdump backup job definition.", | |
937515d6 DM |
186 | permissions => { |
187 | check => ['perm', '/', ['Sys.Modify']], | |
188 | }, | |
ac27b58d DM |
189 | protected => 1, |
190 | parameters => { | |
191 | additionalProperties => 0, | |
192 | properties => { | |
43b2494b | 193 | id => $vzdump_job_id_prop |
ac27b58d DM |
194 | }, |
195 | }, | |
196 | returns => { type => 'null' }, | |
197 | code => sub { | |
198 | my ($param) = @_; | |
199 | ||
200 | my $rpcenv = PVE::RPCEnvironment::get(); | |
201 | my $user = $rpcenv->get_user(); | |
202 | ||
200cef80 CE |
203 | my $delete_job = sub { |
204 | my $data = cfs_read_file('vzdump.cron'); | |
ac27b58d | 205 | |
200cef80 CE |
206 | my $jobs = $data->{jobs} || []; |
207 | my $newjobs = []; | |
ac27b58d | 208 | |
200cef80 CE |
209 | my $found; |
210 | foreach my $job (@$jobs) { | |
211 | if ($job->{id} eq $param->{id}) { | |
212 | $found = 1; | |
213 | } else { | |
214 | push @$newjobs, $job; | |
215 | } | |
ac27b58d | 216 | } |
ac27b58d | 217 | |
200cef80 | 218 | raise_param_exc({ id => "No such job '$param->{id}'" }) if !$found; |
ac27b58d | 219 | |
200cef80 | 220 | $data->{jobs} = $newjobs; |
ac27b58d | 221 | |
200cef80 CE |
222 | cfs_write_file('vzdump.cron', $data); |
223 | }; | |
224 | cfs_lock_file('vzdump.cron', undef, $delete_job); | |
225 | die "$@" if ($@); | |
ac27b58d DM |
226 | |
227 | return undef; | |
228 | }}); | |
229 | ||
230 | __PACKAGE__->register_method({ | |
60e049c2 TM |
231 | name => 'update_job', |
232 | path => '{id}', | |
ac27b58d DM |
233 | method => 'PUT', |
234 | protected => 1, | |
235 | description => "Update vzdump backup job definition.", | |
937515d6 DM |
236 | permissions => { |
237 | check => ['perm', '/', ['Sys.Modify']], | |
e6d963ca | 238 | description => "The 'tmpdir', 'dumpdir' and 'script' parameters are additionally restricted to the 'root\@pam' user.", |
937515d6 | 239 | }, |
ac27b58d DM |
240 | parameters => { |
241 | additionalProperties => 0, | |
2424074e | 242 | properties => PVE::VZDump::Common::json_config_properties({ |
43b2494b | 243 | id => $vzdump_job_id_prop, |
7625ea19 DM |
244 | starttime => { |
245 | type => 'string', | |
246 | description => "Job Start time.", | |
247 | pattern => '\d{1,2}:\d{1,2}', | |
248 | typetext => 'HH:MM', | |
ac27b58d DM |
249 | }, |
250 | dow => { | |
251 | type => 'string', format => 'pve-day-of-week-list', | |
252 | optional => 1, | |
253 | description => "Day of week selection.", | |
254 | }, | |
53c6bb6c DM |
255 | delete => { |
256 | type => 'string', format => 'pve-configid-list', | |
257 | description => "A list of settings you want to delete.", | |
258 | optional => 1, | |
259 | }, | |
4341db1d TL |
260 | enabled => { |
261 | type => 'boolean', | |
262 | optional => 1, | |
263 | description => "Enable or disable the job.", | |
264 | default => '1', | |
265 | }, | |
ac27b58d DM |
266 | }), |
267 | }, | |
268 | returns => { type => 'null' }, | |
269 | code => sub { | |
270 | my ($param) = @_; | |
271 | ||
272 | my $rpcenv = PVE::RPCEnvironment::get(); | |
273 | my $user = $rpcenv->get_user(); | |
274 | ||
2617768f | 275 | $assert_param_permission->($param, $user); |
d5b9f2e1 | 276 | |
16f5b283 TL |
277 | if (my $pool = $param->{pool}) { |
278 | $rpcenv->check_pool_exist($pool); | |
279 | $rpcenv->check($user, "/pool/$pool", ['VM.Backup']); | |
280 | } | |
281 | ||
200cef80 CE |
282 | my $update_job = sub { |
283 | my $data = cfs_read_file('vzdump.cron'); | |
ac27b58d | 284 | |
200cef80 | 285 | my $jobs = $data->{jobs} || []; |
ac27b58d | 286 | |
200cef80 | 287 | die "no options specified\n" if !scalar(keys %$param); |
53c6bb6c | 288 | |
200cef80 | 289 | PVE::VZDump::verify_vzdump_parameters($param); |
ac27b58d | 290 | |
200cef80 | 291 | my @delete = PVE::Tools::split_list(extract_param($param, 'delete')); |
53c6bb6c | 292 | |
200cef80 CE |
293 | foreach my $job (@$jobs) { |
294 | if ($job->{id} eq $param->{id}) { | |
ac27b58d | 295 | |
200cef80 CE |
296 | foreach my $k (@delete) { |
297 | if (!PVE::VZDump::option_exists($k)) { | |
298 | raise_param_exc({ delete => "unknown option '$k'" }); | |
299 | } | |
53c6bb6c | 300 | |
200cef80 CE |
301 | delete $job->{$k}; |
302 | } | |
53c6bb6c | 303 | |
200cef80 CE |
304 | foreach my $k (keys %$param) { |
305 | $job->{$k} = $param->{$k}; | |
306 | } | |
ac27b58d | 307 | |
f3376261 | 308 | $job->{all} = 1 if (defined($job->{exclude}) && !defined($job->{pool})); |
ac27b58d | 309 | |
200cef80 CE |
310 | if (defined($param->{vmid})) { |
311 | delete $job->{all}; | |
312 | delete $job->{exclude}; | |
f3376261 | 313 | delete $job->{pool}; |
200cef80 CE |
314 | } elsif ($param->{all}) { |
315 | delete $job->{vmid}; | |
f3376261 TM |
316 | delete $job->{pool}; |
317 | } elsif ($job->{pool}) { | |
318 | delete $job->{vmid}; | |
319 | delete $job->{all}; | |
b05c9908 | 320 | delete $job->{exclude}; |
200cef80 | 321 | } |
ac27b58d | 322 | |
200cef80 | 323 | PVE::VZDump::verify_vzdump_parameters($job, 1); |
ac27b58d | 324 | |
200cef80 | 325 | cfs_write_file('vzdump.cron', $data); |
ac27b58d | 326 | |
200cef80 CE |
327 | return undef; |
328 | } | |
ac27b58d | 329 | } |
200cef80 CE |
330 | raise_param_exc({ id => "No such job '$param->{id}'" }); |
331 | }; | |
332 | cfs_lock_file('vzdump.cron', undef, $update_job); | |
333 | die "$@" if ($@); | |
ac27b58d DM |
334 | }}); |
335 | ||
336 | 1; |