5
0
mirror of git://git.proxmox.com/git/pve-firewall.git synced 2025-01-09 01:18:04 +03:00

api: lock configs

wherever we have a r-m-w cycle.

Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
This commit is contained in:
Fabian Grünbichler 2020-04-29 10:52:52 +02:00 committed by Thomas Lamprecht
parent 0549601776
commit a38849e650
7 changed files with 277 additions and 216 deletions

View File

@ -143,19 +143,23 @@ sub register_create_alias {
code => sub {
my ($param) = @_;
my ($fw_conf, $aliases) = $class->load_config($param);
$class->lock_config($param, sub {
my ($param) = @_;
my $name = lc($param->{name});
my ($fw_conf, $aliases) = $class->load_config($param);
raise_param_exc({ name => "alias '$param->{name}' already exists" })
if defined($aliases->{$name});
my $name = lc($param->{name});
my $data = { name => $param->{name}, cidr => $param->{cidr} };
$data->{comment} = $param->{comment} if $param->{comment};
raise_param_exc({ name => "alias '$param->{name}' already exists" })
if defined($aliases->{$name});
$aliases->{$name} = $data;
my $data = { name => $param->{name}, cidr => $param->{cidr} };
$data->{comment} = $param->{comment} if $param->{comment};
$class->save_aliases($param, $fw_conf, $aliases);
$aliases->{$name} = $data;
$class->save_aliases($param, $fw_conf, $aliases);
});
return undef;
}});
@ -219,35 +223,39 @@ sub register_update_alias {
code => sub {
my ($param) = @_;
my ($fw_conf, $aliases) = $class->load_config($param);
$class->lock_config($param, sub {
my ($param) = @_;
my $list = &$aliases_to_list($aliases);
my ($fw_conf, $aliases) = $class->load_config($param);
my (undef, $digest) = PVE::Firewall::copy_list_with_digest($list);
my $list = &$aliases_to_list($aliases);
PVE::Tools::assert_if_modified($digest, $param->{digest});
my (undef, $digest) = PVE::Firewall::copy_list_with_digest($list);
my $name = lc($param->{name});
PVE::Tools::assert_if_modified($digest, $param->{digest});
raise_param_exc({ name => "no such alias" }) if !$aliases->{$name};
my $name = lc($param->{name});
my $data = { name => $param->{name}, cidr => $param->{cidr} };
$data->{comment} = $param->{comment} if $param->{comment};
raise_param_exc({ name => "no such alias" }) if !$aliases->{$name};
$aliases->{$name} = $data;
my $data = { name => $param->{name}, cidr => $param->{cidr} };
$data->{comment} = $param->{comment} if $param->{comment};
my $rename = $param->{rename};
$rename = lc($rename) if $rename;
$aliases->{$name} = $data;
if ($rename && ($name ne $rename)) {
raise_param_exc({ name => "alias '$param->{rename}' already exists" })
if defined($aliases->{$rename});
$aliases->{$name}->{name} = $param->{rename};
$aliases->{$rename} = $aliases->{$name};
delete $aliases->{$name};
}
my $rename = $param->{rename};
$rename = lc($rename) if $rename;
$class->save_aliases($param, $fw_conf, $aliases);
if ($rename && ($name ne $rename)) {
raise_param_exc({ name => "alias '$param->{rename}' already exists" })
if defined($aliases->{$rename});
$aliases->{$name}->{name} = $param->{rename};
$aliases->{$rename} = $aliases->{$name};
delete $aliases->{$name};
}
$class->save_aliases($param, $fw_conf, $aliases);
});
return undef;
}});
@ -276,16 +284,20 @@ sub register_delete_alias {
code => sub {
my ($param) = @_;
my ($fw_conf, $aliases) = $class->load_config($param);
$class->lock_config($param, sub {
my ($param) = @_;
my $list = &$aliases_to_list($aliases);
my (undef, $digest) = PVE::Firewall::copy_list_with_digest($list);
PVE::Tools::assert_if_modified($digest, $param->{digest});
my ($fw_conf, $aliases) = $class->load_config($param);
my $name = lc($param->{name});
delete $aliases->{$name};
my $list = &$aliases_to_list($aliases);
my (undef, $digest) = PVE::Firewall::copy_list_with_digest($list);
PVE::Tools::assert_if_modified($digest, $param->{digest});
$class->save_aliases($param, $fw_conf, $aliases);
my $name = lc($param->{name});
delete $aliases->{$name};
$class->save_aliases($param, $fw_conf, $aliases);
});
return undef;
}});

View File

@ -132,29 +132,31 @@ __PACKAGE__->register_method({
code => sub {
my ($param) = @_;
my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
PVE::Firewall::lock_clusterfw_conf(10, sub {
my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
my (undef, $digest) = PVE::Firewall::copy_opject_with_digest($cluster_conf->{options});
PVE::Tools::assert_if_modified($digest, $param->{digest});
my (undef, $digest) = PVE::Firewall::copy_opject_with_digest($cluster_conf->{options});
PVE::Tools::assert_if_modified($digest, $param->{digest});
if ($param->{delete}) {
foreach my $opt (PVE::Tools::split_list($param->{delete})) {
raise_param_exc({ delete => "no such option '$opt'" })
if !$option_properties->{$opt};
delete $cluster_conf->{options}->{$opt};
if ($param->{delete}) {
foreach my $opt (PVE::Tools::split_list($param->{delete})) {
raise_param_exc({ delete => "no such option '$opt'" })
if !$option_properties->{$opt};
delete $cluster_conf->{options}->{$opt};
}
}
}
if (defined($param->{enable}) && ($param->{enable} > 1)) {
$param->{enable} = time();
}
if (defined($param->{enable}) && ($param->{enable} > 1)) {
$param->{enable} = time();
}
foreach my $k (keys %$option_properties) {
next if !defined($param->{$k});
$cluster_conf->{options}->{$k} = $param->{$k};
}
foreach my $k (keys %$option_properties) {
next if !defined($param->{$k});
$cluster_conf->{options}->{$k} = $param->{$k};
}
PVE::Firewall::save_clusterfw_conf($cluster_conf);
PVE::Firewall::save_clusterfw_conf($cluster_conf);
});
# instant firewall update when using double (anti-lockout) API call
# -> not waiting for a firewall update at the first (timestamp enable) set

View File

@ -91,37 +91,39 @@ __PACKAGE__->register_method({
code => sub {
my ($param) = @_;
my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
PVE::Firewall::lock_clusterfw_conf(10, sub {
my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
if ($param->{rename}) {
my (undef, $digest) = &$get_security_group_list($cluster_conf);
PVE::Tools::assert_if_modified($digest, $param->{digest});
if ($param->{rename}) {
my (undef, $digest) = &$get_security_group_list($cluster_conf);
PVE::Tools::assert_if_modified($digest, $param->{digest});
raise_param_exc({ group => "Security group '$param->{rename}' does not exist" })
if !$cluster_conf->{groups}->{$param->{rename}};
raise_param_exc({ group => "Security group '$param->{rename}' does not exist" })
if !$cluster_conf->{groups}->{$param->{rename}};
# prevent overwriting an existing group
raise_param_exc({ group => "Security group '$param->{group}' does already exist" })
if $cluster_conf->{groups}->{$param->{group}} &&
$param->{group} ne $param->{rename};
# prevent overwriting an existing group
raise_param_exc({ group => "Security group '$param->{group}' does already exist" })
if $cluster_conf->{groups}->{$param->{group}} &&
$param->{group} ne $param->{rename};
my $data = delete $cluster_conf->{groups}->{$param->{rename}};
$cluster_conf->{groups}->{$param->{group}} = $data;
if (my $comment = delete $cluster_conf->{group_comments}->{$param->{rename}}) {
$cluster_conf->{group_comments}->{$param->{group}} = $comment;
}
$cluster_conf->{group_comments}->{$param->{group}} = $param->{comment} if defined($param->{comment});
} else {
foreach my $name (keys %{$cluster_conf->{groups}}) {
raise_param_exc({ group => "Security group '$name' already exists" })
if $name eq $param->{group};
my $data = delete $cluster_conf->{groups}->{$param->{rename}};
$cluster_conf->{groups}->{$param->{group}} = $data;
if (my $comment = delete $cluster_conf->{group_comments}->{$param->{rename}}) {
$cluster_conf->{group_comments}->{$param->{group}} = $comment;
}
$cluster_conf->{group_comments}->{$param->{group}} = $param->{comment} if defined($param->{comment});
} else {
foreach my $name (keys %{$cluster_conf->{groups}}) {
raise_param_exc({ group => "Security group '$name' already exists" })
if $name eq $param->{group};
}
$cluster_conf->{groups}->{$param->{group}} = [];
$cluster_conf->{group_comments}->{$param->{group}} = $param->{comment} if defined($param->{comment});
}
$cluster_conf->{groups}->{$param->{group}} = [];
$cluster_conf->{group_comments}->{$param->{group}} = $param->{comment} if defined($param->{comment});
}
PVE::Firewall::save_clusterfw_conf($cluster_conf);
PVE::Firewall::save_clusterfw_conf($cluster_conf);
});
return undef;
}});

View File

@ -118,30 +118,32 @@ __PACKAGE__->register_method({
code => sub {
my ($param) = @_;
my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
my $hostfw_conf = PVE::Firewall::load_hostfw_conf($cluster_conf);
PVE::Firewall::lock_hostfw_conf(10, sub {
my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
my $hostfw_conf = PVE::Firewall::load_hostfw_conf($cluster_conf);
my (undef, $digest) = PVE::Firewall::copy_opject_with_digest($hostfw_conf->{options});
PVE::Tools::assert_if_modified($digest, $param->{digest});
my (undef, $digest) = PVE::Firewall::copy_opject_with_digest($hostfw_conf->{options});
PVE::Tools::assert_if_modified($digest, $param->{digest});
if ($param->{delete}) {
foreach my $opt (PVE::Tools::split_list($param->{delete})) {
raise_param_exc({ delete => "no such option '$opt'" })
if !$option_properties->{$opt};
delete $hostfw_conf->{options}->{$opt};
if ($param->{delete}) {
foreach my $opt (PVE::Tools::split_list($param->{delete})) {
raise_param_exc({ delete => "no such option '$opt'" })
if !$option_properties->{$opt};
delete $hostfw_conf->{options}->{$opt};
}
}
}
if (defined($param->{enable})) {
$param->{enable} = $param->{enable} ? 1 : 0;
}
if (defined($param->{enable})) {
$param->{enable} = $param->{enable} ? 1 : 0;
}
foreach my $k (keys %$option_properties) {
next if !defined($param->{$k});
$hostfw_conf->{options}->{$k} = $param->{$k};
}
foreach my $k (keys %$option_properties) {
next if !defined($param->{$k});
$hostfw_conf->{options}->{$k} = $param->{$k};
}
PVE::Firewall::save_hostfw_conf($hostfw_conf);
PVE::Firewall::save_hostfw_conf($hostfw_conf);
});
return undef;
}});

View File

@ -148,12 +148,17 @@ sub register_delete_ipset {
code => sub {
my ($param) = @_;
my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
$class->lock_config($param, sub {
my ($param) = @_;
die "IPSet '$param->{name}' is not empty\n"
if scalar(@$ipset);
my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
$class->save_ipset($param, $fw_conf, undef);
die "IPSet '$param->{name}' is not empty\n"
if scalar(@$ipset);
$class->save_ipset($param, $fw_conf, undef);
});
return undef;
}});
@ -184,30 +189,35 @@ sub register_create_ip {
code => sub {
my ($param) = @_;
my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
$class->lock_config($param, sub {
my ($param) = @_;
my $cidr = $param->{cidr};
my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
foreach my $entry (@$ipset) {
raise_param_exc({ cidr => "address '$cidr' already exists" })
if $entry->{cidr} eq $cidr;
}
my $cidr = $param->{cidr};
raise_param_exc({ cidr => "a zero prefix is not allowed in ipset entries" })
if $cidr =~ m!/0+$!;
foreach my $entry (@$ipset) {
raise_param_exc({ cidr => "address '$cidr' already exists" })
if $entry->{cidr} eq $cidr;
}
# make sure alias exists (if $cidr is an alias)
PVE::Firewall::resolve_alias($cluster_conf, $fw_conf, $cidr)
if $cidr =~ m/^${PVE::Firewall::ip_alias_pattern}$/;
raise_param_exc({ cidr => "a zero prefix is not allowed in ipset entries" })
if $cidr =~ m!/0+$!;
my $data = { cidr => $cidr };
# make sure alias exists (if $cidr is an alias)
PVE::Firewall::resolve_alias($cluster_conf, $fw_conf, $cidr)
if $cidr =~ m/^${PVE::Firewall::ip_alias_pattern}$/;
$data->{nomatch} = 1 if $param->{nomatch};
$data->{comment} = $param->{comment} if $param->{comment};
my $data = { cidr => $cidr };
unshift @$ipset, $data;
$data->{nomatch} = 1 if $param->{nomatch};
$data->{comment} = $param->{comment} if $param->{comment};
$class->save_ipset($param, $fw_conf, $ipset);
unshift @$ipset, $data;
$class->save_ipset($param, $fw_conf, $ipset);
});
return undef;
}});
@ -276,19 +286,27 @@ sub register_update_ip {
code => sub {
my ($param) = @_;
my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
my $found = $class->lock_config($param, sub {
my ($param) = @_;
my (undef, $digest) = PVE::Firewall::copy_list_with_digest($ipset);
PVE::Tools::assert_if_modified($digest, $param->{digest});
my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
foreach my $entry (@$ipset) {
if($entry->{cidr} eq $param->{cidr}) {
$entry->{nomatch} = $param->{nomatch};
$entry->{comment} = $param->{comment};
$class->save_ipset($param, $fw_conf, $ipset);
return;
my (undef, $digest) = PVE::Firewall::copy_list_with_digest($ipset);
PVE::Tools::assert_if_modified($digest, $param->{digest});
foreach my $entry (@$ipset) {
if($entry->{cidr} eq $param->{cidr}) {
$entry->{nomatch} = $param->{nomatch};
$entry->{comment} = $param->{comment};
$class->save_ipset($param, $fw_conf, $ipset);
return 1;
}
}
}
return 0;
});
return if $found;
raise_param_exc({ cidr => "no such IP/Network" });
}});
@ -318,18 +336,22 @@ sub register_delete_ip {
code => sub {
my ($param) = @_;
my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
$class->lock_config($param, sub {
my ($param) = @_;
my (undef, $digest) = PVE::Firewall::copy_list_with_digest($ipset);
PVE::Tools::assert_if_modified($digest, $param->{digest});
my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
my $new = [];
my (undef, $digest) = PVE::Firewall::copy_list_with_digest($ipset);
PVE::Tools::assert_if_modified($digest, $param->{digest});
foreach my $entry (@$ipset) {
push @$new, $entry if $entry->{cidr} ne $param->{cidr};
}
my $new = [];
$class->save_ipset($param, $fw_conf, $new);
foreach my $entry (@$ipset) {
push @$new, $entry if $entry->{cidr} ne $param->{cidr};
}
$class->save_ipset($param, $fw_conf, $new);
});
return undef;
}});
@ -611,37 +633,41 @@ sub register_create {
code => sub {
my ($param) = @_;
my ($cluster_conf, $fw_conf) = $class->load_config($param);
$class->lock_config($param, sub {
my ($param) = @_;
if ($param->{rename}) {
my (undef, $digest) = &$get_ipset_list($fw_conf);
PVE::Tools::assert_if_modified($digest, $param->{digest});
my ($cluster_conf, $fw_conf) = $class->load_config($param);
raise_param_exc({ name => "IPSet '$param->{rename}' does not exist" })
if !$fw_conf->{ipset}->{$param->{rename}};
if ($param->{rename}) {
my (undef, $digest) = &$get_ipset_list($fw_conf);
PVE::Tools::assert_if_modified($digest, $param->{digest});
# prevent overwriting existing ipset
raise_param_exc({ name => "IPSet '$param->{name}' does already exist"})
if $fw_conf->{ipset}->{$param->{name}} &&
$param->{name} ne $param->{rename};
raise_param_exc({ name => "IPSet '$param->{rename}' does not exist" })
if !$fw_conf->{ipset}->{$param->{rename}};
my $data = delete $fw_conf->{ipset}->{$param->{rename}};
$fw_conf->{ipset}->{$param->{name}} = $data;
if (my $comment = delete $fw_conf->{ipset_comments}->{$param->{rename}}) {
$fw_conf->{ipset_comments}->{$param->{name}} = $comment;
}
$fw_conf->{ipset_comments}->{$param->{name}} = $param->{comment} if defined($param->{comment});
} else {
foreach my $name (keys %{$fw_conf->{ipset}}) {
raise_param_exc({ name => "IPSet '$name' already exists" })
if $name eq $param->{name};
# prevent overwriting existing ipset
raise_param_exc({ name => "IPSet '$param->{name}' does already exist"})
if $fw_conf->{ipset}->{$param->{name}} &&
$param->{name} ne $param->{rename};
my $data = delete $fw_conf->{ipset}->{$param->{rename}};
$fw_conf->{ipset}->{$param->{name}} = $data;
if (my $comment = delete $fw_conf->{ipset_comments}->{$param->{rename}}) {
$fw_conf->{ipset_comments}->{$param->{name}} = $comment;
}
$fw_conf->{ipset_comments}->{$param->{name}} = $param->{comment} if defined($param->{comment});
} else {
foreach my $name (keys %{$fw_conf->{ipset}}) {
raise_param_exc({ name => "IPSet '$name' already exists" })
if $name eq $param->{name};
}
$fw_conf->{ipset}->{$param->{name}} = [];
$fw_conf->{ipset_comments}->{$param->{name}} = $param->{comment} if defined($param->{comment});
}
$fw_conf->{ipset}->{$param->{name}} = [];
$fw_conf->{ipset_comments}->{$param->{name}} = $param->{comment} if defined($param->{comment});
}
$class->save_config($param, $fw_conf);
$class->save_config($param, $fw_conf);
});
return undef;
}});

View File

@ -225,18 +225,22 @@ sub register_create_rule {
code => sub {
my ($param) = @_;
my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
$class->lock_config($param, sub {
my ($param) = @_;
my $rule = {};
my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
PVE::Firewall::copy_rule_data($rule, $param);
PVE::Firewall::verify_rule($rule, $cluster_conf, $fw_conf, $class->rule_env());
my $rule = {};
$rule->{enable} = 0 if !defined($param->{enable});
PVE::Firewall::copy_rule_data($rule, $param);
PVE::Firewall::verify_rule($rule, $cluster_conf, $fw_conf, $class->rule_env());
unshift @$rules, $rule;
$rule->{enable} = 0 if !defined($param->{enable});
$class->save_rules($param, $fw_conf, $rules);
unshift @$rules, $rule;
$class->save_rules($param, $fw_conf, $rules);
});
return undef;
}});
@ -282,36 +286,40 @@ sub register_update_rule {
code => sub {
my ($param) = @_;
my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
$class->lock_config($param, sub {
my ($param) = @_;
my (undef, $digest) = PVE::Firewall::copy_list_with_digest($rules);
PVE::Tools::assert_if_modified($digest, $param->{digest});
my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
my (undef, $digest) = PVE::Firewall::copy_list_with_digest($rules);
PVE::Tools::assert_if_modified($digest, $param->{digest});
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'};
PVE::Firewall::verify_rule($rule, $cluster_conf, $fw_conf, $class->rule_env());
}
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'};
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;
}});
@ -344,16 +352,20 @@ sub register_delete_rule {
code => sub {
my ($param) = @_;
my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
$class->lock_config($param, sub {
my ($param) = @_;
my (undef, $digest) = PVE::Firewall::copy_list_with_digest($rules);
PVE::Tools::assert_if_modified($digest, $param->{digest});
my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param);
die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
my (undef, $digest) = PVE::Firewall::copy_list_with_digest($rules);
PVE::Tools::assert_if_modified($digest, $param->{digest});
splice(@$rules, $param->{pos}, 1);
die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
$class->save_rules($param, $fw_conf, $rules);
splice(@$rules, $param->{pos}, 1);
$class->save_rules($param, $fw_conf, $rules);
});
return undef;
}});
@ -433,12 +445,16 @@ __PACKAGE__->register_method({
code => sub {
my ($param) = @_;
my (undef, $cluster_conf, $rules) = __PACKAGE__->load_config($param);
__PACKAGE__->lock_config($param, sub {
my ($param) = @_;
die "Security group '$param->{group}' is not empty\n"
if scalar(@$rules);
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;
}});

View File

@ -121,31 +121,32 @@ sub register_handlers {
code => sub {
my ($param) = @_;
PVE::Firewall::lock_vmfw_conf($param->{vmid}, 10, sub {
my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
my $vmfw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, $rule_env, $param->{vmid});
my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
my $vmfw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, $rule_env, $param->{vmid});
my (undef, $digest) = PVE::Firewall::copy_opject_with_digest($vmfw_conf->{options});
PVE::Tools::assert_if_modified($digest, $param->{digest});
my (undef, $digest) = PVE::Firewall::copy_opject_with_digest($vmfw_conf->{options});
PVE::Tools::assert_if_modified($digest, $param->{digest});
if ($param->{delete}) {
foreach my $opt (PVE::Tools::split_list($param->{delete})) {
raise_param_exc({ delete => "no such option '$opt'" })
if !$option_properties->{$opt};
delete $vmfw_conf->{options}->{$opt};
if ($param->{delete}) {
foreach my $opt (PVE::Tools::split_list($param->{delete})) {
raise_param_exc({ delete => "no such option '$opt'" })
if !$option_properties->{$opt};
delete $vmfw_conf->{options}->{$opt};
}
}
}
if (defined($param->{enable})) {
$param->{enable} = $param->{enable} ? 1 : 0;
}
if (defined($param->{enable})) {
$param->{enable} = $param->{enable} ? 1 : 0;
}
foreach my $k (keys %$option_properties) {
next if !defined($param->{$k});
$vmfw_conf->{options}->{$k} = $param->{$k};
}
foreach my $k (keys %$option_properties) {
next if !defined($param->{$k});
$vmfw_conf->{options}->{$k} = $param->{$k};
}
PVE::Firewall::save_vmfw_conf($param->{vmid}, $vmfw_conf);
PVE::Firewall::save_vmfw_conf($param->{vmid}, $vmfw_conf);
});
return undef;
}});