my $properties = $class->additional_parameters();
$properties->{name} = get_standard_option('ipset-name');
+ $properties->{force} = {
+ type => 'boolean',
+ optional => 1,
+ description => 'Delete all members of the IPSet, if there are any.',
+ };
$class->register_method({
name => 'delete_ipset',
my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
die "IPSet '$param->{name}' is not empty\n"
- if scalar(@$ipset);
+ if scalar(@$ipset) && !$param->{force};
$class->save_ipset($param, $fw_conf, undef);
my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
my $cidr = $param->{cidr};
+ if ($cidr =~ m@^(dc/|guest/)?(${PVE::Firewall::ip_alias_pattern})$@) {
+ my $scope = $1 // "";
+ my $alias = $2;
+ # make sure alias exists (if $cidr is an alias)
+ PVE::Firewall::resolve_alias($cluster_conf, $fw_conf, $alias, $scope);
+ } else {
+ $cidr = PVE::Firewall::clean_cidr($cidr);
+ # normalize like config parser, otherwise duplicates might slip through
+ $cidr = PVE::Firewall::parse_ip_or_cidr($cidr);
+ }
foreach my $entry (@$ipset) {
raise_param_exc({ cidr => "address '$cidr' already exists" })
raise_param_exc({ cidr => "a zero prefix is not allowed in ipset entries" })
if $cidr =~ m!/0+$!;
- # 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}$/;
my $data = { cidr => $cidr };