Initial revision

master
penguinc 2005-06-27 06:48:59 +00:00
commit 54832ef8c3
7 changed files with 468 additions and 0 deletions

29
build.xml Normal file
View File

@ -0,0 +1,29 @@
<?xml version="1.0"?>
<project name="Mass" default="jar" basedir=".">
<property name="src" value="${basedir}/src" />
<property name="build" value="${basedir}/bin" />
<property name="output" value="${basedir}" />
<target name="clean" description="Cleans the source tree of build files">
<delete>
<fileset dir="${build}" />
<fileset dir="${output}" includes="*.jar" />
</delete>
</target>
<target name="build" description="Compiles the Java classes in the source directory">
<mkdir dir="${build}" />
<javac srcdir="${src}" destdir="${build}" source="1.4">
<compilerarg value="-Xlint:unchecked" />
</javac>
</target>
<target name="jar" depends="build" description="Makes a distributable Jar file for the project">
<jar jarfile="${output}/mass.jar" basedir="${build}" compress="true">
<manifest>
<attribute name="Main-Class" value="org.penguincoder.mass.Manager" />
</manifest>
</jar>
</target>
</project>

BIN
mass.jar Normal file

Binary file not shown.

View File

@ -0,0 +1,20 @@
package org.penguincoder.mass;
/*
* Created on Jan 2, 2005
*
*/
/**
* @author Andrew Coleman
*
*/
public class CMD extends Thread {
public CMD () {
super ();
}
public CMD ( ThreadGroup tg, String name ) {
super ( tg, name );
}
}

View File

@ -0,0 +1,62 @@
/*
* Created on Jun 23, 2005
*
*/
package org.penguincoder.mass;
import java.util.ArrayList;
/**
* @author Andrew Coleman
*
*/
public class CMDcopy extends CMD {
private String hostname;
private ArrayList fileset;
private String remoteDir;
private StringBuffer result;
private final static String lineSeparator = System
.getProperty ( "line.separator" );
public CMDcopy ( ArrayList fileset, String remoteDir, String hostname,
ThreadGroup tg, String threadName ) {
super ( tg, threadName );
this.hostname = hostname;
if ( remoteDir.equals ( "''" ) ) {
this.remoteDir = "";
} else {
this.remoteDir = remoteDir;
}
this.fileset = fileset;
this.result = null;
}
public void run () {
ArrayList toRun = new ArrayList ( 10 );
if ( System.getProperty ( "os.name" ).toLowerCase ().startsWith (
"windows" ) ) {
toRun.add ( "pscp" );
} else {
toRun.add ( "scp" );
}
toRun.addAll ( this.fileset );
toRun.add ( this.hostname + ":" + this.remoteDir );
result = Manager.getCommandOutput ( (String[]) toRun
.toArray ( new String[0] ) );
}
public String toString () {
if ( result == null )
return "";
StringBuffer out = new StringBuffer ( 2048 );
out.append ( "Secure copy results from '" + this.hostname + "'"
+ lineSeparator );
out.append ( result.toString () );
return out.toString () + lineSeparator;
}
}

View File

@ -0,0 +1,57 @@
/*
* Created on Jun 23, 2005
*
*/
package org.penguincoder.mass;
/**
* @author Andrew Coleman
*
*/
public class CMDrun extends CMD {
private String hostname;
private String command;
private StringBuffer result;
private final static String lineSeparator = System
.getProperty ( "line.separator" );
public CMDrun ( String command, String hostname, ThreadGroup tg,
String threadName ) {
super ( tg, threadName );
this.hostname = hostname;
this.command = command;
result = null;
}
public void run () {
String[] toRun;
if ( System.getProperty ( "os.name" ).toLowerCase ().startsWith (
"windows" ) ) {
toRun = new String[4];
toRun[0] = "plink";
toRun[1] = "-ssh";
toRun[2] = this.hostname;
toRun[3] = this.command;
} else {
toRun = new String[3];
toRun[0] = "ssh";
toRun[1] = this.hostname;
toRun[2] = this.command;
}
result = Manager.getCommandOutput ( toRun );
}
public String toString () {
if ( result == null )
return "";
StringBuffer out = new StringBuffer ( 2048 );
out.append ( "Command results from '" + this.hostname + "'"
+ lineSeparator );
out.append ( result.toString () );
return out.toString () + lineSeparator;
}
}

View File

@ -0,0 +1,285 @@
/*
* Created on Dec 21, 2004
*/
package org.penguincoder.mass;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
/**
* @author Andrew Coleman
*
*/
public class Manager {
private static ArrayList serverlist;
protected final static double currentVersion = .01;
private static String hostname, fqdnhostname;
private static void parseServerList ( String inputfile ) {
/* the result arraylist, useful for unknown array sizes */
if ( serverlist == null ) {
serverlist = new ArrayList ( 64 );
}
/*
* either fill from the file if the file exists, if the file does not
* exist, assume that you mean a hostname
*/
try {
/* nice buffered reader for input */
BufferedReader inReader = new BufferedReader ( new FileReader (
inputfile ) );
/* read until the file is done */
while ( inReader.ready () ) {
/* the most effective, not efficient, way to do this is by line */
String line = inReader.readLine ().trim ();
if ( !line.startsWith ( "#" ) && !line.equals ( hostname ) && !line.equals ( fqdnhostname ) ) {
serverlist.add ( line );
}
}
/* finished with the file */
inReader.close ();
} catch ( FileNotFoundException e ) {
serverlist.add ( inputfile );
} catch ( IOException e ) {
System.err.println ( "There was a problem reading the file: "
+ e.getLocalizedMessage () );
System.exit ( 1 );
}
}
public static StringBuffer getCommandOutput ( String[] command ) {
StringBuffer resultBuffer = new StringBuffer ( 2048 );
try {
Process process = Runtime.getRuntime ().exec ( command );
/* get the regular output */
BufferedReader reader = new BufferedReader ( new InputStreamReader (
process.getInputStream () ) );
int bytesRead = 0;
char[] buf = new char[2048];
do {
bytesRead = reader.read ( buf );
if ( bytesRead > 0 ) {
resultBuffer.append ( buf, 0, bytesRead );
}
} while ( bytesRead > 0 );
/* sometimes this can be null, unknown as to the reason */
if ( reader != null ) {
reader.close ();
}
/* get the error stream */
BufferedReader ereader = new BufferedReader (
new InputStreamReader ( process.getErrorStream () ) );
do {
bytesRead = ereader.read ( buf );
if ( bytesRead > 0 ) {
resultBuffer.append ( buf, 0, bytesRead );
}
} while ( bytesRead > 0 );
/* sometimes this can be null, unknown as to the reason */
if ( ereader != null ) {
ereader.close ();
}
} catch ( IOException e ) {
/* report IO errors */
resultBuffer.append ( "IOException caught!"
+ System.getProperty ( "line.separator" ) );
resultBuffer.append ( e.toString ()
+ System.getProperty ( "line.separator" ) );
}
return resultBuffer;
}
private static void usage () {
String lineSeparator = System.getProperty ( "line.separator" );
System.out.println ( "This is the Massive Cluster Utility" );
System.out
.println ( "General Usage: java -jar mass.jar <command> <serverfiles or servers> -- <arguments>" );
System.out.println ( "Current Version: " + currentVersion
+ lineSeparator );
System.out
.println ( "The serverfile is a line delimited list of machines." );
System.out.println ( "Supported Commands: (case-insensitive)" );
System.out.println ( "\trun" + lineSeparator + "\tcopy" );
}
public static void main ( String[] args2 ) {
/* sigh, this is a dirty hack to make
* Eclipse run this program, remove the block
* and change the main arguments to args from
* args2 to remove the hack.
*/
String[] args = null;
if ( args2[0].indexOf ( "Manager" ) > 0 ) {
args = new String[args2.length - 1];
for ( int i = 1; i < args2.length; i++ ) {
args[i - 1] = args2[i];
}
} else {
args = args2;
}
/* end hacky block */
/* see if the gui needs to be started */
if ( args.length < 4 ) {
usage ();
System.exit ( 1 );
}
/* basic sanity check on the command, there are only two */
String command = args[0].toLowerCase ();
if ( !command.equals ( "copy" ) && !command.equals ( "run" ) ) {
usage ();
System.exit ( 1 );
}
/* determine the hostname of the current box, must skip current box */
hostname = "";
try {
java.net.InetAddress localMachine = java.net.InetAddress
.getLocalHost ();
fqdnhostname = localMachine.getHostName ().toLowerCase ();
hostname = fqdnhostname.replaceFirst("[.].*", "");
} catch ( java.net.UnknownHostException uhe ) {
hostname = "localhost";
fqdnhostname = "localhost.localdomain";
}
/* populate the list of servers */
int j = 1;
for ( ; j < args.length && !args[j].equals ( "--" ); j++ ) {
/* either fill from the file or from the listing */
parseServerList ( args[j] );
}
/* found the double dash, so populate the argument array */
j++;
String[] commandArgs = new String[args.length - j];
for ( int i = 0; j < args.length; j++, i++ ) {
commandArgs[i] = args[j];
}
/* start the textual report */
generateTextReport ( command, commandArgs );
}
private static void generateTextReport ( String command,
String[] commandArgs ) {
int serverCount = serverlist.size ();
/* the ThreadGroup that will house all of the commands */
ThreadGroup threadGroup = new ThreadGroup ( "MassiveClusterUtility" );
/* the array of Commands that will eventually be run */
CMD[] commands = new CMD[serverCount];
/* create the command for each site */
int threadCount = 0;
System.out.println ( "Creating threads:" );
/*
* simple command check, there are only two. more would require the use
* of a factory for simplicity
*
* I'm going to go ahead and do all of the processing required to get
* the object moving here. This is better done once than done
* serverCount times :P
*/
if ( command.equals ( "run" ) ) {
String commandToRun = "";
for ( int i = 0; i < commandArgs.length; i++ ) {
commandToRun += commandArgs[i] + " ";
}
commandToRun.trim ();
System.out.println ( "Going to run the command: " + commandToRun );
for ( int serverNum = 0; serverNum < serverCount; serverNum++ ) {
String server = (String) serverlist.get ( serverNum );
System.out.print ( server + " " );
commands[serverNum] = new CMDrun ( commandToRun, server,
threadGroup, "mass-run-" + server );
commands[serverNum].setPriority ( Thread.MIN_PRIORITY );
commands[serverNum].start ();
if ( threadCount == 5 ) {
System.out.println ();
threadCount = 0;
} else {
threadCount++;
}
}
} else {
String remotePath = "", fileString = "";
ArrayList files = new ArrayList ( 10 );
remotePath = commandArgs[commandArgs.length - 1];
int top = commandArgs.length - 2;
for ( int i = 0; i <= top; i++ ) {
files.add ( commandArgs[i].trim () );
fileString += commandArgs[i].trim () + " ";
}
fileString.trim ();
System.out.println ( "Going to copy the fileset: " + files );
System.out.println ( "Remote path will be: " + remotePath );
for ( int serverNum = 0; serverNum < serverCount; serverNum++ ) {
String server = (String) serverlist.get ( serverNum );
System.out.print ( server + " " );
commands[serverNum] = new CMDcopy ( files, remotePath, server,
threadGroup, "mass-copy-" + server );
commands[serverNum].setPriority ( Thread.MIN_PRIORITY );
commands[serverNum].start ();
if ( threadCount == 5 ) {
System.out.println ();
threadCount = 0;
} else {
threadCount++;
}
}
}
System.out.println ( "Done" );
/* wait on all of the threads to start */
do {
threadCount = threadGroup.activeCount ();
try {
Thread.sleep ( 100 );
} catch ( InterruptedException e1 ) {
}
} while ( threadCount != threadGroup.activeCount () );
/* wait on all the threads to finish */
int dotNumber = 0;
while ( (threadCount = threadGroup.activeCount ()) > 0 ) {
/*
* this will print out 12 dots in one line, with one dot every 5
* seconds. each line is a minute of processing, makes it very easy
* to figure out how long it ran.
*/
System.out.print ( "." );
try {
Thread.sleep ( 5000 );
} catch ( InterruptedException e1 ) {
}
if ( dotNumber >= 11 ) {
System.out.println ();
dotNumber = 0;
} else {
dotNumber++;
}
}
/* print out the report */
System.out.println ( System.getProperty ( "line.separator" ) );
System.out.println ( "===== Begin Report =====" );
for ( int thread = 0; thread < commands.length; thread++ ) {
System.out.print ( commands[thread].toString () );
}
/* finished */
System.out.println ( "Fin" );
}
}

View File

@ -0,0 +1,15 @@
package org.penguincoder.mass;
/*
* Created on Dec 21, 2004
*
*/
/**
* @author Andrew Coleman
*
*/
public class MassiveException extends Exception {
public MassiveException ( String message ) {
super ( message );
}
}