Code:
#!/usr/bin/perl
#**************************************************************
#
# PERL SCRIPT
# This script restarts the Application
#
#
##**************************************************************
$ENV{'IFS'} = ' ';
#open(STDERR,">&STDOUT");
#select STDOUT;
$|=1;
push(@INC, "/usr/share/perl/5.6.1");
push(@INC, "/usr/share/perl/5.8.0");
use Getopt::Long;
use FileHandle;
use sigtrap 'handler' => \&signal_handler, 'normal-signals', 'error-signals', 'old-interface-signals';
use Errno qw(EAGAIN);
@optl = ("w=i", "p=i", "log=s");
GetOptions @optl;
chomp($echo = `which echo`);
chomp($grep = `which grep`);
chomp($ps = `which ps`);
chomp($evlsend = `which evlsend`);
$evt_success = "iden.ha.mpm.start_app";
$evt_failure = "iden.ha.mpm.stop_app_failure";
$ospf_script = "/usr/app/ha/admin/configureOSPF.sh";
$ospf_option = "-s";
$dhcp_script = "/etc/init.d/dhcp";
$dhcp_option = "stop";
$tftp_script = "/usr/app/ha/admin/tftp_setup.pl";
$tftp_option = "--notftpd";
$sleep_time = 2;
$retries = 3;
$kill_success = 0;
$failure = 0;
$p_ppid = getppid;
$c_ppid = $$;
$start_app = "/usr/app/ha/admin/start_app.pl";
$scr_log_dir = "/usr/app/ha/tmp";
$exit_status = 1;
$ckpt_clean = "/usr/app/ha/admin/ckptclean.pl";
$stop_app_file = "/usr/app/config/stop_app_task";
$stop_app_precfg = "/usr/app/config/stop_app_preconfig";
$ha_cleanup = "/usr/app/ha/admin/ha_cleanup.pl";
$max_app_cfg = 8;
chomp($killall = `which killall`);
chomp($pidof = `which pidof`);
$log_file = "$scr_log_dir/restart_app.$$";
$app_log = "/dev/null";
chomp($priocntl = `which priocntl`);
$platform_type = &get_install_value("PT_PLATFORM_TYPE", "cx2600");
if ($platform_type eq "ATCA-7367") {
$dhcp_script = "/etc/init.d/dhcpd";
}
`rm -rf \`find $scr_log_dir -name 'restart_app.*' -mtime +7 -print\``;
open(FILE, ">$log_file");
$ha_cleanup = "/usr/app/ha/admin/ha_cleanup.pl";
autoflush FILE 1;
if($opt_log)
{
$app_log = $opt_log;
print FILE "logging out to file ($app_log)...";
}
open(STDOUT, ">$app_log");
open(STDERR, ">&STDOUT");
FORK: {
if($pid = fork) {
if( $opt_w ) {
print FILE "waiting for child to complete...\n";
wait;
exit($?);
}
#Return exit status of child
exit(0);
}elsif ($! == EAGAIN) {
sleep 5;
redo FORK;
}elsif (defined $pid) { #I'm the child
# If I was not called with the -w option, it means that I was called
# from MPMT. Therefore I need to check and see whether a start_app.pl
# is running, if it is, I need to wait for a bit of time until the
# buff pools etc are created completely before I will kill all of it,
# otherwise, for some reason, the tasks do not get killed effectively.
#
chomp(@start_script = `$ps ax | grep $start_app | grep -v grep | awk '{print \$1}'`);
if(@start_script) {
$ts=localtime();
print FILE "$ts: Killing $start_app(@start_script)\n";
kill ("KILL", @start_script);
}
#Kill PST
chomp($pst = `$pidof pst`);
if($pst) {
$ts=localtime();
&run_script("$ts:KILL PST", "$killall -s KILL pst");
}
# Check if another restart_app.pl process is running. If so, then sleep
# until the process dies or 120 seconds have passed. If latter, exit.
&wait_for_process($0, 5, 12, 1);
#Call switchover script if it exists
if( -e $ospf_script ) {
&switchover();
}
#Stop the dhcp server on this card
if( -e $dhcp_script) {
my($script) = $dhcp_script . " " . $dhcp_option;
&run_script("Stopping dhcp server", $script);
}
#Stop the tftp server on this card
if( -e $tftp_script) {
my($script) = $tftp_script . " " . $tftp_option;
&run_script("Stopping dhcp server", $script);
}
#Call appropriate stop_app scripts to stop the app
&post_event("iden.ha.stop_app");
$count = 0;
$count_succ = 0;
for($i = 1; $i <= $max_app_cfg; $i++) {
$tmp_var = "";
$tmp_var = $stop_app_file . "$i";
if( -e $tmp_var ) {
$count++;
if( ($rv = &run_script("STOP APP $i", $tmp_var)) < 0 ){
print FILE "$tmp_var returned error [$rv]\n";
$failure++;
}else{
$count_succ++;
print FILE "$tmp_var returned $rv success!\n";
}
}
}
# All the processes are killed by now, lets cleanup /tmp
#Check for preconfig script and run it if it exists
if( -e $stop_app_precfg ) {
$mypid = $$;
$count = 0;
open(PRIO, "$priocntl -d $mypid|");
while(<PRIO>) {
if($count == 1) {
$count++;
}elsif($count == 2) {
chop;
@slist = split(/\s+/);
$slist[2] =~ s/SCHED_//g;
last;
}elsif(/CLASS/) {
$count++;
}
}
close(PRIO);
if( ($rv = &run_script("PRE-STOP sched_policy", "$priocntl -c OTHER -p 0 $mypid")) < 0) {
print FILE "pre-stop sched_policy failed!!!\n";
$sched=0;
}else{
$sched++;
}
if( ($rv = &run_script("PRECFG", $stop_app_precfg)) < 0 ) {
print FILE "$stop_app_precfg returned error [$rv]\n";
$failure++;
}else{
printf FILE "$stop_app_precfg returned success!\n";
}
if($sched == 1) {
$rv = &run_script("POST-stop sched_policy", "$priocntl -c $slist[2] -p $slist[3] $mypid");
if($rv != 0) {
print FILE "running POST-stop sched failed, exiting [$rv]\n";
$failure++;
}
}
}
if( -e $ckpt_clean ) {
if( (&run_script("Cleanup checkpoint", $ckpt_clean)) < 0 ) {
print FILE "ERROR: $ckpt_clean script failed...\n";
}
}
if( -e $ha_cleanup ) {
if( (&run_script("HA Cleanup checkpoint", $ha_cleanup)) < 0 ) {
print FILE "ERROR: $ha_clean script failed...\n";
}
}
if( !$failure ) {
$event = $evt_success;
$exit_status = 0;
}else{
$event = $evt_failure;
$exit_status = -1;
}
if( $opt_w eq "" ) {
&post_event($event);
}
close(FILE);
exit($exit_status);
}else{
print FILE "weird fork error $!\n";
exit(-1);
}
}
sub check_processes {
my($str, $arr_ref) = @_;
my($pids) = "";
my($ps_line) = "";
my(@arr) = @$arr_ref;
my($val);
# This block eliminates the shell called from start_app.pl, the parent
# of this child, and the child itself.
# $ppid is the process id of the grand parent of the child (i.e. it
# could either be MPMT which calls the stop_app.pl or the shell called
# from start_app.pl which calls it as system(stop_app.pl).
# $c_ppid is the process of this forked child's parent which we also
# want to ignore.
#
$ps_line = "| $grep $str | $grep -v grep ";
foreach $val (@arr) {
if( $val ne "" ) {
$ps_line .= "| $grep -v ";
$ps_line .= $val;
}
}
open(PS, "$ps $ps_opt $ps_line|");
while(<PS>) {
chop;
@ps_list = split(/\s+/, $_);
$pids .= "$ps_list[1] ";
}
close(PS);
return($pids);
}
sub switchover {
my($script) = $ospf_script . " " . $ospf_option;
if( (&run_script("ConfigureOSPF script", $script)) < 0 ) {
print FILE "ERROR: switching over - $ospf_script returned $?\n";
$failure++;
}else{
print FILE "Switchover successful...\n";
}
}
sub run_script {
my($name, $script) = @_;
my($rc) = 0;
my($rv) = -1;
my($signal) = 0;
my($scr);
my($one);
my($two);
($scr, $one, $two) = split(/\s+/, $script, 3);
if( (-e $scr) != 1 ) {
print FILE "ERROR: $script does not exist!!\n";
return $rv;
}
$rc = 0xffff & system $script;
$ts=localtime();
printf FILE "$ts system(%s) returned 0x%#04x: \n", $name, $rc;
if( $rc == 0 ) {
print FILE "$name returned success...\n";
$rv = 0;
}elsif( $rc == 0xffff ) {
print FILE "ERROR: $name could not execute!!!!\n";
}elsif( ($rc & 0xff) == 0 ) {
$rc >>= 8;
print FILE "ERROR: $name returned with non-zero exit
status ($rc)!!!\n";
}else {
print FILE "ERROR: $name Got signal $rc!!!\n";
}
return $rv;
}
sub post_event {
my($event) = @_;
my($count) = $retries;
while ($count > 0) {
$ts=localtime();
if( system("$evlsend -f iden -t 0x8100 -m '$event'") != 0 ) {
print FILE "$ts:ERROR: could not post event $event...\n";
$count--;
}else{
print FILE "$ts:Posted event $event\n";
$count = 0;
}
}
}
sub signal_handler {
my($sig) = @_;
print FILE "received signal SIG$sig...\n";
&post_event($evt_failure);
die;
}
sub wait_for_process {
my($script, $s_time, $num, $quit) = @_;
my($pid) = "";
my($count) = 0;
my($num_sec) = 0;
my(@lst) = ("samt", $$, $c_ppid, $p_ppid);
my($rv) = -1;
while(1) {
$pid = &check_processes($script, \@lst);
if($pid eq "") {
$rv = 0;
return($rv);
}else{
print FILE "process $script found, sleeping for $s_time seconds\n";
sleep $s_time;
$count++;
}
if( $count >= $num ) {
last;
}
}
$num_sec = $count * $s_time;
print FILE "ERROR: slept for longer than $num_sec seconds!!!!!\n";
if($quit) {
print FILE "exiting...\n";
exit(-1);
}else{
print FILE "continuing...\n";
return($rv);
}
}
sub get_install_value {
my ($delim, $value) = @_;
my $path = "/etc";
my $file = "install_values";
$path = "/etc/pt" if (-f "/etc/pt/$file" && ! -f "$path/$file");
$iv = "$path/$file";
if (-f $iv) {
open(F, $iv);
while(<F>) {
if($_ =~ /$delim=(.+)/) {
$value = $1;
}
}
close(F);
}
return $value;
}