#!/usr/bin/perl -I/usr/local/lib/perl/agsi
# -I/home/bryan/sb/2.5/spintools_rpm/SOURCES/usr/local/lib/perl/agsi
# -I/usr/local/lib/perl/agsi
# -*-cperl-*-

@ISA = qw(Generic);

use vars qw(@optionlist);
use Tie::Persistent;
use SpinsupXML;
use Data::Dumper;
use Getopt::Long;
use Generic;
use POSIX ":sys_wait_h";

use vars qw(%Options);
tie %Options, 'Tie::Persistent', '/.auto_gsi.rc', 'rw';

my @modules = qw(SpinDescs EthInfo ProcFile VMDump Rnum GSIFiles HealthMail Cluster GetSupportInfo);
foreach my $mod (@modules){
#  print "Use $mod\n";
  eval "use $mod";
  if ($@) {
    print $@, "\n\n\n";
    exit(1);
  }
}

my @options = (
	       ['Sleep', 1, 'sleep', '=i'],
	       ['Save', 5, 'save', '=i'],
	       ['Control', '/etc/spin.d/auto_gsi.ctr', 'controlfile', '=s'],
	       ['Check', 255, 'check', '=i'],
	       ['SaveRC', 0, 'saverc', '', 1],
	       ['Daemon', 0, 'daemon', '', 1],
	       ['Help', 0, 'help', '', 1],
	       ['Log', '/dev/null', 'log', '=s', 1],
	       ['Debug', 0, undef, '=i', 1],
);

push(@main::optionlist, Generic::Options(__PACKAGE__, @options));

sub new {
    my $invocant = shift;
    my $class = ref($invocant) || $invocant;

    my $self = {};
    my $retval = bless($self, $class);
    $retval->_initall(\@options, @_);

    print Dumper($retval) if $self->{Debug};

    $| = 1;

    $self->{gsi} = GetSupportInfo->new();

#    print "Check is $self->{Check}\n";
    push (@{$self->{list}}, SpinDescs->new()) if $self->{Check} & 1;
    push (@{$self->{list}}, VMDump->new()) if $self->{Check} & 2;
    push (@{$self->{list}}, Rnum->new()) if $self->{Check} & 4;
    push (@{$self->{list}}, $self->{gsifiles} = GSIFiles->new()); # if $self->{Check} & 8;
    push (@{$self->{list}}, $self->{healthmail} = HealthMail->new()) if $self->{Check} & 16;
    push (@{$self->{list}}, $self->{cluster} = Cluster->new()) if $self->{Check} & 32;

    foreach my $efile (glob("/proc/net/nicinfo/eth*.info")){
      $efile =~ /(eth\d+)\.info/;
      my $match = $1;

      push (@{$self->{list}}, EthInfo->new(
				File => $efile,
			       )) if ($self->{Check} & 64) && $self->{Test};
    }
    push (@{$self->{list}}, ProcFile->(Prefix => "RA", File => "/proc/spin/stream.d/raStats")) if ($self->{Check} & 128) && $self->{Test};

    $retval;
}

my $pos = 0;
sub spin {
#  print "pos is $pos\n";
  if ($pos == 0){
    print " \\\r";
  } elsif ($pos == 1){
    print " -\r";
  } elsif ($pos == 2){
    print " /\r";
  } elsif ($pos == 3){
    print " |\r";
  }
  $pos++;
  $pos %= 4;
}

sub Run {
  my $self = shift;
  if ($self->{Daemon}){
    $self->Daemonize();
  }

  while (1){
    spin();
    foreach my $item (@{$self->{list}}){
      my $checkval;
      if ($checkval = $item->Check()){
	my $eventid;
	my $eventlocal = 0;
	my $eventtime = time();
	if ($self->{cluster} && ($item != $self->{cluster})){
	  $eventid = $self->{gsi}->GenEventID();
	  $eventlocal = 1;
	} else {
	  $eventid = $checkval;
	}

	my $msg = $item->Message();
	if (ref($msg) ne "HASH"){
	  print "Format no longer valid : " . $item . " => $msg\n";
	}
	print "$item Message returned " . Dumper($msg);
	my $cmsg = $self->{cluster}->Message(Force => $msg->{Cluster}, EventId => $eventid) if ($self->{cluster} && ($item != $self->{cluster}));
	if ($item == $self->{cluster}){
	  $cmsg = $msg;
	}

	my %event = (
		     identification => 'SPINSUP',
		     eventId => $eventid,
		     eventIsLocal => ($eventlocal ? "TRUE" : "FALSE"),
		     from => $self->{gsi}->GetFrom(),
		     generatedEpoch => $eventtime,
		     generatedLocal => scalar localtime($eventtime),
		     compatible => "1.0",
		    );
	$event{subject} = $msg->{Subject} if $msg->{Subject};
	$event{severity} = $msg->{Severity} if $msg->{Severity};

	# We can run GetSupportInfo since we're not over the GSIFile limit.  We may go over with this
	# run, but that's another problem.
	my $filename = "/tmp/HEADER-INFO";
	open(OF, ">$filename");
	SpinsupXML::print_container_start(*OF, 'headers');
	SpinsupXML::print_element(*OF, 'eventInfo', \%event);
	SpinsupXML::print_element(*OF, 'localNode', shift @{$cmsg->{PeerInfo}});
	while (@{$cmsg->{PeerInfo}}){
	    SpinsupXML::print_element(*OF, 'partnerNode', shift @{$cmsg->{PeerInfo}});
	  }
	SpinsupXML::print_container_end(*OF, 'headers');
	close(OF);

	$self->{gsi}->GetSupportInfo(%{$msg}, File => $filename, %event, LocalSave => !$self->{gsifiles}->GetValue());
	print "Back in main loop after running get_support_info\n";
	$item->Clear();
      }

      print "Check of $item returned $checkval\n" if ($checkval != 0);
    }
    select undef, undef, undef, $self->{Sleep};
  }

  exit;
}

# Sub:         Daemonize
#
# Description: Turns the running process into a daemon
#
# Arguments:   None
#
# Returns:     Nothing exciting currently.
sub Daemonize {
  my $self = shift;

  # cd to /
  chdir '/'                 or die "Can't chdir to /: $!";

  defined(my $pid = fork)   or die "Can't fork: $!";

  # Exit if this is the parent
  if ($pid){
#    print "Forked off child process $pid\n";
    exit;
  }

  # Redirect STDIN and STDOUT to /dev/null
  open STDIN, '/dev/null'   or die "Can't read /dev/null: $!";
  open STDOUT, ">$self->{Log}" or die "Can't write to $self->{Log}: $!";

  # Only the child remains.  Munge the command line so that we can find
  # this process using pidof...
  $0 = "auto_gsi";

  # Start a new session
  POSIX::setsid()                  or die "Can't start a new session: $!";

  # Dup stdout to stderr
  open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
}

# Note: Command line options always win
die "Error parsing command line"
  unless GetOptions(\%Options,
		    @optionlist,
		   );
my $obj = new main();
if ($Options{"main.Help"}){
  foreach my $option (@optionlist){
    my ($key, $type) = split(/=/, $option);
    print "-$key ";
    if ($type eq "s"){
      print "string";
    } elsif ($type eq "i"){
      print "integer";
    } elsif ($type eq ""){
      print "flag";
    } else {
      print "Unknown type $type";
    }
    print "\n";
  }
  exit 2;
}
exit 1 if $Options{"main.SaveRC"};
$obj->Run();
