#!/usr/bin/perl use Term::ReadKey; use Getopt::Long; $interval = 600; $outsubdir = `date +'%Y%m%d-%H%M%S'`; chop $outsubdir; $outdir = "stresstest/$outsubdir"; system "mkdir -p $outdir"; system "rm -f stresstest/last"; system "ln -sf $outsubdir stresstest/last"; $ncrashes = 0; #$xslt_rstate = "xsltproc /usr/share/pvss_mockup/rstate.xsl"; # -------------------------------------------------------------------------- # Read configuration file # # The values can be overwritten with command line options # -------------------------------------------------------------------------- foreach $f ("/etc/trd/stresstest.cfg", $ENV{'HOME'}."/.stresstestrc") { open CFG, "<$f"; $line = 0; while() { $line++; if ( /^\#/ ) { next; } elsif ( /^\s*$/ ) { next; } elsif ( /target\s*([a-zA-Z0-9]*)/ ) { $target = $1; } elsif ( /tag\s*cfg\s*(\d*)/ ) { $tag_cfg = $1; } elsif ( /tag\s*init\s*(\d*)/ ) { $tag_init = $1; } elsif ( /tag\s*uncfg\s*(\d*)/ ) { $tag_uncfg = $1; } elsif ( /tag\s*reset\s*(\d*)/ ) { $tag_reset = $1; } elsif ( /tag\s*rstate\s*(\d*)/ ) { $tag_rstate = $1; } elsif ( /trigger\s*on\s*(.*)$/ ) { $trigger_on = $1; } elsif ( /trigger\s*off\s*(.*)$/ ) { $trigger_off = $1; } elsif ( /trigger\s*reset\s*(.*)$/ ) { $trigger_reset = $1; } elsif ( /rstate\s*format\s*(.*)$/ ) { $rstate_format = $1; } elsif ( /rstate\s*check\s*(.*)$/ ) { $rstate_check = $1; } elsif ( /xslt\s*command\s*(.*)$/ ) { print "warning: found obsolete line $line in $f\n"; } else { print "Syntax error in $f line $line\n"; exit; } } close CFG; } # -------------------------------------------------------------------------- # Parse command line options # -------------------------------------------------------------------------- $help = 0; $result = GetOptions ( "target|t=s" => \$target, "init-tag|i=i" => \$tag_init, "config-tag|c=i" => \$tag_cfg, "reset-tag|r=i" => \$tag_reset, "uncfg-tag|u=i" => \$tag_uncfg, "trigger-on|o=s" => \$trigger_on, "trigger-off|f=s" => \$trigger_off, "trigger-reset|R=s" => \$trigger_reset, "rstate-tag|s=i" => \$tag_rstate, "rstate-format|x=s" => \$rstate_format, "rstate-format|q=s" => \$rstate_check, "help|?" => \$help ); if ($help or ! defined $target or ! defined $trigger_reset or ! defined $trigger_on or ! defined $trigger_off or ! defined $tag_cfg or ! defined $tag_reset or ! defined $tag_init or ! defined $tag_uncfg or ! defined $tag_rstate or ! defined $rstate_format or ! defined $rstate_check ) { print_usage(); exit; } print "\nTarget: $target\n"; print "\nTags\n"; print " Init: $tag_init\n"; print " Configure: $tag_cfg\n"; print " rstate: $tag_rstate\n"; print " Reset: $tag_reset\n"; print " UnConfigure: $tag_uncfg\n"; print "\nTrigger Commands\n"; print " On: $trigger_on\n"; print " Off: $trigger_off\n"; print " Reset: $trigger_reset\n"; print "\nrstate Commands\n"; print " Format: $rstate_format\n"; print " Check: $rstate_check\n"; if ($#ignore_mcms >= 0) { print "\nIgnoring MCMs: "; foreach $i (@ignore_mcms) { print "$i "; } print"\n"; } print "\n"; open LOG, ">$outdir/log"; print "\n\nSetting up stresstest for $target "; mkdir $outdir; system $trigger_off; print "."; system "nginject '$target\@error' $tag_reset > /dev/null"; print "."; system "nginject '$target\@stdby' $tag_init > /dev/null"; print "."; system "nginject '$target\@cfg' $tag_uncfg > /dev/null"; print "."; system "nginject '$target\@init' $tag_cfg > /dev/null"; print "."; system $trigger_reset; print "."; print "\n"; chomp($d=`date`); print LOG "$d: configured with tag $tag_cfg\n"; run_rstate("begin"); system "cp --dereference $outdir/last.xml $outdir/begin.xml"; print "Send triggers for 10 seconds...\n\n"; system $trigger_on; sleep 10; system $trigger_off; run_rstate(); # main loop while (1) { eval { print "\nSend triggers for $interval seconds...\n\n"; local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required print_menu(); print "Enter command: "; alarm $interval; ReadMode 4; # Turn off controls keys while (not defined ($c = ReadKey(1))) {} ReadMode 0; # Reset tty mode }; # Stop timer and remember rest time $lastint = alarm 0; if ($@) { die unless $@ eq "alarm\n"; # propagate unexpected errors # timed out print "\n"; run_rstate(); } else { print "$c\n"; if ($c eq 'r') { run_rstate(); } elsif ($c eq 'i') { print "New interval: "; $interval = <>; chop $interval; } elsif ($c eq "q") { run_rstate("end"); system $trigger_off; system "cp --dereference $outdir/last.xml $outdir/end.xml"; print "Finished stress test: $ncrashes crashes\n"; chomp($d=`date`); print LOG "$d: finished stress test: $ncrashes crashes\n"; close LOG; exit; } else { print "Unknown command: $c\n"; } } } sub run_rstate { my $mode = shift; chomp($d=`date`); print "\nQuery rstate ($d)\n"; system $trigger_off; # Construct filename for intermediate rstate.xml $thedate = `date +%Y%m%d-%H%M%S`; chop $thedate; $filename = "rstate-$thedate.xml"; system "nginject '$target\@cfg' $tag_rstate > $outdir/$filename"; system "ln -sf $filename $outdir/last.xml"; if ($mode) { system "cp $outdir/$filename $outdir/$mode-$thedate.xml"; } @errlog = `cat $outdir/$filename | $rstate_format`; foreach $line (@errlog) { print LOG "$d: $line"; print "$line"; } #$result = system "$xslt_rstate $outdir/$filename | grep -v '^OK'"; if ( ! system "cat $outdir/$filename | $rstate_check" ) { print "Errors found in stresstest\n"; print "Configuring chambers with tag $tag_cfg\n"; $ncrashes++; system "cp --dereference $outdir/$filename $outdir/crash-$thedate.xml"; system "nginject '$target\@cfg' $tag_uncfg $tag_cfg > /dev/null"; chomp($d=`date`); print LOG "$d: configured with tag $tag_cfg\n"; } else { print "$ncrashes errors so far\n"; } system $trigger_on; } sub print_menu() { print <