]>
git.proxmox.com Git - pmg-api.git/blob - src/PMG/API2/PBS/Job.pm
1 package PMG
::API2
::PBS
::Job
;
6 use POSIX
qw(strftime);
8 use PVE
::JSONSchema
qw(get_standard_option);
11 use PVE
::Tools
qw(extract_param);
14 use PMG
::RESTEnvironment
;
19 use base
qw(PVE::RESTHandler);
21 __PACKAGE__-
>register_method ({
25 description
=> "List all configured Proxmox Backup Server jobs.",
26 permissions
=> { check
=> [ 'admin', 'audit' ] },
30 additionalProperties
=> 0,
32 node
=> get_standard_option
('pve-node'),
37 items
=> PMG
::PBSConfig-
>createSchema(1),
38 links
=> [ { rel
=> 'child', href
=> "{remote}" } ],
45 my $conf = PMG
::PBSConfig-
>new();
46 return $res if !defined($conf);
48 foreach my $remote (keys %{$conf->{ids
}}) {
49 my $d = $conf->{ids
}->{$remote};
52 server
=> $d->{server
},
53 datastore
=> $d->{datastore
},
60 __PACKAGE__-
>register_method ({
61 name
=> 'remote_index',
64 description
=> "Backup Job index.",
66 additionalProperties
=> 0,
68 node
=> get_standard_option
('pve-node'),
70 description
=> "Proxmox Backup Server ID.",
71 type
=> 'string', format
=> 'pve-configid',
79 properties
=> { section
=> { type
=> 'string'} },
81 links
=> [ { rel
=> 'child', href
=> "{section}" } ],
87 { section
=> 'snapshots' },
88 { section
=> 'backup' },
89 { section
=> 'restore' },
90 { section
=> 'timer' },
95 __PACKAGE__-
>register_method ({
96 name
=> 'get_snapshots',
97 path
=> '{remote}/snapshots',
99 description
=> "Get snapshots stored on remote.",
102 permissions
=> { check
=> [ 'admin', 'audit' ] },
104 additionalProperties
=> 0,
106 node
=> get_standard_option
('pve-node'),
108 description
=> "Proxmox Backup Server ID.",
109 type
=> 'string', format
=> 'pve-configid',
118 time => { type
=> 'string'},
119 ctime
=> { type
=> 'string'},
120 size
=> { type
=> 'integer'},
123 links
=> [ { rel
=> 'child', href
=> "{time}" } ],
128 my $remote = $param->{remote
};
129 my $node = $param->{node
};
131 my $conf = PMG
::PBSConfig-
>new();
133 my $remote_config = $conf->{ids
}->{$remote};
134 die "PBS remote '$remote' does not exist\n" if !$remote_config;
137 return $res if $remote_config->{disable
};
139 my $pbs = PVE
::PBSClient-
>new($remote_config, $remote, $conf->{secret_dir
});
141 my $snapshots = $pbs->get_snapshots("host/$node");
142 foreach my $item (@$snapshots) {
143 my ($type, $id, $time) = $item->@{qw(backup-type backup-id backup-time)};
144 next if $type ne 'host' || $id ne $node;
146 my @pxar = grep { $_->{filename
} eq 'pmgbackup.pxar.didx' } @{$item->{files
}};
147 die "unexpected number of pmgbackup archives in snapshot\n" if (scalar(@pxar) != 1);
149 my $time_rfc3339 = strftime
("%FT%TZ", gmtime($time));
152 time => $time_rfc3339,
154 size
=> $item->{size
} // 1,
161 __PACKAGE__-
>register_method ({
162 name
=> 'forget_snapshot',
163 path
=> '{remote}/snapshots/{time}',
165 description
=> "Forget a snapshot",
168 permissions
=> { check
=> [ 'admin', 'audit' ] },
170 additionalProperties
=> 0,
172 node
=> get_standard_option
('pve-node'),
174 description
=> "Proxmox Backup Server ID.",
175 type
=> 'string', format
=> 'pve-configid',
178 description
=> "Backup time in RFC 3339 format",
183 returns
=> {type
=> 'null' },
187 my $remote = $param->{remote
};
188 my $node = $param->{node
};
189 my $time = $param->{time};
191 my $snapshot = "host/$node/$time";
193 my $conf = PMG
::PBSConfig-
>new();
195 my $remote_config = $conf->{ids
}->{$remote};
196 die "PBS remote '$remote' does not exist\n" if !$remote_config;
197 die "PBS remote '$remote' is disabled\n" if $remote_config->{disable
};
199 my $pbs = PVE
::PBSClient-
>new($remote_config, $remote, $conf->{secret_dir
});
201 eval { $pbs->forget_snapshot($snapshot) };
202 die "Forgetting backup failed: $@" if $@;
208 __PACKAGE__-
>register_method ({
209 name
=> 'run_backup',
210 path
=> '{remote}/backup',
212 description
=> "run backup and prune the backupgroup afterwards.",
215 permissions
=> { check
=> [ 'admin', 'audit' ] },
217 additionalProperties
=> 0,
219 node
=> get_standard_option
('pve-node'),
221 description
=> "Proxmox Backup Server ID.",
222 type
=> 'string', format
=> 'pve-configid',
226 returns
=> { type
=> "string" },
230 my $rpcenv = PMG
::RESTEnvironment-
>get();
231 my $authuser = $rpcenv->get_user();
233 my $remote = $param->{remote
};
234 my $node = $param->{node
};
236 my $conf = PMG
::PBSConfig-
>new();
238 my $remote_config = $conf->{ids
}->{$remote};
239 die "PBS remote '$remote' does not exist\n" if !$remote_config;
240 die "PBS remote '$remote' is disabled\n" if $remote_config->{disable
};
242 my $pbs = PVE
::PBSClient-
>new($remote_config, $remote, $conf->{secret_dir
});
243 my $backup_dir = "/var/lib/pmg/backup/current";
248 print "starting update of current backup state\n";
250 -d
$backup_dir || mkdir $backup_dir;
251 PMG
::Backup
::pmg_backup
($backup_dir, $param->{statistic
});
253 $pbs->backup_fs_tree($backup_dir, $node, 'pmgbackup');
255 print "backup finished\n";
257 my $group = "host/$node";
258 if (defined(my $prune_opts = $conf->prune_options($remote))) {
259 print "starting prune of $group\n";
260 my $res = $pbs->prune_group(undef, $prune_opts, $group);
262 foreach my $pruned (@$res){
263 my $time = strftime
("%FT%TZ", gmtime($pruned->{'backup-time'}));
264 my $snap = $pruned->{'backup-type'} . '/' . $pruned->{'backup-id'} . '/' . $time;
265 print "pruned snapshot: $snap\n";
267 print "prune finished\n";
273 return $rpcenv->fork_worker('pbs_backup', undef, $authuser, $worker);
277 __PACKAGE__-
>register_method ({
279 path
=> '{remote}/restore',
281 description
=> "Restore the system configuration.",
282 permissions
=> { check
=> [ 'admin' ] },
286 additionalProperties
=> 0,
288 PMG
::Backup
::get_restore_options
(),
290 description
=> "Proxmox Backup Server ID.",
291 type
=> 'string', format
=> 'pve-configid',
293 'backup-time' => {description
=> "backup-time to restore",
294 optional
=> 1, type
=> 'string'
296 'backup-id' => {description
=> "backup-id (hostname) of backup snapshot",
297 optional
=> 1, type
=> 'string'
301 returns
=> { type
=> "string" },
305 my $rpcenv = PMG
::RESTEnvironment-
>get();
306 my $authuser = $rpcenv->get_user();
308 my $remote = $param->{remote
};
309 my $backup_id = $param->{'backup-id'} // $param->{node
};
310 my $snapshot = "host/$backup_id";
311 $snapshot .= "/$param->{'backup-time'}" if defined($param->{'backup-time'});
313 my $conf = PMG
::PBSConfig-
>new();
315 my $remote_config = $conf->{ids
}->{$remote};
316 die "PBS remote '$remote' does not exist\n" if !$remote_config;
317 die "PBS remote '$remote' is disabled\n" if $remote_config->{disable
};
319 my $pbs = PVE
::PBSClient-
>new($remote_config, $remote, $conf->{secret_dir
});
322 my $dirname = "/tmp/proxrestore_$$.$now";
324 $param->{database
} //= 1;
326 die "nothing selected - please select what you want to restore (config or database?)\n"
327 if !($param->{database
} || $param->{config
});
332 print "starting restore of $snapshot from $remote\n";
334 $pbs->restore_pxar($snapshot, 'pmgbackup', $dirname);
335 print "starting restore of PMG config\n";
336 PMG
::Backup
::pmg_restore
($dirname, $param->{database
},
337 $param->{config
}, $param->{statistic
});
338 print "restore finished\n";
343 return $rpcenv->fork_worker('pbs_restore', undef, $authuser, $worker);
346 __PACKAGE__-
>register_method ({
347 name
=> 'create_timer',
348 path
=> '{remote}/timer',
350 description
=> "Create backup schedule",
353 permissions
=> { check
=> [ 'admin', 'audit' ] },
355 additionalProperties
=> 0,
357 node
=> get_standard_option
('pve-node'),
359 description
=> "Proxmox Backup Server ID.",
360 type
=> 'string', format
=> 'pve-configid',
363 description
=> "Schedule for the backup (OnCalendar setting of the systemd.timer)",
364 type
=> 'string', pattern
=> '[0-9a-zA-Z*.:,\-/ ]+',
365 default => 'daily', optional
=> 1,
368 description
=> "Randomized delay to add to the starttime (RandomizedDelaySec setting of the systemd.timer)",
369 type
=> 'string', pattern
=> '[0-9a-zA-Z. ]+',
370 default => '5min', optional
=> 1,
374 returns
=> { type
=> 'null' },
378 my $remote = $param->{remote
};
379 my $schedule = $param->{schedule
} // 'daily';
380 my $delay = $param->{delay
} // '5min';
382 my $conf = PMG
::PBSConfig-
>new();
384 my $remote_config = $conf->{ids
}->{$remote};
385 die "PBS remote '$remote' does not exist\n" if !$remote_config;
386 die "PBS remote '$remote' is disabled\n" if $remote_config->{disable
};
388 PMG
::PBSSchedule
::create_schedule
($remote, $schedule, $delay);
392 __PACKAGE__-
>register_method ({
393 name
=> 'delete_timer',
394 path
=> '{remote}/timer',
396 description
=> "Delete backup schedule",
399 permissions
=> { check
=> [ 'admin', 'audit' ] },
401 additionalProperties
=> 0,
403 node
=> get_standard_option
('pve-node'),
405 description
=> "Proxmox Backup Server ID.",
406 type
=> 'string', format
=> 'pve-configid',
410 returns
=> { type
=> 'null' },
414 my $remote = $param->{remote
};
416 PMG
::PBSSchedule
::delete_schedule
($remote);
420 __PACKAGE__-
>register_method ({
421 name
=> 'list_timer',
422 path
=> '{remote}/timer',
424 description
=> "Get timer specification",
427 permissions
=> { check
=> [ 'admin', 'audit' ] },
429 additionalProperties
=> 0,
431 node
=> get_standard_option
('pve-node'),
433 description
=> "Proxmox Backup Server ID.",
434 type
=> 'string', format
=> 'pve-configid',
438 returns
=> { type
=> 'object', properties
=> {
440 description
=> "Proxmox Backup Server ID.",
441 type
=> 'string', format
=> 'pve-configid',
445 description
=> "Schedule for the backup (OnCalendar setting of the systemd.timer)",
446 type
=> 'string', pattern
=> '[0-9a-zA-Z*.:,\-/ ]+',
447 default => 'daily', optional
=> 1,
450 description
=> "Randomized delay to add to the starttime (RandomizedDelaySec setting of the systemd.timer)",
451 type
=> 'string', pattern
=> '[0-9a-zA-Z. ]+',
452 default => '5min', optional
=> 1,
455 description
=> "unit file for the systemd.timer unit",
456 type
=> 'string', optional
=> 1,
462 my $remote = $param->{remote
};
464 my $schedules = PMG
::PBSSchedule
::get_schedules
();
465 my @data = grep {$_->{remote
} eq $remote} @$schedules;
468 if (scalar(@data) == 1) {