#!/usr/bin/perl

# c3_add_cluster
#
# Written by Jason Brechin 03/25/03

use strict;
use Getopt::Long;
Getopt::Long::Configure ("pass_through");

my $add     = 0;
my $delete  = 0;
my @nodes   = ();
my $cluster = '';
my $zero    = 0;
my $list;
my $hostname= `hostname`;

my $c3conf = '/etc/c3.conf';

sub usage () {
  print "$0\n";
  print 'Written by Jason Brechin <brechin@ncsa.uiuc.edu>' . "\n\n";
  print "--help			Usage Information (this)\n";
  print "--add <name>		Adds cluster with given name\n";
  print "--rm <name>		Removes cluster with given name\n";
  print "--list <cluster>	Lists nodes in cluster\n";
  print "--listclusters		Lists defined clusters\n";
  print "--zero			Use 0-indexing\n";
  exit 1;
}

&GetOptions(
  'help|h|?' 	=> \&usage,
  'addcluster=s'=> \$add,
  'add=s'	=> \$add,
  'rmcluster=s'	=> \$delete,
  'rm=s'	=> \$delete,
  'zero|0|z'	=> \$zero,
  'list:s'	=> \$list,
  'l:s'		=> \$list,
#  '<>'		=> sub { push @nodes, @ARGV; },
);

@nodes = @ARGV;  # ARGV will now have all node names

if ( $add && $delete ) { 
  die "Can't specify a cluster to add and remove"; 
}
if ( defined($list) && ($add || $delete) ) { 
  die "Can't list AND add/delete"; 
}
if ( $add ) { 
  $delete = $add; 
}

if ( $delete && -e "$c3conf" ) {	
  open C3CONF, $c3conf or die "Couldn't open $c3conf";
  my @c3file = <C3CONF>;
  close(C3CONF);
  !system("cp $c3conf $c3conf.bak") or die "Couldn't create backup\n";
  open(C3OUT, ">$c3conf");
  my $incluster = 0;
  foreach my $line (@c3file) {
    if (!$incluster && $line =~ /cluster\s*(\S*)\s*\{/g) { #cluster begin
      $incluster = 1;
      $cluster = $1;
      if ( $delete eq $cluster ) { 
        $incluster = 0; 
      } else { 
        print C3OUT "$line"; 
      }
    } elsif ( $incluster && $line =~ /\}/g) { #cluster end
      $incluster = 0;
      print C3OUT "$line";
    } elsif ( $incluster ) { #in cluster, not end
      print C3OUT "$line";
    } else { #outside cluster
      ; 
    }
  }
  close(C3CONF);
}

if ($add) {
  if (-e "$c3conf") { 
    open(C3OUT, ">>$c3conf"); 
  } else { 
    open(C3OUT, ">$c3conf"); 
  }
  print C3OUT "cluster $add {\n";
  print C3OUT "\t$hostname";
  unless ($zero) { 
    print C3OUT "\tdead remove_for_0-indexing\n";
  }
  foreach my $node (@nodes) {
    print C3OUT "\t$node\n";
  }
  print C3OUT "}\n";
  close C3OUT;
}

if (defined($list) && -e "$c3conf") {
  open(C3IN, "$c3conf") or die "Couldn't open $c3conf";
  my @c3file = <C3IN>;
  close C3IN;
  my $incluster = 0;
  my $host = '';
  my @clusters;
  if ($list eq '') {
    foreach my $line (@c3file) {
      if (!$incluster && $line =~ /^\s*cluster\s*(\S*)\s*\{/g) {
	push @clusters, $1;
	$incluster = 1;
      } elsif ( $incluster && $line =~ /\}/g) { #cluster end
	$incluster = 0;
      } else  { 
        ; #do nothing
      }
    } 
  } else {
    foreach my $line (@c3file) {
      if (!$incluster && $line =~ /^\s*cluster\s*(\S*)\s*\{/g) { #cluster begin
        $incluster = 1;
        $cluster = $1;
        if ( $cluster ne $list ) { 
          $incluster = 0;
        }
      } elsif ( $incluster && $line =~ /\}/g) { #cluster end
        $incluster = 0;
      } elsif ( $incluster && !$host ) { #getting C3 host
        $host = $line;
      } elsif ( $incluster && $line =~ /^\s*dead/ ) { #dead node
        ; #do nothing
      } elsif ( $incluster ) { #in cluster, not end
        print "$line";
      } else { #outside cluster
        ; #do nothing
      }
    }
  }
  if ($list ne '' && !$host) { 
    exit 1; 
  } elsif ($list eq '') {
    if (scalar(@clusters)) {
      print scalar(@clusters);
      print " entries:\n@clusters\n";
    } else { 
      print "No clusters!"; 
    }
  } else { 
    exit 0; 
  }
}
