use strict;
use warnings;
+
use PVE::JSONSchema qw(get_standard_option);
use PVE::Exception qw(raise raise_param_exc);
use base qw(PVE::RESTHandler);
-my $api_properties = {
+my $api_properties = {
pos => {
description => "Rule position.",
type => 'integer',
},
};
+sub lock_config {
+ my ($class, $param, $code) = @_;
+
+ die "implement this in subclass";
+}
+
sub load_config {
my ($class, $param) = @_;
sub rule_env {
my ($class, $param) = @_;
-
+
die "implement this in subclass";
}
my $properties = $class->additional_parameters();
$properties->{pos} = $api_properties->{pos};
-
+
my $rule_env = $class->rule_env();
$class->register_method({
type => 'integer',
optional => 1,
},
+ log => PVE::Firewall::get_standard_option('pve-fw-loglevel', {
+ description => 'Log level for firewall rule',
+ }),
+ 'icmp-type' => {
+ type => 'string',
+ optional => 1,
+ },
iface => {
type => 'string',
optional => 1,
optional => 1,
},
macro => {
- type => 'integer',
+ type => 'string',
optional => 1,
},
pos => {
my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
my ($list, $digest) = PVE::Firewall::copy_list_with_digest($rules);
-
+
die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$list);
-
+
my $rule = $list->[$param->{pos}];
$rule->{pos} = $param->{pos};
my $create_rule_properties = PVE::Firewall::add_rule_properties($properties);
$create_rule_properties->{action}->{optional} = 0;
$create_rule_properties->{type}->{optional} = 0;
-
+
my $rule_env = $class->rule_env();
$class->register_method({
code => sub {
my ($param) = @_;
- my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
+ $class->lock_config($param, sub {
+ my ($param) = @_;
+
+ my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
- my $rule = {};
+ my $rule = {};
- PVE::Firewall::copy_rule_data($rule, $param);
- PVE::Firewall::verify_rule($rule, $cluster_conf, $fw_conf, $class->rule_env());
+ PVE::Firewall::copy_rule_data($rule, $param);
+ PVE::Firewall::verify_rule($rule, $cluster_conf, $fw_conf, $class->rule_env());
- $rule->{enable} = 0 if !defined($param->{enable});
+ $rule->{enable} = 0 if !defined($param->{enable});
- unshift @$rules, $rule;
+ unshift @$rules, $rule;
- $class->save_rules($param, $fw_conf, $rules);
+ $class->save_rules($param, $fw_conf, $rules);
+ });
return undef;
}});
my $properties = $class->additional_parameters();
$properties->{pos} = $api_properties->{pos};
-
+
my $rule_env = $class->rule_env();
$properties->{moveto} = {
code => sub {
my ($param) = @_;
- my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
+ $class->lock_config($param, sub {
+ my ($param) = @_;
+
+ my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
- my (undef, $digest) = PVE::Firewall::copy_list_with_digest($rules);
- PVE::Tools::assert_if_modified($digest, $param->{digest});
+ my (undef, $digest) = PVE::Firewall::copy_list_with_digest($rules);
+ PVE::Tools::assert_if_modified($digest, $param->{digest});
- die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
-
- my $rule = $rules->[$param->{pos}];
+ die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
- my $moveto = $param->{moveto};
- if (defined($moveto) && $moveto != $param->{pos}) {
- my $newrules = [];
- for (my $i = 0; $i < scalar(@$rules); $i++) {
- next if $i == $param->{pos};
- if ($i == $moveto) {
- push @$newrules, $rule;
+ my $rule = $rules->[$param->{pos}];
+
+ my $moveto = $param->{moveto};
+ if (defined($moveto) && $moveto != $param->{pos}) {
+ my $newrules = [];
+ for (my $i = 0; $i < scalar(@$rules); $i++) {
+ next if $i == $param->{pos};
+ if ($i == $moveto) {
+ push @$newrules, $rule;
+ }
+ push @$newrules, $rules->[$i];
}
- push @$newrules, $rules->[$i];
- }
- push @$newrules, $rule if $moveto >= scalar(@$rules);
- $rules = $newrules;
- } else {
- PVE::Firewall::copy_rule_data($rule, $param);
-
- PVE::Firewall::delete_rule_properties($rule, $param->{'delete'}) if $param->{'delete'};
+ push @$newrules, $rule if $moveto >= scalar(@$rules);
+ $rules = $newrules;
+ } else {
+ PVE::Firewall::copy_rule_data($rule, $param);
- PVE::Firewall::verify_rule($rule, $cluster_conf, $fw_conf, $class->rule_env());
- }
+ PVE::Firewall::delete_rule_properties($rule, $param->{'delete'}) if $param->{'delete'};
+
+ PVE::Firewall::verify_rule($rule, $cluster_conf, $fw_conf, $class->rule_env());
+ }
- $class->save_rules($param, $fw_conf, $rules);
+ $class->save_rules($param, $fw_conf, $rules);
+ });
return undef;
}});
$properties->{pos} = $api_properties->{pos};
$properties->{digest} = get_standard_option('pve-config-digest');
-
+
my $rule_env = $class->rule_env();
$class->register_method({
code => sub {
my ($param) = @_;
- my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
+ $class->lock_config($param, sub {
+ my ($param) = @_;
+
+ my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
+
+ my (undef, $digest) = PVE::Firewall::copy_list_with_digest($rules);
+ PVE::Tools::assert_if_modified($digest, $param->{digest});
- my (undef, $digest) = PVE::Firewall::copy_list_with_digest($rules);
- PVE::Tools::assert_if_modified($digest, $param->{digest});
-
- die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
-
- splice(@$rules, $param->{pos}, 1);
-
- $class->save_rules($param, $fw_conf, $rules);
+ die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
+
+ splice(@$rules, $param->{pos}, 1);
+
+ $class->save_rules($param, $fw_conf, $rules);
+ });
return undef;
}});
sub rule_env {
my ($class, $param) = @_;
-
+
return 'group';
}
+sub lock_config {
+ my ($class, $param, $code) = @_;
+
+ PVE::Firewall::lock_clusterfw_conf(10, $code, $param);
+}
+
sub load_config {
my ($class, $param) = @_;
},
parameters => {
additionalProperties => 0,
- properties => {
+ properties => {
group => get_standard_option('pve-security-group-name'),
},
},
returns => { type => 'null' },
code => sub {
my ($param) = @_;
-
- my (undef, $cluster_conf, $rules) = __PACKAGE__->load_config($param);
- die "Security group '$param->{group}' is not empty\n"
- if scalar(@$rules);
+ __PACKAGE__->lock_config($param, sub {
+ my ($param) = @_;
+
+ my (undef, $cluster_conf, $rules) = __PACKAGE__->load_config($param);
- __PACKAGE__->save_rules($param, $cluster_conf, undef);
+ die "Security group '$param->{group}' is not empty\n"
+ if scalar(@$rules);
+
+ __PACKAGE__->save_rules($param, $cluster_conf, undef);
+ });
return undef;
}});
sub rule_env {
my ($class, $param) = @_;
-
+
return 'cluster';
}
+sub lock_config {
+ my ($class, $param, $code) = @_;
+
+ PVE::Firewall::lock_clusterfw_conf(10, $code, $param);
+}
+
sub load_config {
my ($class, $param) = @_;
sub rule_env {
my ($class, $param) = @_;
-
+
return 'host';
}
+sub lock_config {
+ my ($class, $param, $code) = @_;
+
+ PVE::Firewall::lock_hostfw_conf(undef, 10, $code, $param);
+}
+
sub load_config {
my ($class, $param) = @_;
use base qw(PVE::API2::Firewall::RulesBase);
-__PACKAGE__->additional_parameters({
+__PACKAGE__->additional_parameters({
node => get_standard_option('pve-node'),
- vmid => get_standard_option('pve-vmid'),
+ vmid => get_standard_option('pve-vmid'),
});
sub rule_env {
my ($class, $param) = @_;
-
+
return 'vm';
}
+sub lock_config {
+ my ($class, $param, $code) = @_;
+
+ PVE::Firewall::lock_vmfw_conf($param->{vmid}, 10, $code, $param);
+}
+
sub load_config {
my ($class, $param) = @_;
use base qw(PVE::API2::Firewall::RulesBase);
-__PACKAGE__->additional_parameters({
+__PACKAGE__->additional_parameters({
node => get_standard_option('pve-node'),
- vmid => get_standard_option('pve-vmid'),
+ vmid => get_standard_option('pve-vmid'),
});
sub rule_env {
my ($class, $param) = @_;
-
+
return 'ct';
}
+sub lock_config {
+ my ($class, $param, $code) = @_;
+
+ PVE::Firewall::lock_vmfw_conf($param->{vmid}, 10, $code, $param);
+}
+
sub load_config {
my ($class, $param) = @_;