api: add locking helpers
[pve-firewall.git] / src / PVE / API2 / Firewall / Aliases.pm
CommitLineData
81d574a7
DM
1package PVE::API2::Firewall::AliasesBase;
2
3use strict;
4use warnings;
5use PVE::Exception qw(raise raise_param_exc);
6use PVE::JSONSchema qw(get_standard_option);
7
8use PVE::Firewall;
9
10use base qw(PVE::RESTHandler);
11
75a12a9d 12my $api_properties = {
81d574a7
DM
13 cidr => {
14 description => "Network/IP specification in CIDR format.",
ae029a88 15 type => 'string', format => 'IPorCIDR',
81d574a7
DM
16 },
17 name => get_standard_option('pve-fw-alias'),
cdc39d63
DM
18 rename => get_standard_option('pve-fw-alias', {
19 description => "Rename an existing alias.",
20 optional => 1,
21 }),
81d574a7
DM
22 comment => {
23 type => 'string',
24 optional => 1,
cdc39d63 25 },
81d574a7
DM
26};
27
05496017
FG
28sub lock_config {
29 my ($class, $param, $code) = @_;
30
31 die "implement this in subclass";
32}
33
81d574a7
DM
34sub load_config {
35 my ($class, $param) = @_;
36
37 die "implement this in subclass";
38
39 #return ($fw_conf, $rules);
40}
41
42sub save_aliases {
43 my ($class, $param, $fw_conf, $aliases) = @_;
44
45 die "implement this in subclass";
46}
47
5679b3a8
DM
48sub rule_env {
49 my ($class, $param) = @_;
75a12a9d 50
5679b3a8
DM
51 die "implement this in subclass";
52}
53
81d574a7
DM
54my $additional_param_hash = {};
55
56sub additional_parameters {
57 my ($class, $new_value) = @_;
58
59 if (defined($new_value)) {
60 $additional_param_hash->{$class} = $new_value;
61 }
62
63 # return a copy
64 my $copy = {};
65 my $org = $additional_param_hash->{$class} || {};
66 foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; }
67 return $copy;
68}
69
70my $aliases_to_list = sub {
71 my ($aliases) = @_;
72
73 my $list = [];
74 foreach my $k (sort keys %$aliases) {
75 push @$list, $aliases->{$k};
76 }
77 return $list;
78};
79
80sub register_get_aliases {
81 my ($class) = @_;
82
83 my $properties = $class->additional_parameters();
84
85 $class->register_method({
86 name => 'get_aliases',
87 path => '',
88 method => 'GET',
89 description => "List aliases",
5679b3a8 90 permissions => PVE::Firewall::rules_audit_permissions($class->rule_env()),
81d574a7
DM
91 parameters => {
92 additionalProperties => 0,
93 properties => $properties,
94 },
95 returns => {
96 type => 'array',
97 items => {
98 type => "object",
99 properties => {
100 name => { type => 'string' },
101 cidr => { type => 'string' },
102 comment => {
103 type => 'string',
104 optional => 1,
105 },
75a12a9d 106 digest => get_standard_option('pve-config-digest', { optional => 0} ),
81d574a7
DM
107 },
108 },
109 links => [ { rel => 'child', href => "{name}" } ],
110 },
111 code => sub {
112 my ($param) = @_;
113
114 my ($fw_conf, $aliases) = $class->load_config($param);
115
116 my $list = &$aliases_to_list($aliases);
117
118 return PVE::Firewall::copy_list_with_digest($list);
119 }});
120}
121
122sub register_create_alias {
123 my ($class) = @_;
124
125 my $properties = $class->additional_parameters();
126
127 $properties->{name} = $api_properties->{name};
128 $properties->{cidr} = $api_properties->{cidr};
129 $properties->{comment} = $api_properties->{comment};
130
131 $class->register_method({
132 name => 'create_alias',
133 path => '',
134 method => 'POST',
135 description => "Create IP or Network Alias.",
5679b3a8 136 permissions => PVE::Firewall::rules_modify_permissions($class->rule_env()),
81d574a7
DM
137 protected => 1,
138 parameters => {
139 additionalProperties => 0,
140 properties => $properties,
141 },
142 returns => { type => "null" },
143 code => sub {
144 my ($param) = @_;
145
146 my ($fw_conf, $aliases) = $class->load_config($param);
147
148 my $name = lc($param->{name});
75a12a9d
TL
149
150 raise_param_exc({ name => "alias '$param->{name}' already exists" })
81d574a7 151 if defined($aliases->{$name});
75a12a9d 152
81d574a7
DM
153 my $data = { name => $param->{name}, cidr => $param->{cidr} };
154 $data->{comment} = $param->{comment} if $param->{comment};
155
156 $aliases->{$name} = $data;
157
158 $class->save_aliases($param, $fw_conf, $aliases);
159
160 return undef;
161 }});
162}
163
164sub register_read_alias {
165 my ($class) = @_;
166
167 my $properties = $class->additional_parameters();
168
169 $properties->{name} = $api_properties->{name};
75a12a9d 170
81d574a7
DM
171 $class->register_method({
172 name => 'read_alias',
173 path => '{name}',
174 method => 'GET',
175 description => "Read alias.",
5679b3a8 176 permissions => PVE::Firewall::rules_audit_permissions($class->rule_env()),
81d574a7
DM
177 parameters => {
178 additionalProperties => 0,
179 properties => $properties,
180 },
181 returns => { type => "object" },
182 code => sub {
183 my ($param) = @_;
184
185 my ($fw_conf, $aliases) = $class->load_config($param);
186
187 my $name = lc($param->{name});
188
189 raise_param_exc({ name => "no such alias" })
190 if !defined($aliases->{$name});
191
192 return $aliases->{$name};
193 }});
194}
195
196sub register_update_alias {
197 my ($class) = @_;
198
199 my $properties = $class->additional_parameters();
200
201 $properties->{name} = $api_properties->{name};
cdc39d63 202 $properties->{rename} = $api_properties->{rename};
81d574a7
DM
203 $properties->{cidr} = $api_properties->{cidr};
204 $properties->{comment} = $api_properties->{comment};
205 $properties->{digest} = get_standard_option('pve-config-digest');
206
207 $class->register_method({
208 name => 'update_alias',
209 path => '{name}',
210 method => 'PUT',
211 description => "Update IP or Network alias.",
5679b3a8 212 permissions => PVE::Firewall::rules_modify_permissions($class->rule_env()),
81d574a7
DM
213 protected => 1,
214 parameters => {
215 additionalProperties => 0,
216 properties => $properties,
217 },
218 returns => { type => "null" },
219 code => sub {
220 my ($param) = @_;
221
222 my ($fw_conf, $aliases) = $class->load_config($param);
223
224 my $list = &$aliases_to_list($aliases);
225
226 my (undef, $digest) = PVE::Firewall::copy_list_with_digest($list);
227
228 PVE::Tools::assert_if_modified($digest, $param->{digest});
229
230 my $name = lc($param->{name});
231
232 raise_param_exc({ name => "no such alias" }) if !$aliases->{$name};
233
234 my $data = { name => $param->{name}, cidr => $param->{cidr} };
235 $data->{comment} = $param->{comment} if $param->{comment};
236
237 $aliases->{$name} = $data;
238
13d39f19
ML
239 my $rename = $param->{rename};
240 $rename = lc($rename) if $rename;
cdc39d63
DM
241
242 if ($rename && ($name ne $rename)) {
75a12a9d 243 raise_param_exc({ name => "alias '$param->{rename}' already exists" })
cdc39d63
DM
244 if defined($aliases->{$rename});
245 $aliases->{$name}->{name} = $param->{rename};
246 $aliases->{$rename} = $aliases->{$name};
247 delete $aliases->{$name};
248 }
249
81d574a7 250 $class->save_aliases($param, $fw_conf, $aliases);
cdc39d63
DM
251
252 return undef;
81d574a7
DM
253 }});
254}
255
256sub register_delete_alias {
257 my ($class) = @_;
258
259 my $properties = $class->additional_parameters();
260
261 $properties->{name} = $api_properties->{name};
81d574a7
DM
262 $properties->{digest} = get_standard_option('pve-config-digest');
263
264 $class->register_method({
265 name => 'remove_alias',
266 path => '{name}',
267 method => 'DELETE',
268 description => "Remove IP or Network alias.",
5679b3a8 269 permissions => PVE::Firewall::rules_modify_permissions($class->rule_env()),
81d574a7
DM
270 protected => 1,
271 parameters => {
272 additionalProperties => 0,
273 properties => $properties,
274 },
275 returns => { type => "null" },
276 code => sub {
277 my ($param) = @_;
278
279 my ($fw_conf, $aliases) = $class->load_config($param);
280
281 my $list = &$aliases_to_list($aliases);
282 my (undef, $digest) = PVE::Firewall::copy_list_with_digest($list);
283 PVE::Tools::assert_if_modified($digest, $param->{digest});
284
285 my $name = lc($param->{name});
286 delete $aliases->{$name};
287
288 $class->save_aliases($param, $fw_conf, $aliases);
75a12a9d 289
81d574a7
DM
290 return undef;
291 }});
292}
293
294sub register_handlers {
295 my ($class) = @_;
296
297 $class->register_get_aliases();
298 $class->register_create_alias();
299 $class->register_read_alias();
300 $class->register_update_alias();
301 $class->register_delete_alias();
302}
303
304package PVE::API2::Firewall::ClusterAliases;
305
306use strict;
307use warnings;
308
309use base qw(PVE::API2::Firewall::AliasesBase);
310
5679b3a8
DM
311sub rule_env {
312 my ($class, $param) = @_;
75a12a9d 313
5679b3a8
DM
314 return 'cluster';
315}
316
05496017
FG
317sub lock_config {
318 my ($class, $param, $code) = @_;
319
320 PVE::Firewall::lock_clusterfw_conf(10, $code, $param);
321}
322
81d574a7
DM
323sub load_config {
324 my ($class, $param) = @_;
325
326 my $fw_conf = PVE::Firewall::load_clusterfw_conf();
327 my $aliases = $fw_conf->{aliases};
328
329 return ($fw_conf, $aliases);
330}
331
332sub save_aliases {
333 my ($class, $param, $fw_conf, $aliases) = @_;
334
335 $fw_conf->{aliases} = $aliases;
336 PVE::Firewall::save_clusterfw_conf($fw_conf);
337}
338
339__PACKAGE__->register_handlers();
340
e76a9f53
DM
341package PVE::API2::Firewall::VMAliases;
342
343use strict;
344use warnings;
345use PVE::JSONSchema qw(get_standard_option);
346
347use base qw(PVE::API2::Firewall::AliasesBase);
348
5679b3a8
DM
349sub rule_env {
350 my ($class, $param) = @_;
75a12a9d 351
5679b3a8
DM
352 return 'vm';
353}
354
75a12a9d 355__PACKAGE__->additional_parameters({
e76a9f53 356 node => get_standard_option('pve-node'),
75a12a9d 357 vmid => get_standard_option('pve-vmid'),
e76a9f53
DM
358});
359
05496017
FG
360sub lock_config {
361 my ($class, $param, $code) = @_;
362
363 PVE::Firewall::lock_vmfw_conf($param->{vmid}, 10, $code, $param);
364}
365
e76a9f53
DM
366sub load_config {
367 my ($class, $param) = @_;
368
42ec8178
DM
369 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
370 my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, 'vm', $param->{vmid});
b6b8e6ad
DM
371 my $aliases = $fw_conf->{aliases};
372
373 return ($fw_conf, $aliases);
374}
375
376sub save_aliases {
377 my ($class, $param, $fw_conf, $aliases) = @_;
378
379 $fw_conf->{aliases} = $aliases;
380 PVE::Firewall::save_vmfw_conf($param->{vmid}, $fw_conf);
381}
382
383__PACKAGE__->register_handlers();
384
385package PVE::API2::Firewall::CTAliases;
386
387use strict;
388use warnings;
389use PVE::JSONSchema qw(get_standard_option);
390
391use base qw(PVE::API2::Firewall::AliasesBase);
392
5679b3a8
DM
393sub rule_env {
394 my ($class, $param) = @_;
75a12a9d 395
5679b3a8
DM
396 return 'ct';
397}
398
75a12a9d 399__PACKAGE__->additional_parameters({
b6b8e6ad 400 node => get_standard_option('pve-node'),
75a12a9d 401 vmid => get_standard_option('pve-vmid'),
b6b8e6ad
DM
402});
403
05496017
FG
404sub lock_config {
405 my ($class, $param, $code) = @_;
406
407 PVE::Firewall::lock_vmfw_conf($param->{vmid}, 10, $code, $param);
408}
409
b6b8e6ad
DM
410sub load_config {
411 my ($class, $param) = @_;
412
42ec8178
DM
413 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
414 my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, 'ct', $param->{vmid});
e76a9f53
DM
415 my $aliases = $fw_conf->{aliases};
416
417 return ($fw_conf, $aliases);
418}
419
420sub save_aliases {
421 my ($class, $param, $fw_conf, $aliases) = @_;
422
423 $fw_conf->{aliases} = $aliases;
424 PVE::Firewall::save_vmfw_conf($param->{vmid}, $fw_conf);
425}
426
427__PACKAGE__->register_handlers();
428
81d574a7 4291;