--- /dev/null
+#!/usr/bin/perl
+use strict;
+use XML::LibXML;
+use FindBin qw($Bin);
+
+my $parser = XML::LibXML->new();
+my $dom = $parser->parse_file($ARGV[1] || "$Bin/test_runner.xml");
+chomp (my $whoami = `whoami`);
+
+# XML file looks like this:
+# <config>
+# <local>
+# <report_path>~/public_html/</report_path>
+# <installer_path>/home/phasefx/git/random/</installer_path>
+# </local>
+# <hosts>
+# <host>
+# <name>qa01</name>
+# <description>qa01</description>
+# <target_ssh_user>phasefx</target_ssh_user>
+# <target_ssh_host>192.168.1.79</target_ssh_host>
+# <!-- Local Copy, relative to installer_path -->
+# <installer_scripts>installer/wheezy/</installer_scripts>
+# <!-- On Remote Host -->
+# <installer_invocation>/home/phasefx/eg_installer/wheezy/installer_installer2.sh /home/phasefx/eg_installer/wheezy/</installer_invocation>
+# </host>
+# </hosts>
+# </config>
+
+my $localconf = $dom->findnodes('//local')->[0];
+my $installer_path = $localconf->findvalue('./installer_path');
+
+foreach my $host ($dom->findnodes('//host')) {
+
+ my $pid;
+ next if $pid = fork; # Parent goes to next server.
+ die "fork failed: $!" unless defined $pid;
+
+ # inside the child process
+
+ my $name = $host->findvalue('./name');
+ my $description = $host->findvalue('./description');
+ my $target_ssh_user = $host->findvalue('./target_ssh_user') || $whoami;
+ my $target_ssh_host = $host->findvalue('./target_ssh_host');
+ my $target_ssh_path = $host->findvalue('./target_ssh_path') || "/home/$whoami/eg_installer";
+ my $installer_scripts = $host->findvalue('./installer_scripts');
+ my $installer_invocation = $host->findvalue('./installer_invocation');
+ my $output_path = $host->findvalue('./output_path') || "/home/$whoami/public_html/hosts/$name";
+ my $output_parser = $host->findvalue('./output_parser') || "$Bin/test_output_webifier.pl";
+
+ print "$pid *** Ensuring $output_path and related paths exist\n";
+ my @args = ('mkdir','-p',$output_path);
+ system(@args) == 0 or die "system @args failed: $?";
+ @args = ('mkdir','-p',"$output_path/archive/");
+ system(@args) == 0 or die "system @args failed: $?";
+ chomp(my $month = `date +%Y-%m`);
+ @args = ('mkdir','-p',"$output_path/archive/$month/");
+ system(@args) == 0 or die "system @args failed: $?";
+ chomp(my $time = `date +%F_%T`);
+ @args = ('mkdir','-p',"$output_path/archive/$month/$time/");
+ system(@args) == 0 or die "system @args failed: $?";
+
+ print "$pid *** Archiving previous output\n";
+ `(cd $output_path && mv *.* $output_path/archive/$month/$time/ && cp $output_path/archive/$month/$time/*.hash .)`;
+
+ print "$pid *** In Progress Page\n";
+ `cp test_output.css $output_path/`;
+ open FILE, ">$output_path/test.html";
+ print FILE '<html><head></head><body><h1>Testing in progress</h1>[<a href="archive/">Previous Runs</a>]</body></html>';
+ close FILE;
+ `(cd $output_path && ln -s test.html index.html)`;
+
+ print "$pid *** Ensuring $target_ssh_user\@$target_ssh_host:$target_ssh_path exists\n";
+ my @args = ('ssh',"$target_ssh_user\@$target_ssh_host", 'mkdir','-p',$target_ssh_path);
+ system(@args) == 0 or die "system @args failed: $?";
+
+ print "$pid *** Pushing $installer_path$installer_scripts to $target_ssh_user\@$target_ssh_host:$target_ssh_path\n";
+ @args = ('scp', '-r', $installer_path . $installer_scripts, "$target_ssh_user\@$target_ssh_host:$target_ssh_path");
+ system(@args) == 0 or die "system @args failed: $?";
+
+ print "$pid *** Test starting, writing to $output_path/output.txt\n";
+ my $cmd = "ssh $target_ssh_user\@$target_ssh_host $installer_invocation 1>$output_path/output.txt 2>&1";
+ print "$cmd\n";
+ `$cmd`;
+
+ print "$pid *** Test complete, prettifying results\n";
+ `cd $output_path && $output_parser output.txt`;
+
+ exit; # end the child process
+}
+
+1 while (wait() != -1); # wait for all child processes
+
+print "*** Finis\n";