#! /usr/bin/perl 
#
# jira-alert.pl - create a Jira issue based on an Lithium alert notification.
#
# 2008 Andrew J Cosgriff, In Systems <ajc@insys.com.au>
#
# based on the distributed Lithium action scripts.
#
use XML::Simple; 
use Net::SMTP; 
use Data::Dumper; 
use Time::CTime; 
use XMLRPC::Lite;
use BerkeleyDB;

###################################
#  Script Configuration Variables
###################################
my $issuecache_filename = '/var/tmp/lithium-jira.db';

%xmlstruct = (  'desc' => "Jira Task Creator Notification Script",
                'version' => '1.0',
                'config_variable'=> [
                              {
                                'name' => 'jira_url',
                                'required' => '1',
                                'desc' => 'Jira URL'
                              },
                              {
                                'name' => 'project',
                                'required' => '1',
                                'desc' => 'Jira Project to add the task to'
                              },
                              {
                                'name' => 'assign_to',
                                'required' => '1',
                                'desc' => 'Jira username to assign task to'
                              },
                              {
                                'name' => 'user',
                                'required' => '1',
                                'desc' => 'Jira username for API access'
                              },
                              {
                                'name' => 'passwd',
                                'required' => '1',
                                'desc' => 'Jira password for API access'
                              }
                 ]
            );


###################################
#  Command processing
###################################

($ARGV[0] eq "info") and ($#ARGV == 0) and
   print &generateConfig($xmlroot, \%xmlstruct);
 
($ARGV[0] eq "report") and ($#ARGV != 0) and
  reportIncident($ARGV[$#ARGV]);

($ARGV[0] eq "remind") and ($#ARGV != 0) and
  remindIncident($ARGV[$#ARGV]);

($ARGV[0] eq "clear") and ($#ARGV != 0) and
  clearIncident($ARGV[$#ARGV]);

###################################
# Handling of an incident report
###################################

sub reportIncident
{
  # 1 Parameter: Filename for the XML
  my ($filename) = @_;

  # Retrieve action from ARGV 
  %action = &getAction();
  
  # Extract Variables from XML and store in %variables Hash
  %variables = &getVariables($filename);
   
  # Set variables from XML
  my $jira_url  = %variables->{jira_url}->{value};
  my $project   = %variables->{project}->{value};
  my $assign_to = %variables->{assign_to}->{value};
  my $user      = %variables->{user}->{value};
  my $passwd    = %variables->{passwd}->{value};

  # Design email content
  my $subject = "Lithium: ";
  $subject .= " " . %action->{device};
  $subject .= " at " . %action->{site};
  $subject .= " " . %action->{container};
  $subject .= " " . %action->{object};
  $subject .= " " . %action->{metric};
  $subject .= " " . %action->{trigger};
  my $content = "This is an automated incident report from Lithium.\n\n";
  $content .= ctime(%action->{start_time});
  $content .= "\nThe value of the " . %action->{metric};
  $content .= " metric for " . %action->{container} . " ";
  $content .= %action->{object} . " on device " . %action->{device} . " at " . %action->{site};
  $content .= " exceeded the pre-defined " . %action->{trigger} . " trigger.\n\n";
  $content .= "Incident ID:   " . %action->{incident_id} . "\n";
  $content .= "Site:          " . %action->{site} . "\n";
  $content .= "Device:        " . %action->{device} . "\n";
  $content .= "Container:     " . %action->{container} . "\n";
  $content .= "Object:        " . %action->{object} . "\n";
  $content .= "Metric:        " . %action->{metric} . "\n";
  $content .= "Trigger:       " . %action->{trigger} . "\n\n";
  
  if (%action->{state} eq "0") { $content .= "Current State: Normal\n\n" };
  if (%action->{state} eq "1") { $content .= "Current State: Warning\n\n" };
  if (%action->{state} eq "2") { $content .= "Current State: Impaired\n\n" };
  if (%action->{state} eq "3") { $content .= "Current State: Critical\n\n" };
  
  $content .= "Start Time:    " . ctime(%action->{start_time}) . "\n";
  if (%action->{end_time} != 0) { $content .= "End Time:      " . ctime(%action->{end_time}) . "\n\n"; }

  # Create task in Jira
  my $jira = XMLRPC::Lite->proxy($jira_url . '/rpc/xmlrpc');
  my $auth = $jira->call("jira1.login", $user, $passwd)->result();
  my $call = $jira->call("jira1.createIssue", $auth, {
      'project'	    => $project,
      'type'	    => 1,	# bug
      'priority'    => 3,	# major
      'assignee'    => $assign_to,
      'summary'	    => $subject,
      'description' => $content});
  my $fault = $call->fault();
  my $jira_issue;
  my $lithium_id = %action->{incident_id};
  if (defined $fault) {
      print "report: " . $call->faultstring();
      die $call->faultstring();
  } else {
      my $res=$call->result();
      $jira_issue=$res->{'key'};
      #print Dumper($res);
      print "jira issue $jira_issue created for lithium incident $lithium_id\n";
  }
  $jira->call("jira1.logout", $auth);

  # update our mapping table
  my $db = tie (my %ids, BerkeleyDB::Hash,
		-Filename => $issuecache_filename,
		-Flags => DB_CREATE);
  $ids{$lithium_id} = $jira_issue;
  untie %ids;
}

############################################
# Handling of an incident reminder (re-run)
############################################

sub remindIncident
{
  # 1 Parameter: Filename for the XML
  
  my ($filename) = @_;

  # Retrieve action from ARGV 
  %action = &getAction();
  
  # Extract Variables from XML and store in %variables Hash
  %variables = &getVariables($filename);
   
  # Set variables from XML
  my $jira_url  = %variables->{jira_url}->{value};
  my $project   = %variables->{project}->{value};
  my $assign_to = %variables->{assign_to}->{value};
  my $user      = %variables->{user}->{value};
  my $passwd    = %variables->{passwd}->{value};

  # Design email content
  my $subject = "Lithium: ";
  $subject .= " " . %action->{device};
  $subject .= " at " . %action->{site};
  $subject .= " " . %action->{container};
  $subject .= " " . %action->{object};
  $subject .= " " . %action->{metric};
  $subject .= " " . %action->{trigger};
  my $content = "This is an automated reminder of an existing incident from Lithium.\n\n";
  $content .= ctime(%action->{start_time});
  $content .= "\nThe value of the " . %action->{metric};
  $content .= " metric for " . %action->{container};
  $content .= %action->{object} . " on device " . %action->{device} . " at " . %action->{site};
  $content .= " exceeded the pre-defined " . %action->{trigger} . " trigger.\n\n";
  $content .= "Incident ID:   " . %action->{incident_id} . "\n";
  $content .= "Site:          " . %action->{site} . "\n";
  $content .= "Device:        " . %action->{device} . "\n";
  $content .= "Container:     " . %action->{container} . "\n";
  $content .= "Object:        " . %action->{object} . "\n";
  $content .= "Metric:        " . %action->{metric} . "\n";
  $content .= "Trigger:       " . %action->{trigger} . "\n\n";
  
  if (%action->{state} eq "0") { $content .= "Current State: Normal\n\n" };
  if (%action->{state} eq "1") { $content .= "Current State: Warning\n\n" };
  if (%action->{state} eq "2") { $content .= "Current State: Impaired\n\n" };
  if (%action->{state} eq "3") { $content .= "Current State: Critical\n\n" };
  
  $content .= "Start Time:    " . ctime(%action->{start_time}) . "\n";
  if (%action->{end_time} != 0) { $content .= "End Time:      " . ctime(%action->{end_time}) . "\n\n"; }

  # grab the issue from our mapping table
  my $lithium_id = %action->{incident_id};
  my $db = tie (my %ids, BerkeleyDB::Hash,
		-Filename => $issuecache_filename,
		-Flags	  => DB_CREATE);
  my $jira_issue = $ids{$lithium_id};
  untie %ids;

  # Comment on the task in Jira
  my $jira = XMLRPC::Lite->proxy($jira_url . '/rpc/xmlrpc');
  my $auth = $jira->call("jira1.login", $user, $passwd)->result();
  my $call = $jira->call("jira1.addComment", $auth, $jira_issue, $content);
  my $fault = $call->fault();
  if (defined $fault) {
      print "remind: " . $call->faultstring();
      die $call->faultstring();
  } else {
      my $res=$call->result();
      print "jira issue $jira_issue updated for lithium incident $lithium_id\n";
  }
  $jira->call("jira1.logout", $auth);
}

###########################################
# Handling of incident cleared
###########################################

sub clearIncident
{
  # 1 Parameter: Filename for the XML
  
  my ($filename) = @_;

  # Retrieve action from ARGV 
  %action = &getAction();
  
  # Extract Variables from XML and store in %variables Hash
  %variables = &getVariables($filename);
   
  # Set variables from XML
  my $jira_url  = %variables->{jira_url}->{value};
  my $project   = %variables->{project}->{value};
  my $assign_to = %variables->{assign_to}->{value};
  my $user      = %variables->{user}->{value};
  my $passwd    = %variables->{passwd}->{value};

  # Design email content
  my $content = "This is an automated incident cleared/resolved report from Lithium.\n\n";
  $content .= ctime(%action->{end_time});
  $content .= "\nThe value of the " . %action->{metric};
  $content .= " metric for " . %action->{container};
  $content .= %action->{object} . " on device " . %action->{device} . " at " . %action->{site};
  $content .= " is no longer within the pre-defined " . %action->{trigger} . " trigger range.\n\n";
  $content .= "Incident ID:   " . %action->{incident_id} . "\n";
  $content .= "Site:          " . %action->{site} . "\n";
  $content .= "Device:        " . %action->{device} . "\n";
  $content .= "Container:     " . %action->{container} . "\n";
  $content .= "Object:        " . %action->{object} . "\n";
  $content .= "Metric:        " . %action->{metric} . "\n";
  $content .= "Trigger:       " . %action->{trigger} . "\n\n";
  
  $content .= "Start Time:    " . ctime(%action->{start_time}) . "\n";
  if (%action->{end_time} != 0) { $content .= "End Time:      " . ctime(%action->{end_time}) . "\n\n"; }

  # grab the issue from our mapping table
  my $lithium_id = %action->{incident_id};
  my $db = tie (my %ids, BerkeleyDB::Hash,
		-Filename => $issuecache_filename,
		-Flags => DB_CREATE);
  my $jira_issue = $ids{$lithium_id};
  delete $ids{$lithium_id};
  untie %ids;

  # Comment on the task in Jira
  my $jira = XMLRPC::Lite->proxy($jira_url . '/rpc/xmlrpc');
  my $auth = $jira->call("jira1.login", $user, $passwd)->result();
  my $call = $jira->call("jira1.addComment", $auth, $jira_issue, $content);
  my $fault = $call->fault();
  if (defined $fault) {
      print $call->faultstring();
      die "clear: " . $call->faultstring();
  } else {
      my $res=$call->result();
      print "jira issue $jira_issue updated for lithium incident $lithium_id\n";
  }
  $jira->call("jira1.logout", $auth);
}

###########################################
# Standard Functions
###########################################

sub generateConfig 
{
  # Create the XML Config file. 
  # You don't have to make changes to this sub.
  # To make changes to this XML Structure:
  #   Modify %xmlstruct at the begining of this file

  # Parameter 1: Temporary XML File
  my ($xmlrool) = $_[0];
  my (%struct) = %{$_[1]};
  
  my $xml = new XML::Simple(NoAttr=>1, RootName=>"action_script",XMLDecl=>1);
  $data = $xml->XMLout(\%struct);
  return "$data";
}

sub getVariables 
{
  # Parameter: Filename for the XML
  my ($filename) = @_;

  # ------>Collect XML Info Here <----------
  my $xml = new XML::Simple; # create new XML object
  my $data = $xml->XMLin($filename);
  my %variables =%{$data->{variable}};
  return %variables;
}

sub getAction
{
  my %action = ( incident_id => $ARGV[1],
                 entity_address => $ARGV[2],
                 state => $ARGV[3],
                 customer => $ARGV[4],
                 site => $ARGV[5],
                 device => $ARGV[6],
                 container => $ARGV[7],
                 object => $ARGV[8],
                 metric => $ARGV[9],
                 trigger => $ARGV[10],
                 run_count => $ARGV[11],
                 start_time => $ARGV[12],
                 end_time => $ARGV[13]
               );
  return %action;
}
