You have a private Cricket
server on your protected network that collects tons of information
from your routers and other nodes.
Some of these data are confidental.
Your network is behind a firewall. You don't want to allow any
incoming HTTP (or other) request from the Big Bad Internet to your
Cricket server but you want to share part of collected information
with the world. You cannot put the data collector outside the
firewall due to following reasons:
People could not be allowed to reach the protected Cricket server through the firewall. The solution is to create a second Cricket server (a public one) that does not collect info from routers but mirrors some data from internal server.
The question is: How to duplicate the selected information?
Any data transfer have to be initiated from the internal Cricket, external request must not be served. So some push method is allowed only.
The first idea that comes in mind is to copy out all RRD files
in every 5 minutes.
However this would consume too much resources (CPU and bandwidth)
in case of thousands of large databases.
Moreover the main problem is that re-reading gigabytes of (almost static) data
causes operating system disk cache to be flushed. RRD file structure
is constructed such a way that update affects only a small portion of the
file therefore it can be fast if it is in memory. Periodic wipe out of
cache makes RRD updates painfully slow.
Additionally there is no guarantee that the copied data will be consistent.
Updates can occur in the middle of the file transfer.
And finally: RRD files are platform dependent. You cannot move them
between different architectures (32/64 bit, little/big endian, etc.).
Fortunately cricket has a remarkable feature. The collector process is able to forward incoming data via SNMP traps. This behavior can be configured by the copy-to attribute of a target.
A daemon on the slave Cricket called trapcollector catches these traps and updates appropriate RRD files. (Download from here.)
This is almost an ideal solution in this case. There are only three further problems to solve:
sub trap { my($to, $spec, @data) = @_; # this is the OID for enterprises.webtv.wtvOps.wtvOpsTraps my($ent) = ".1.3.6.1.4.1.2595.1.1"; # this makes a oid->value map for the trap. Note that # we just fake up simple one-level OID's... it suits our needs. my($item, @vars); my($ct) = 1; foreach $item (@data) { my($type) = "string"; $type = "integer" if ($item =~ /^(\d+)$/); push @vars, $ct, $type, $item; $ct++; } _do(\&snmptrap, $to, $ent, hostname(), 6, $spec, @vars); } |
diff -urNad cricket-1.0.5~/lib/snmpUtils.pm cricket-1.0.5/lib/snmpUtils.pm --- cricket-1.0.5~/lib/snmpUtils.pm 2007-08-29 11:40:38.491721503 +0200 +++ cricket-1.0.5/lib/snmpUtils.pm 2007-08-29 11:41:24.520251565 +0200 @@ -120,7 +120,7 @@ my($type) = "string"; $type = "integer" if ($item =~ /^(\d+)$/); - push @vars, $ct, $type, $item; + push @vars, "$ent.$ct", $type, $item; $ct++; } _do(\&snmptrap, $to, $ent, hostname(), 6, $spec, @vars); |
#!/bin/sh REALSCRIPT=/opt/cricket/cricket/compile.real CONFIGDIR=/opt/cricket/cricket-config if [ -e $CONFIGDIR/config.db ] then find $CONFIGDIR -newer $CONFIGDIR/config.db -type f | grep -q . && $REALSCRIPT else $REALSCRIPT fi /opt/cricket/cricket-scripts/send-config |
#!/bin/sh SSHDIR=/opt/cricket/etc/.ssh CONFIGDIR=/opt/cricket/cricket-config TARGET=cricket@slave.cricket.yourdomain.org:/DUMMY RSYNCOPTS='-ltpr --delete' SSHOPTS="-i $SSHDIR/id_rsa-configsync" rsync $RSYNCOPTS \ -e "ssh $SSHOPTS" \ --exclude '*.local' \ --exclude config.db \ --exclude '.*.swp' \ --exclude '*~' \ --exclude '*.bak' \ $CONFIGDIR/./ $TARGET |
from="<IP address of master>", command="/usr/local/bin/restricted-rsync /var/cricket/config; /usr/bin/cricket-compile >&2", no-port-forwarding,no-X11-forwarding, no-agent-forwarding ssh-rsa <public key here> Cricket config synchronization |
So sshd on the slave host starts command
/usr/local/bin/restricted-rsync /var/cricket/config; /usr/bin/cricket-compile >&2
restricted-rsync is a general purpose wrapper around rsync that allows access to the given directory only. (This reduces the risk of compromised private key. Remote user can read/write only the preconfigured directory.) After copying config files, the compiler is started.
.*.swp *~ *.bak | Ignore the usual garbage. |
config.db | The binary database that will be rebuilt on the slave at the next moment. It is no use to transfer. |
*.local | This is the matter! |
Even if the master and slave hosts has the identical software configuration it may occur that you want minor differences in config files so synchronization should not be full. In real cases it often occurs that master and slave Cricket instances use different sets of directories especially datadir and scriptdir. They are defined in the config. How to avoid rsync to overwrite local settings? Put these in small config files that are included in the big config tree but are not transferred by rsync. In our case files matching *.local pattern are not synchronized.
At this moment we have only one local config file called Defaults.local in the top configdir:
# # Site Specific Top Level Defaults # Target --default-- dataDir = %auto-base%/../cricket-data/%auto-target-path% copy-to = trap:some-community@slave.cricket.yourdomain.org scriptdir = /opt/cricket/cricket-scripts |
Target --default-- dataDir = /var/cricket/data/%auto-target-path% scriptdir = /usr/share/cricket/utils collect = false view --default-- rrd-graph-args = "--slope-mode --font LEGEND:7: --font TITLE:18:" |
E.g. on the master you may run a command like this once a day from crontab:
rsync --recursive --delete --ignore-non-existing --ignore-existing \ -e "ssh -i $SSHDIR/id_rsa-rrdsync" \ $SRCDIR/./ cricket@slave.cricket.yourdomain.org:/var/cricket/config |
from="<IP address of master>", command="/usr/local/bin/restricted-rsync /var/cricket/data", no-port-forwarding,no-X11-forwarding, no-agent-forwarding ssh-rsa <another public key here> Cricket data synchronization |
Trapcollector can listen on IPv4 interfaces only. (This is due to some limitations of SNMP_Session PERL module.) If both master and slave host has IPv6 protocol stack you have to ensure that master Cricket tries to send UDP packets over IPv4. E.g. use IPv4 address in copy-to config line instead of domain name.