use PVE::SafeSyslog;
use PVE::Tools;
use PVE::INotify;
+use PVE::APIClient::LWP;
use PMG::Utils;
use PMG::Config;
use PMG::RuleDB;
use PMG::RuleCache;
use PMG::MailQueue;
-use PVE::APIClient::LWP;
+use PMG::Fetchmail;
sub remote_node_ip {
my ($nodename, $noerr) = @_;
sub update_ssh_keys {
my ($cinfo) = @_;
+ my $old = '';
my $data = '';
+
foreach my $node (values %{$cinfo->{ids}}) {
$data .= "$node->{ip} ssh-rsa $node->{hostrsapubkey}\n";
$data .= "$node->{name} ssh-rsa $node->{hostrsapubkey}\n";
}
- PVE::Tools::file_set_contents($sshglobalknownhosts, $data);
+ $old = PVE::Tools::file_get_contents($sshglobalknownhosts, 1024*1024)
+ if -f $sshglobalknownhosts;
+
+ PVE::Tools::file_set_contents($sshglobalknownhosts, $data)
+ if $old ne $data;
$data = '';
+ $old = '';
# always add ourself
if (-f $ssh_rsa_id) {
$newdata .= "$line\n";
}
- PVE::Tools::file_set_contents($rootsshauthkeys, $newdata, 0600);
+ $old = PVE::Tools::file_get_contents($rootsshauthkeys, 1024*1024)
+ if -f $rootsshauthkeys;
+
+ PVE::Tools::file_set_contents($rootsshauthkeys, $newdata, 0600)
+ if $old ne $newdata;
}
my $cfgdir = '/etc/pmg';
return 0 if $new eq $old;
}
+ # set mtime (touch) to avoid time drift problems
+ utime(undef, undef, $srcfn);
+
rename($srcfn, $dstfn) ||
die "cond_rename_file '$filename' failed - $!\n";
};
sub sync_quarantine_files {
- my ($host_ip, $host_name, $flistname) = @_;
+ my ($host_ip, $host_name, $flistname, $rcid) = @_;
my $spooldir = $PMG::MailQueue::spooldir;
+ mkdir "$spooldir/cluster/";
+ my $syncdir = "$spooldir/cluster/$rcid";
+ mkdir $syncdir;
+
my $cmd = $rsync_command->(
- $host_name, '--timeout', '10', "${host_ip}:$spooldir", $spooldir,
+ $host_name, '--timeout', '10', "[${host_ip}]:$spooldir", $spooldir,
'--files-from', $flistname);
PVE::Tools::run_command($cmd);
mkdir $syncdir;
my $cmd = $rsync_command->(
- $host_name, '-aq', '--timeout', '10', "${host_ip}:$syncdir/", $syncdir);
+ $host_name, '-aq', '--timeout', '10', "[${host_ip}]:$syncdir/", $syncdir);
foreach my $incl (('spam/', 'spam/*', 'spam/*/*', 'virus/', 'virus/*', 'virus/*/*')) {
push @$cmd, '--include', $incl;
mkdir $syncdir;
my $cmd = $rsync_command->(
- $host_name, '-aq', '--timeout', '10', "${host_ip}:$syncdir", $syncdir);
+ $host_name, '-aq', '--timeout', '10', "[${host_ip}]:$syncdir", $syncdir);
PVE::Tools::run_command($cmd);
}
my $cmd = $rsync_command->(
$master_name, '-aq',
- "${master_ip}:$cfgdir/* ${sa_conf_dir}/${sa_custom_cf}",
+ "[${master_ip}]:$cfgdir/* ${sa_conf_dir}/${sa_custom_cf}",
"$syncdir/",
'--exclude', 'master/',
'--exclude', '*~',
$cond_commit_synced_file->('cluster.conf');
+ update_ssh_keys($cinfo); # rewrite ssh keys
+
+ PMG::Fetchmail::update_fetchmail_default(0); # disable on slave
+
my $files = [
'pmg-authkey.key',
'pmg-authkey.pub',
'pmg-csrf.key',
'ldap.conf',
'user.conf',
+ 'domains',
+ 'mynetworks',
+ 'transport',
+ 'tls_policy',
+ 'fetchmailrc',
];
foreach my $filename (@$files) {
$cond_commit_synced_file->($filename);
}
+
my $force_restart = {};
if ($cond_commit_synced_file->($sa_custom_cf, "${sa_conf_dir}/${sa_custom_cf}")) {
my $callback = sub {
my $ref = shift;
$maxid = $ref->{rid};
- print $flistfh "$ref->{file}\n";
+ my $filename = $ref->{file};
+ # skip files generated before cluster was created
+ return if $filename !~ m!^cluster/!;
+ print $flistfh "$filename\n";
};
my $attrs = [qw(cid rid time qtype bytes spamlevel info sender header file)];
close($flistfh);
my $starttime = [ gettimeofday() ];
- sync_quarantine_files($ni->{ip}, $ni->{name}, $flistname);
+ sync_quarantine_files($ni->{ip}, $ni->{name}, $flistname, $rcid);
$$rsynctime_ref += tv_interval($starttime);
if ($maxid) {
$mscount += $count;
- last if $mscount >= $maxmails;
-
- } while ($count >= $maxcount);
+ } while (($count >= $maxcount) && ($mscount < $maxmails));
PMG::DBTools::create_clusterinfo_default($ldb, $rcid, 'lastmt_CMSReceivers', 0, undef);
my $update_sth = $ldb->prepare(
"UPDATE CMSReceivers SET status = ? WHERE " .
- "CMailstore_CID = ? AND CMailstore_RID = ? AND PMail = ?;");
+ "CMailstore_CID = ? AND CMailstore_RID = ? AND TicketID = ?");
while (my $ref = $sth->fetchrow_hashref()) {
$update_sth->execute($ref->{status}, $ref->{cmailstore_cid},
- $ref->{cmailstore_rid}, $ref->{pmail});
+ $ref->{cmailstore_rid}, $ref->{ticketid});
}
PMG::DBTools::write_maxint_clusterinfo($ldb, $rcid, 'lastmt_CMSReceivers', $ctime);
$attrs = [qw(cstatistic_cid cstatistic_rid blocked receiver)];
PMG::DBTools::copy_selected_data($ldb, $sth, 'CReceivers', $attrs);
-
- PMG::DBTools::write_maxint_clusterinfo ($ldb, $rcid, 'lastid_CStatistic', $maxid);
}
+ PMG::DBTools::write_maxint_clusterinfo ($ldb, $rcid, 'lastid_CStatistic', $maxid);
+
$ldb->commit;
};
if (my $err = $@) {
$mscount += $count;
- last if $mscount >= $maxmails;
-
- } while ($count >= $maxcount);
+ } while (($count >= $maxcount) && ($mscount < $maxmails));
return $mscount;
}
return $updates;
};
+sub sync_localstat_db {
+ my ($dbh, $rdb, $ni) = @_;
+
+ my $rcid = $ni->{cid};
+
+ my $selectfunc = sub {
+ my ($ctime, $lastmt) = @_;
+ return "SELECT * from LocalStat WHERE mtime >= $lastmt AND cid = $rcid";
+ };
+
+ my $merge_sth = $dbh->prepare(
+ 'INSERT INTO LocalStat (Time, RBLCount, PregreetCount, CID, MTime) ' .
+ 'VALUES (?, ?, ?, ?, ?) ' .
+ 'ON CONFLICT (Time, CID) DO UPDATE SET ' .
+ 'RBLCount = excluded.RBLCount, PregreetCount = excluded.PregreetCount, MTime = excluded.MTime');
+
+ my $mergefunc = sub {
+ my ($ref) = @_;
+
+ $merge_sth->execute($ref->{time}, $ref->{rblcount}, $ref->{pregreetcount}, $ref->{cid}, $ref->{mtime});
+ };
+
+ return $sync_generic_mtime_db->($dbh, $rdb, $ni, 'LocalStat', $selectfunc, $mergefunc);
+}
+
sub sync_greylist_db {
my ($dbh, $rdb, $ni) = @_;
my $merge_sth = $dbh->prepare(
"INSERT INTO UserPrefs (PMail, Name, Data, MTime) " .
- 'VALUES (?, ?, ?, 0) ' .
+ 'VALUES (?, ?, ?, ?) ' .
'ON CONFLICT (PMail, Name) DO UPDATE SET ' .
# Note: MTime = 0 ==> this is just a copy from somewhere else, not modified
- 'MTime = CASE WHEN excluded.MTime >= UserPrefs.MTime THEN 0 ELSE UserPrefs.MTime END' .
+ 'MTime = CASE WHEN excluded.MTime >= UserPrefs.MTime THEN 0 ELSE UserPrefs.MTime END, ' .
'Data = CASE WHEN excluded.MTime >= UserPrefs.MTime THEN excluded.Data ELSE UserPrefs.Data END');
my $mergefunc = sub {
my ($ref) = @_;
- $merge_sth->execute($ref->{pmail}, $ref->{name}, $ref->{data});
+ $merge_sth->execute($ref->{pmail}, $ref->{name}, $ref->{data}, $ref->{mtime});
};
return $sync_generic_mtime_db->($dbh, $rdb, $ni, 'UserPrefs', $selectfunc, $mergefunc);