[pve-devel] [PATCH V2 pve-firewall 1/1] fix #1965: cache firewall/cluster.fw file

Stefan Hrdlicka s.hrdlicka at proxmox.com
Fri Nov 25 15:47:25 CET 2022


for large IP sets (for example > 25k) it takes noticable longer to parse the
files, this commit caches the cluster.fw file and reduces parsing time

Signed-off-by: Stefan Hrdlicka <s.hrdlicka at proxmox.com>
---
 src/PVE/Firewall.pm | 108 ++++++++++++++++++++++++++++++--------------
 1 file changed, 75 insertions(+), 33 deletions(-)

diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm
index d40a9b1..8bb41ba 100644
--- a/src/PVE/Firewall.pm
+++ b/src/PVE/Firewall.pm
@@ -26,6 +26,12 @@ use PVE::Tools qw(run_command lock_file dir_glob_foreach);
 
 use PVE::Firewall::Helpers;
 
+PVE::Cluster::cfs_register_file(
+    "firewall/cluster.fw",
+    \&parse_clusterfw_config,
+    \&_save_clusterfw_conf
+);
+
 my $pvefw_conf_dir = "/etc/pve/firewall";
 my $clusterfw_conf_filename = "$pvefw_conf_dir/cluster.fw";
 
@@ -2953,23 +2959,28 @@ sub parse_alias {
     return undef;
 }
 
-sub generic_fw_config_parser {
-    my ($filename, $cluster_conf, $empty_conf, $rule_env) = @_;
-
-    my $section;
-    my $group;
+sub parse_clusterfw_config {
+    my ($filename, $raw) = @_;
+    my $empty_conf = {
+	rules => [],
+	options => {},
+	aliases => {},
+	groups => {},
+	group_comments => {},
+	ipset => {} ,
+	ipset_comments => {},
+    };
 
-    my $res = $empty_conf;
+    return _generic_fw_config_parser($filename, $empty_conf, $empty_conf, 'cluster', $raw);
+}
 
-    my $raw;
-    if ($filename =~ m!^/etc/pve/(.*)$!) {
-	$raw = PVE::Cluster::get_config($1);
-    } else {
-	$raw = eval { PVE::Tools::file_get_contents($filename) }; # ignore errors
-    }
-    return {} if !$raw;
+sub _generic_fw_config_parser {
+    my ($filename, $cluster_conf, $empty_conf, $rule_env, $raw) = @_;
 
+    my $section;
+    my $group;
     my $curr_group_keys = {};
+    my $res = $empty_conf;
 
     my $linenr = 0;
     while ($raw =~ /^\h*(.*?)\h*$/gm) {
@@ -3132,6 +3143,26 @@ sub generic_fw_config_parser {
     return $res;
 }
 
+sub generic_fw_config_parser {
+    my ($filename, $cluster_conf, $empty_conf, $rule_env) = @_;
+
+    my $section;
+    my $group;
+
+    my $res = $empty_conf;
+
+    my $raw;
+    if ($filename =~ m!^/etc/pve/(.*)$!) {
+	$raw = PVE::Cluster::get_config($1);
+    } else {
+	$raw = eval { PVE::Tools::file_get_contents($filename) }; # ignore errors
+    }
+    return {} if !$raw;
+
+    my $curr_group_keys = {};
+    return _generic_fw_config_parser($filename, $cluster_conf, $empty_conf, $rule_env, $raw);
+}
+
 # this is only used to prevent concurrent runs of rule compilation/application
 # see lock_*_conf for cfs locks protectiong config modification
 sub run_locked {
@@ -3544,26 +3575,42 @@ sub lock_clusterfw_conf {
 sub load_clusterfw_conf {
     my ($filename) = @_;
 
-    $filename = $clusterfw_conf_filename if !defined($filename);
-    my $empty_conf = {
-	rules => [],
-	options => {},
-	aliases => {},
-	groups => {},
-	group_comments => {},
-	ipset => {} ,
-	ipset_comments => {},
-    };
+    # special case for tests
+    if ($filename) {
+	my $empty_conf = {
+	    rules => [],
+	    options => {},
+	    aliases => {},
+	    groups => {},
+	    group_comments => {},
+	    ipset => {} ,
+	    ipset_comments => {},
+	};
+
+	my $cluster_conf = generic_fw_config_parser($filename, $empty_conf, $empty_conf, 'cluster');
+	$set_global_log_ratelimit->($cluster_conf->{options});
 
-    my $cluster_conf = generic_fw_config_parser($filename, $empty_conf, $empty_conf, 'cluster');
-    $set_global_log_ratelimit->($cluster_conf->{options});
+	return $cluster_conf;
+
+    } else {
+	my $res = {};
+	eval { $res = PVE::Cluster::cfs_read_file("firewall/cluster.fw"); };
+	warn $@ if $@;
+
+	return $res;
+    }
 
-    return $cluster_conf;
 }
 
 sub save_clusterfw_conf {
     my ($cluster_conf) = @_;
 
+    PVE::Cluster::cfs_write_file("firewall/cluster.fw", $cluster_conf)
+}
+
+sub _save_clusterfw_conf {
+    my ($filename, $cluster_conf) = @_;
+
     my $raw = '';
 
     my $options = $cluster_conf->{options};
@@ -3595,13 +3642,7 @@ sub save_clusterfw_conf {
 	    $raw .= "\n";
 	}
     }
-
-    if ($raw) {
-	mkdir $pvefw_conf_dir;
-	PVE::Tools::file_set_contents($clusterfw_conf_filename, $raw);
-    } else {
-	unlink $clusterfw_conf_filename;
-    }
+    return $raw
 }
 
 sub lock_hostfw_conf : prototype($$$@) {
@@ -4601,4 +4642,5 @@ sub update {
     run_locked($code);
 }
 
+
 1;
-- 
2.30.2






More information about the pve-devel mailing list