From 85bd4a755f7218d04b44ebbc31cbeb5b00757590 Mon Sep 17 00:00:00 2001 From: Mikael Nordin Date: Sat, 10 Sep 2016 13:09:40 +0200 Subject: [PATCH] Create cluster_cron.pl --- cluster_cron.pl | 130 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 cluster_cron.pl diff --git a/cluster_cron.pl b/cluster_cron.pl new file mode 100644 index 0000000..e694220 --- /dev/null +++ b/cluster_cron.pl @@ -0,0 +1,130 @@ +#!/usr/bin/env perl +use warnings; +use strict; +use Sys::Hostname; + +# We need a common directory for our nodes to write and read state from plus a couple of cronfiles +my ($electiondir, $cronfile, $sharedcronfile) = @_; + +unless (-d $electiondir) { + mkdir $electiondir; +} + +# We need our name +my $hostname = hostname; + +# We also need to know the time +my $time = time; + + +# Get the nodes in the cluster +sub get_nodes { + # Our data type is a hash with the following fields + # name, time, numeric + my @nodes = (); + my @files = <$electiondir/*>; + foreach my $filename (@files) { + my $node = {}; + open(FILE, "<$filename") or die "Could not open file: $!"; + $filename =~ s/^$electiondir\///; + $node->{'name'} = $filename; + my $content = ; + chomp $content; + $node->{'time'} = $content; + $node->{'numeric'} = get_numeric($filename); + close FILE; + push @nodes, $node; + } + return @nodes; + + +} + + +# Simply write a unix timestamp to a file with our name on it +sub write_timestamp { + open(FILE,"+>$electiondir/$hostname"); + print FILE $time; + close FILE; + +} + +# Lets see if we are the active node +sub is_active { + + my @nodes = @_; + + # Assume you are active + my $state = 1; + # Loop all nodes + foreach my $node (@nodes) { + # Dont do anything if this is the node + unless ($node eq $node->{'name'}) { + # If it has been active in the last 120 seconds it is eligable + my $diff = $time - $node->{'time'}; + if( $diff < 120 ) { + # Go to passive mode if the numeric of that host is less than that of this host + if( get_numeric($hostname) > $node->{'numeric'} ) { + $state = 0 ; + } + } + } + } + return $state; +} + +# Turn a hostname in to a decimal number used for comparison, lowest numer gets to be active if it is working +sub get_numeric { + my ($host) = @_; + my @ascii = unpack 'C*', $host; + my $numeric = ''; + foreach my $val (@ascii) { + $numeric .= $val; + } + return $numeric + 0; +} + +# But a # infront of any actime crontab entry +sub comment_out { + my ($infile, $outfile) = @_; + open(INFILE,"<$infile"); + my $content = ''; + while(my $line = ) { + $line =~ s/(^(?!#))/#$1/g; + $content .= $line; + } + + close INFILE; + open(OUTFILE,"+>$outfile"); + print OUTFILE $content; + close OUTFILE; + +} + +# Remove a # from any crontab entry +sub uncomment { + my ($infile, $outfile) = @_; + open(INFILE,"<$infile"); + my $content = ''; + while(my $line = ) { + $line =~ s/^(#)([\d*])/$2/g; + $content .= $line; + } + + close INFILE; + open(OUTFILE,"+>$outfile"); + print OUTFILE $content; + close OUTFILE; + +} + +# Update timestamp +write_timestamp; + +# See if I am the one +if (is_active(get_nodes) ){ + uncomment $sharedcronfile, $cronfile; + +} else { + comment_out $cronfile, $sharedcronfile; +}