]> git.proxmox.com Git - pmg-api.git/blob - src/PMG/PBSSchedule.pm
92de542e6d865c75c287ea9836e6926e1848ea33
[pmg-api.git] / src / PMG / PBSSchedule.pm
1 package PMG::PBSSchedule;
2
3 use strict;
4 use warnings;
5
6 use PVE::Tools qw(run_command file_set_contents file_get_contents trim dir_glob_foreach);
7 use PVE::Systemd;
8
9 # note: not exactly cheap...
10 my sub next_calendar_event {
11 my ($spec) = @_;
12
13 my $res = '-';
14 eval {
15 run_command(
16 ['systemd-analyze', 'calendar', $spec],
17 noerr => 1,
18 outfunc => sub {
19 my $line = shift;
20 if ($line =~ /^\s*Next elapse:\s*(.+)$/) {
21 $res = $1;
22 }
23 },
24 );
25 };
26 return $res;
27 }
28
29 # systemd timer, filter optionally by a $remote
30 sub get_schedules {
31 my ($filter_remote) = @_;
32
33 my $result = [];
34
35 my $systemd_dir = '/etc/systemd/system';
36
37 dir_glob_foreach($systemd_dir, '^pmg-pbsbackup@.+\.timer$', sub {
38 my ($filename) = @_;
39 my $remote;
40 if ($filename =~ /^pmg-pbsbackup\@(.+)\.timer$/) {
41 $remote = PVE::Systemd::unescape_unit($1);
42 } else {
43 die "Unrecognized timer name!\n";
44 }
45
46 if (defined($filter_remote) && $filter_remote ne $remote) {
47 return; # next
48 }
49
50 my $unitfile = "$systemd_dir/$filename";
51 my $unit = PVE::Systemd::read_ini($unitfile);
52 my $timer = $unit->{'Timer'};
53
54 push @$result, {
55 unitfile => $unitfile,
56 remote => $remote,
57 schedule => $timer->{'OnCalendar'},
58 delay => $timer->{'RandomizedDelaySec'},
59 'next-run' => next_calendar_event($timer->{'OnCalendar'}),
60 };
61 });
62
63 return $result;
64
65 }
66
67 sub create_schedule {
68 my ($remote, $schedule, $delay) = @_;
69
70 my $unit_name = 'pmg-pbsbackup@' . PVE::Systemd::escape_unit($remote);
71 #my $service_unit = $unit_name . '.service';
72 my $timer_unit = $unit_name . '.timer';
73 my $timer_unit_path = "/etc/systemd/system/$timer_unit";
74
75 # create systemd timer
76 run_command(
77 ['systemd-analyze', 'calendar', $schedule],
78 errmsg => "Invalid schedule specification",
79 outfunc => sub {},
80 );
81 run_command(
82 ['systemd-analyze', 'timespan', $delay],
83 errmsg => "Invalid delay specification",
84 outfunc => sub {},
85 );
86 my $timer = {
87 'Unit' => {
88 'Description' => "Timer for PBS Backup to remote $remote",
89 },
90 'Timer' => {
91 'OnCalendar' => $schedule,
92 'RandomizedDelaySec' => $delay,
93 },
94 'Install' => {
95 'WantedBy' => 'timers.target',
96 },
97 };
98
99 eval {
100 PVE::Systemd::write_ini($timer, $timer_unit_path);
101 run_command(['systemctl', 'daemon-reload']);
102 run_command(['systemctl', 'enable', $timer_unit]);
103 run_command(['systemctl', 'start', $timer_unit]);
104
105 };
106 if (my $err = $@) {
107 die "Creating backup schedule for $remote failed: $err\n";
108 }
109
110 return;
111 }
112
113 sub delete_schedule {
114 my ($remote) = @_;
115
116 my $schedules = get_schedules($remote);
117
118 die "Schedule for $remote not found!\n" if scalar(@$schedules) < 1;
119
120 my $unit_name = 'pmg-pbsbackup@' . PVE::Systemd::escape_unit($remote);
121 my $service_unit = $unit_name . '.service';
122 my $timer_unit = $unit_name . '.timer';
123 my $timer_unit_path = "/etc/systemd/system/$timer_unit";
124
125 eval {
126 run_command(['systemctl', 'disable', $timer_unit]);
127 unlink($timer_unit_path) || die "delete '$timer_unit_path' failed - $!\n";
128 run_command(['systemctl', 'daemon-reload']);
129
130 };
131 if (my $err = $@) {
132 die "Removing backup schedule for $remote failed: $err\n";
133 }
134
135 return;
136 }
137
138 1;