]> git.proxmox.com Git - pmg-api.git/blobdiff - PMG/Cluster.pm
PMG/Cluster.pm: implement sync_ruledb_from_master()
[pmg-api.git] / PMG / Cluster.pm
index bcdea5d75a0ea1f65c85b98852fac137e90266c6..5956143562cf8590dcfe77b23b5a656cf829b0c6 100644 (file)
@@ -10,8 +10,12 @@ use PVE::SafeSyslog;
 use PVE::Tools;
 use PVE::INotify;
 
+use PMG::Utils;
 use PMG::Config;
 use PMG::ClusterConfig;
+use PMG::RuleDB;
+use PMG::RuleCache;
+use PVE::APIClient::LWP;
 
 our $spooldir = "/var/spool/proxmox";
 
@@ -117,7 +121,7 @@ sub read_local_cluster_info {
        unlink $rootrsakey_fn;
        my $cmd = ['ssh-keygen', '-t', 'rsa', '-N', '', '-b', '2048',
                   '-f', $rootrsakey_fn];
-       PVE::Tools::run_command($cmd);
+       PMG::Utils::run_silent_cmd($cmd);
     }
 
     my $rootrsapubkey = PVE::Tools::file_read_firstline($rootrsapubkey_fn);
@@ -276,12 +280,15 @@ my $cond_commit_synced_file = sub {
 };
 
 sub sync_config_from_master {
-    my ($cinfo, $master_ip, $noreload) = @_;
+    my ($cinfo, $master_name, $master_ip, $noreload) = @_;
 
     my $local_ip = $cinfo->{local}->{ip};
     my $local_name = $cinfo->{local}->{name};
 
-    return if $local_ip eq $master_ip;
+    if ($local_ip eq $master_ip) {
+       print STDERR "local node is master - nothing to do\n";
+       return;
+    }
 
     mkdir $syncdir;
     File::Path::remove_tree($syncdir, {keep_root => 1});
@@ -289,7 +296,10 @@ sub sync_config_from_master {
     my $sa_conf_dir = "/etc/mail/spamassassin";
     my $sa_custom_cf = "custom.cf";
 
-    my $cmd = ['rsync', '--rsh=ssh -l root -o BatchMode=yes', '-lpgoq',
+    my $ssh_cmd = '--rsh=ssh -l root -o BatchMode=yes';
+    $ssh_cmd .=  " -o HostKeyAlias=${master_name}" if $master_name;
+
+    my $cmd = ['rsync', "--rsh=ssh -l root -o BatchMode=yes -o HostKeyAlias=${master_name}", '-lpgoq',
               "${master_ip}:$cfgdir/* ${sa_conf_dir}/${sa_custom_cf}",
               "$syncdir/",
               '--exclude', '*~',
@@ -346,4 +356,66 @@ sub sync_config_from_master {
     $cfg->rewrite_config(1, $force_restart);
 }
 
+sub sync_ruledb_from_master {
+    my ($ldb, $rdb, $ni, $ticket) = @_;
+
+    my $ruledb = PMG::RuleDB->new($ldb);
+    my $rulecache = PMG::RuleCache->new($ruledb);
+
+    my $conn = PVE::APIClient::LWP->new(
+       ticket => $ticket,
+       cookie_name => 'PMGAuthCookie',
+       host => $ni->{ip},
+       cached_fingerprints => {
+           $ni->{fingerprint} => 1,
+       });
+
+    my $digest = $conn->get("/config/ruledb/digest", {});
+
+    return if $digest eq $rulecache->{digest}; # no changes
+
+    syslog('info', "detected rule database changes - starting sync from '$ni->{ip}'");
+
+    eval {
+       $ldb->begin_work;
+
+       $ldb->do("DELETE FROM Rule");
+       $ldb->do("DELETE FROM RuleGroup");
+       $ldb->do("DELETE FROM ObjectGroup");
+       $ldb->do("DELETE FROM Object");
+       $ldb->do("DELETE FROM Attribut");
+
+       eval {
+           $rdb->begin_work;
+
+           # read a consistent snapshot
+           $rdb->do("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
+
+           PMG::DBTools::copy_table($ldb, $rdb, "Rule");
+           PMG::DBTools::copy_table($ldb, $rdb, "RuleGroup");
+           PMG::DBTools::copy_table($ldb, $rdb, "ObjectGroup");
+           PMG::DBTools::copy_table($ldb, $rdb, "Object", 'value');
+           PMG::DBTools::copy_table($ldb, $rdb, "Attribut", 'value');
+       };
+
+       $rdb->rollback; # end transaction
+
+       die $@ if $@;
+
+       # update sequences
+
+       $ldb->do("SELECT setval('rule_id_seq', max(id)+1) FROM Rule");
+       $ldb->do("SELECT setval('object_id_seq', max(id)+1) FROM Object");
+       $ldb->do("SELECT setval('objectgroup_id_seq', max(id)+1) FROM ObjectGroup");
+
+       $ldb->commit;
+    };
+    if (my $err = $@) {
+       $ldb->rollback;
+       die $err;
+    }
+
+    syslog('info', "finished rule database sync from host '$ni->{ip}'");
+}
+
 1;