2019-05-18 13:08:09 -07:00
|
|
|
/*
|
|
|
|
|
* JobServClient
|
|
|
|
|
*
|
|
|
|
|
* v1.0
|
|
|
|
|
*
|
|
|
|
|
* May 18, 2019
|
|
|
|
|
*/
|
|
|
|
|
|
2019-05-17 01:28:26 -07:00
|
|
|
package JobServ;
|
|
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
import io.grpc.netty.GrpcSslContexts;
|
2019-05-17 01:28:26 -07:00
|
|
|
import io.grpc.ManagedChannel;
|
2019-05-23 16:06:07 -07:00
|
|
|
import java.util.InputMismatchException;
|
2019-05-17 01:28:26 -07:00
|
|
|
import io.grpc.ManagedChannelBuilder;
|
2019-05-19 12:21:00 -07:00
|
|
|
import io.netty.handler.ssl.SslContext;
|
|
|
|
|
import io.netty.handler.ssl.SslContextBuilder;
|
|
|
|
|
import javax.net.ssl.SSLException;
|
2019-05-23 16:06:07 -07:00
|
|
|
import io.grpc.netty.NettyChannelBuilder;
|
2019-05-17 01:28:26 -07:00
|
|
|
import java.util.Scanner;
|
2019-05-23 16:06:07 -07:00
|
|
|
import java.io.File;
|
2019-05-17 01:28:26 -07:00
|
|
|
|
2019-05-18 13:08:09 -07:00
|
|
|
/*
|
|
|
|
|
* The JobServClient class extends the gRPC stub code
|
|
|
|
|
* Additionally, it plugs a command line interface into the API code.
|
|
|
|
|
*/
|
2019-05-17 01:28:26 -07:00
|
|
|
public class JobServClient {
|
2019-05-23 16:06:07 -07:00
|
|
|
private final String serversideTimeoutErrorMessage = "Timeout locking process control on server\n"+
|
|
|
|
|
"Server could be under heavy load\nConsider trying again.";
|
2019-05-17 01:28:26 -07:00
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
private JobServClientAPIConnector api;
|
|
|
|
|
private String[] programArgs;
|
2019-05-17 01:28:26 -07:00
|
|
|
|
2019-05-19 12:21:00 -07:00
|
|
|
/*
|
|
|
|
|
* Constructor
|
2019-05-23 16:06:07 -07:00
|
|
|
* takes program arguments and an api connector object
|
2019-05-19 12:21:00 -07:00
|
|
|
*/
|
2019-05-23 16:06:07 -07:00
|
|
|
public JobServClient(String[] args, JobServClientAPIConnector api) {
|
|
|
|
|
this.programArgs = args;
|
|
|
|
|
this.api = api;
|
2019-05-17 01:28:26 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-19 12:21:00 -07:00
|
|
|
/*
|
2019-05-23 16:06:07 -07:00
|
|
|
* getPidArg()
|
|
|
|
|
* reentrant code was found in all commands except newjob
|
|
|
|
|
* this function pulls the pid argument and wraps around the integer cast
|
|
|
|
|
* returns -1 (an invalid PID) if bad index or unparsable int
|
2019-05-19 12:21:00 -07:00
|
|
|
*/
|
2019-05-23 16:06:07 -07:00
|
|
|
private int getPidArg(int index) {
|
|
|
|
|
if (this.programArgs.length < index) {
|
|
|
|
|
System.out.println("Improper formatting, try client --help");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2019-05-17 01:28:26 -07:00
|
|
|
|
|
|
|
|
try {
|
2019-05-23 16:06:07 -07:00
|
|
|
return Integer.parseInt(this.programArgs[index]);
|
|
|
|
|
|
|
|
|
|
} catch (InputMismatchException e) {
|
|
|
|
|
System.out.println(this.programArgs[index] + " is not a valid int, much less a valid pid");
|
|
|
|
|
return -1;
|
2019-05-17 01:28:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-19 12:21:00 -07:00
|
|
|
/*
|
2019-05-23 16:06:07 -07:00
|
|
|
* outputHelp()
|
|
|
|
|
* writes help information about all commands in the shell to screen
|
2019-05-19 12:21:00 -07:00
|
|
|
*/
|
2019-05-23 16:06:07 -07:00
|
|
|
public static void outputHelp() {
|
|
|
|
|
System.out.println("... new (command)");
|
|
|
|
|
System.out.println("Starts a new process on the server");
|
|
|
|
|
System.out.println("... output (pid)");
|
|
|
|
|
System.out.println("Garners output from process on server");
|
|
|
|
|
System.out.println("... status (pid)");
|
|
|
|
|
System.out.println("Returns whether process on server is running");
|
|
|
|
|
System.out.println("... return (pid)");
|
|
|
|
|
System.out.println("Collects return code from remote process");
|
|
|
|
|
System.out.println("... kill (pid)");
|
|
|
|
|
System.out.println("Immediately destroys remote process");
|
|
|
|
|
}
|
2019-05-17 01:28:26 -07:00
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
/*
|
|
|
|
|
* makeNewProcess
|
|
|
|
|
* makes a new process
|
|
|
|
|
*/
|
|
|
|
|
public void makeNewProcess() {
|
|
|
|
|
if (this.programArgs.length < 6) {
|
|
|
|
|
System.out.println("Improper formatting, try client --help");
|
|
|
|
|
return;
|
2019-05-17 01:28:26 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
String command = "";
|
|
|
|
|
for (int token = 6; token < this.programArgs.length; token++) {
|
|
|
|
|
command += " " + this.programArgs[token];
|
2019-05-17 01:28:26 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
int newProcess = this.api.sendNewJobMessage(command);
|
2019-05-23 16:10:43 -07:00
|
|
|
switch(newProcess) {
|
|
|
|
|
case -1:
|
|
|
|
|
System.out.println(this.serversideTimeoutErrorMessage);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case -2:
|
|
|
|
|
System.out.println("Server failed to create job, check server logs.");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case -3:
|
|
|
|
|
// error logged by API Connector
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
System.out.printf("Process started, assigned pid is %d\n", newProcess);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
2019-05-17 18:22:38 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-19 12:21:00 -07:00
|
|
|
/*
|
2019-05-23 16:06:07 -07:00
|
|
|
* getOutput
|
|
|
|
|
* gets output from a process
|
2019-05-19 12:21:00 -07:00
|
|
|
*/
|
2019-05-23 16:06:07 -07:00
|
|
|
public void getOutput() {
|
|
|
|
|
int candidatePid = this.getPidArg(6);
|
|
|
|
|
if (candidatePid < 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-05-17 18:22:38 -07:00
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
String processOutput = this.api.getProcessOutput(candidatePid);
|
|
|
|
|
System.out.println(processOutput);
|
|
|
|
|
}
|
2019-05-17 18:22:38 -07:00
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
/*
|
|
|
|
|
* getStatus
|
|
|
|
|
* gets the running status of a process
|
|
|
|
|
*/
|
|
|
|
|
public void getStatus() {
|
|
|
|
|
int candidatePid = this.getPidArg(6);
|
|
|
|
|
if (candidatePid < 0) {
|
|
|
|
|
return;
|
2019-05-17 18:22:38 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
int processStatus = this.api.getProcessStatus(candidatePid);
|
|
|
|
|
switch(processStatus) {
|
|
|
|
|
case 0:
|
|
|
|
|
System.out.println("Process is running");
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
System.out.println("Process is not running");
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
System.out.println("A client killed the process already");
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
System.out.println("Process does not exist");
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
System.out.println(this.serversideTimeoutErrorMessage);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-05-17 18:22:38 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-19 12:21:00 -07:00
|
|
|
/*
|
2019-05-23 16:06:07 -07:00
|
|
|
* killProcess
|
|
|
|
|
* kills a process
|
2019-05-19 12:21:00 -07:00
|
|
|
*/
|
2019-05-23 16:06:07 -07:00
|
|
|
public void killProcess() {
|
|
|
|
|
int candidatePid = this.getPidArg(6);
|
|
|
|
|
if (candidatePid < 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-05-17 18:22:38 -07:00
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
int finalStatus = this.api.killProcess(candidatePid);
|
|
|
|
|
switch(finalStatus) {
|
|
|
|
|
case 0:
|
|
|
|
|
System.out.println("Process is still running");
|
|
|
|
|
break;
|
2019-05-17 18:22:38 -07:00
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
case 1:
|
|
|
|
|
System.out.println("Process was killed");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
System.out.println("Process does not exist");
|
|
|
|
|
break;
|
2019-05-17 18:22:38 -07:00
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
case 3:
|
|
|
|
|
System.out.println(this.serversideTimeoutErrorMessage);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
|
// error logged in API Connector
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-05-17 18:22:38 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-19 12:21:00 -07:00
|
|
|
/*
|
2019-05-23 16:06:07 -07:00
|
|
|
* getReturn
|
|
|
|
|
* gets return code from a process
|
2019-05-19 12:21:00 -07:00
|
|
|
*/
|
2019-05-23 16:06:07 -07:00
|
|
|
public void getReturn() {
|
|
|
|
|
int candidatePid = this.getPidArg(6);
|
|
|
|
|
if (candidatePid < 0) {
|
2019-05-17 18:22:38 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
int returnCode = this.api.getProcessReturn(candidatePid);
|
|
|
|
|
|
|
|
|
|
switch(returnCode){
|
|
|
|
|
case 256:
|
|
|
|
|
System.out.println("Process is still running");
|
|
|
|
|
break;
|
|
|
|
|
case 257:
|
|
|
|
|
System.out.println("Process was killed manually by a client");
|
|
|
|
|
break;
|
|
|
|
|
case 258:
|
|
|
|
|
System.out.println("Process does not exist");
|
|
|
|
|
break;
|
|
|
|
|
case 259:
|
|
|
|
|
System.out.println(this.serversideTimeoutErrorMessage);
|
|
|
|
|
break;
|
|
|
|
|
case 260:
|
|
|
|
|
// error logged in getProcesReturn
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
System.out.println("Process Exit Code: " + Integer.toString(returnCode));
|
2019-05-17 18:22:38 -07:00
|
|
|
}
|
2019-05-17 01:28:26 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-19 12:21:00 -07:00
|
|
|
/*
|
|
|
|
|
* main()
|
|
|
|
|
* Client entrypoint
|
2019-05-21 13:56:37 -07:00
|
|
|
* Parses arguments, initializes client, and calls the correct functions
|
2019-05-19 12:21:00 -07:00
|
|
|
*/
|
2019-05-17 01:28:26 -07:00
|
|
|
public static void main(String[] args) throws Exception {
|
|
|
|
|
// check args
|
2019-05-19 12:21:00 -07:00
|
|
|
if (args.length < 7) {
|
|
|
|
|
System.out.println("Usage: $ ./jobserv-client privatekey, cert, truststore, host, port, command, args");
|
|
|
|
|
System.out.println("Or try $ ./jobserv-client help");
|
2019-05-19 14:39:41 -07:00
|
|
|
outputHelp();
|
2019-05-17 01:28:26 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
JobServClientAPIConnector api;
|
2019-05-17 01:28:26 -07:00
|
|
|
try {
|
2019-05-22 16:23:33 -07:00
|
|
|
SslContextBuilder builder = GrpcSslContexts.forClient();
|
|
|
|
|
builder.trustManager(new File(args[2]));
|
|
|
|
|
builder.keyManager(new File(args[1]), new File(args[0]));
|
|
|
|
|
|
|
|
|
|
ManagedChannel channel = NettyChannelBuilder.forAddress(args[3], Integer.parseInt(args[4]))
|
|
|
|
|
.sslContext(builder.build())
|
|
|
|
|
.build();
|
2019-05-23 16:06:07 -07:00
|
|
|
api = new JobServClientAPIConnector(channel);
|
2019-05-17 18:22:38 -07:00
|
|
|
|
2019-05-21 01:37:41 -07:00
|
|
|
// Likely bad port
|
2019-05-17 01:28:26 -07:00
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
System.out.println("Invalid Port");
|
|
|
|
|
return;
|
2019-05-21 01:37:41 -07:00
|
|
|
|
2019-05-22 16:23:33 -07:00
|
|
|
// bad cert or key format
|
2019-05-19 12:21:00 -07:00
|
|
|
} catch (SSLException e) {
|
|
|
|
|
System.out.println(e.getMessage());
|
|
|
|
|
return;
|
2019-05-17 01:28:26 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
JobServClient client = new JobServClient(args, api);
|
|
|
|
|
|
2019-05-19 12:21:00 -07:00
|
|
|
// parse remaining args
|
2019-05-19 13:03:53 -07:00
|
|
|
switch (args[5]) {
|
2019-05-17 18:22:38 -07:00
|
|
|
case "new":
|
2019-05-23 16:06:07 -07:00
|
|
|
client.makeNewProcess();
|
2019-05-17 01:28:26 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "output":
|
2019-05-23 16:06:07 -07:00
|
|
|
client.getOutput();
|
2019-05-17 01:28:26 -07:00
|
|
|
break;
|
2019-05-17 18:22:38 -07:00
|
|
|
|
2019-05-23 16:06:07 -07:00
|
|
|
case "status":
|
|
|
|
|
client.getStatus();
|
2019-05-17 01:28:26 -07:00
|
|
|
break;
|
|
|
|
|
|
2019-05-17 18:22:38 -07:00
|
|
|
case "kill":
|
2019-05-23 16:06:07 -07:00
|
|
|
client.killProcess();
|
2019-05-17 01:28:26 -07:00
|
|
|
break;
|
2019-05-17 12:19:51 -07:00
|
|
|
|
2019-05-17 18:22:38 -07:00
|
|
|
case "return":
|
2019-05-23 16:06:07 -07:00
|
|
|
client.getReturn();
|
|
|
|
|
break;
|
2019-05-17 12:19:51 -07:00
|
|
|
|
2019-05-17 18:22:38 -07:00
|
|
|
default:
|
|
|
|
|
System.out.println("Improper command, try 'help'");
|
2019-05-17 12:19:51 -07:00
|
|
|
break;
|
2019-05-21 01:37:41 -07:00
|
|
|
}
|
2019-05-17 01:28:26 -07:00
|
|
|
}
|
|
|
|
|
}
|