]>
Commit | Line | Data |
---|---|---|
2de4cfb2 SI |
1 | package PMG::PBSConfig; |
2 | ||
3 | # section config implementation for PBS integration in PMG | |
4 | ||
5 | use strict; | |
6 | use warnings; | |
7 | ||
8 | use PVE::Tools qw(extract_param); | |
9 | use PVE::SectionConfig; | |
10 | use PVE::JSONSchema qw(get_standard_option); | |
11 | use PVE::PBSClient; | |
12 | ||
13 | use base qw(PVE::SectionConfig); | |
14 | ||
15 | my $inotify_file_id = 'pmg-pbs.conf'; | |
16 | my $secret_dir = '/etc/pmg/pbs'; | |
17 | my $config_filename = "${secret_dir}/pbs.conf"; | |
18 | ||
2de4cfb2 SI |
19 | my %prune_option = ( |
20 | optional => 1, | |
21 | type => 'integer', minimum => '0', | |
22 | format_description => 'N', | |
23 | ); | |
24 | ||
25 | my %prune_properties = ( | |
26 | 'keep-last' => { | |
27 | %prune_option, | |
28 | description => 'Keep the last <N> backups.', | |
29 | }, | |
30 | 'keep-hourly' => { | |
31 | %prune_option, | |
e8a18e4b TL |
32 | description => 'Keep backups for the last <N> different hours. If there is' |
33 | .' more than one backup for a single hour, only the latest one is kept.' | |
2de4cfb2 SI |
34 | }, |
35 | 'keep-daily' => { | |
36 | %prune_option, | |
e8a18e4b TL |
37 | description => 'Keep backups for the last <N> different days. If there is' |
38 | .' more than one backup for a single day, only the latest one is kept.' | |
2de4cfb2 SI |
39 | }, |
40 | 'keep-weekly' => { | |
41 | %prune_option, | |
e8a18e4b TL |
42 | description => 'Keep backups for the last <N> different weeks. If there is' |
43 | .'more than one backup for a single week, only the latest one is kept.' | |
2de4cfb2 SI |
44 | }, |
45 | 'keep-monthly' => { | |
46 | %prune_option, | |
e8a18e4b TL |
47 | description => 'Keep backups for the last <N> different months. If there is' |
48 | .' more than one backup for a single month, only the latest one is kept.' | |
2de4cfb2 SI |
49 | }, |
50 | 'keep-yearly' => { | |
51 | %prune_option, | |
e8a18e4b TL |
52 | description => 'Keep backups for the last <N> different years. If there is' |
53 | .' more than one backup for a single year, only the latest one is kept.' | |
2de4cfb2 SI |
54 | }, |
55 | ); | |
56 | ||
57 | my $defaultData = { | |
58 | propertyList => { | |
59 | type => { description => "Section type." }, | |
60 | remote => { | |
61 | description => "Proxmox Backup Server ID.", | |
62 | type => 'string', format => 'pve-configid', | |
63 | }, | |
64 | }, | |
65 | }; | |
66 | ||
4ac03bcb TL |
67 | my $SAFE_ID_RE = '(?:[A-Za-z0-9_][A-Za-z0-9._\-]*)'; |
68 | my $NS_RE = "(?:${SAFE_ID_RE}/){0,7}(?:${SAFE_ID_RE})?"; | |
69 | ||
2de4cfb2 SI |
70 | sub properties { |
71 | return { | |
72 | datastore => { | |
e8a18e4b | 73 | description => "Proxmox Backup Server datastore name.", |
4ac03bcb TL |
74 | pattern => $SAFE_ID_RE, |
75 | type => 'string', | |
76 | }, | |
77 | namespace => { | |
2de4cfb2 | 78 | type => 'string', |
4ac03bcb TL |
79 | description => "Proxmox Backup Server namespace in the datastore, defaults to the root NS.", |
80 | pattern => $NS_RE, | |
81 | maxLength => 256, | |
2de4cfb2 SI |
82 | }, |
83 | server => { | |
e8a18e4b | 84 | description => "Proxmox Backup Server address.", |
2de4cfb2 SI |
85 | type => 'string', format => 'address', |
86 | maxLength => 256, | |
87 | }, | |
88 | disable => { | |
e8a18e4b | 89 | description => "Flag to disable (deactivate) the entry.", |
2de4cfb2 SI |
90 | type => 'boolean', |
91 | optional => 1, | |
92 | }, | |
93 | password => { | |
e8a18e4b TL |
94 | description => "Password or API token secret for the user on the" |
95 | ." Proxmox Backup Server.", | |
2de4cfb2 SI |
96 | type => 'string', |
97 | optional => 1, | |
98 | }, | |
c807df9f MS |
99 | port => { |
100 | description => "Non-default port for Proxmox Backup Server.", | |
101 | optional => 1, | |
102 | type => 'integer', | |
103 | minimum => 1, | |
104 | maximum => 65535, | |
105 | default => 8007, | |
106 | }, | |
2de4cfb2 | 107 | username => get_standard_option('pmg-email-address', { |
e8a18e4b | 108 | description => "Username or API token ID on the Proxmox Backup Server" |
2de4cfb2 SI |
109 | }), |
110 | fingerprint => get_standard_option('fingerprint-sha256'), | |
f8c773d8 SI |
111 | notify => { |
112 | description => "Specify when to notify via e-mail", | |
113 | type => 'string', | |
114 | enum => [ 'always', 'error', 'never' ], | |
115 | optional => 1, | |
116 | }, | |
d6e25685 SI |
117 | 'include-statistics' => { |
118 | description => "Include statistics in scheduled backups", | |
119 | type => 'boolean', | |
120 | optional => 1, | |
121 | }, | |
2de4cfb2 SI |
122 | %prune_properties, |
123 | }; | |
124 | } | |
125 | ||
126 | sub options { | |
127 | return { | |
128 | server => {}, | |
129 | datastore => {}, | |
4ac03bcb | 130 | namespace => { optional => 1 }, |
2de4cfb2 SI |
131 | disable => { optional => 1 }, |
132 | username => { optional => 1 }, | |
133 | password => { optional => 1 }, | |
c807df9f | 134 | port => { optional => 1 }, |
2de4cfb2 | 135 | fingerprint => { optional => 1 }, |
f8c773d8 | 136 | notify => { optional => 1 }, |
d6e25685 | 137 | 'include-statistics' => { optional => 1 }, |
2de4cfb2 SI |
138 | 'keep-last' => { optional => 1 }, |
139 | 'keep-hourly' => { optional => 1 }, | |
140 | 'keep-daily' => { optional => 1 }, | |
141 | 'keep-weekly' => { optional => 1 }, | |
142 | 'keep-monthly' => { optional => 1 }, | |
143 | 'keep-yearly' => { optional => 1 }, | |
144 | }; | |
145 | } | |
146 | ||
147 | sub type { | |
148 | return 'pbs'; | |
149 | } | |
150 | ||
151 | sub private { | |
152 | return $defaultData; | |
153 | } | |
154 | ||
155 | sub prune_options { | |
156 | my ($self, $remote) = @_; | |
157 | ||
158 | my $remote_cfg = $self->{ids}->{$remote}; | |
159 | ||
160 | my $res = {}; | |
d423685c | 161 | my $pruning_setup; |
2de4cfb2 | 162 | foreach my $keep_opt (keys %prune_properties) { |
2de4cfb2 | 163 | if (defined($remote_cfg->{$keep_opt})) { |
d423685c | 164 | $pruning_setup = 1; |
2de4cfb2 SI |
165 | $res->{$keep_opt} = $remote_cfg->{$keep_opt}; |
166 | } | |
167 | } | |
d423685c | 168 | return $pruning_setup ? $res : undef; |
2de4cfb2 SI |
169 | } |
170 | ||
171 | sub new { | |
172 | my ($type) = @_; | |
173 | ||
174 | my $class = ref($type) || $type; | |
175 | ||
176 | my $cfg = PVE::INotify::read_file($inotify_file_id); | |
177 | ||
178 | $cfg->{secret_dir} = $secret_dir; | |
179 | ||
180 | return bless $cfg, $class; | |
181 | } | |
182 | ||
183 | sub write { | |
184 | my ($self) = @_; | |
185 | ||
186 | PVE::INotify::write_file($inotify_file_id, $self); | |
187 | } | |
188 | ||
2de4cfb2 SI |
189 | sub lock_config { |
190 | my ($code, $errmsg) = @_; | |
191 | ||
e8a18e4b TL |
192 | my $lockfile = "/var/lock/pmgpbsconfig.lck"; |
193 | ||
2de4cfb2 SI |
194 | my $p = PVE::Tools::lock_file($lockfile, undef, $code); |
195 | if (my $err = $@) { | |
196 | $errmsg ? die "$errmsg: $err" : die $err; | |
197 | } | |
198 | } | |
199 | ||
2de4cfb2 SI |
200 | __PACKAGE__->register(); |
201 | __PACKAGE__->init(); | |
202 | ||
203 | sub read_pmg_pbs_conf { | |
204 | my ($filename, $fh) = @_; | |
205 | ||
181ef3f1 | 206 | my $raw = defined($fh) ? do { local $/ = undef; <$fh> } : ''; |
2de4cfb2 SI |
207 | |
208 | return __PACKAGE__->parse_config($filename, $raw); | |
209 | } | |
210 | ||
211 | sub write_pmg_pbs_conf { | |
212 | my ($filename, $fh, $cfg) = @_; | |
213 | ||
214 | my $raw = __PACKAGE__->write_config($filename, $cfg); | |
215 | ||
216 | PVE::Tools::safe_print($filename, $fh, $raw); | |
217 | } | |
218 | ||
e8a18e4b TL |
219 | PVE::INotify::register_file( |
220 | $inotify_file_id, | |
221 | $config_filename, | |
222 | \&read_pmg_pbs_conf, | |
223 | \&write_pmg_pbs_conf, | |
224 | undef, | |
225 | always_call_parser => 1 | |
226 | ); | |
2de4cfb2 SI |
227 | |
228 | 1; |