jobserv/src/main/java/JobServ/JobServClient.java

300 lines
8.6 KiB
Java
Raw Normal View History

/*
* JobServClient
*
* v1.0
*
* May 18, 2019
*/
2019-05-17 01:28:26 -07:00
package JobServ;
import io.grpc.netty.GrpcSslContexts;
2019-05-17 01:28:26 -07:00
import io.grpc.ManagedChannel;
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;
import io.grpc.netty.NettyChannelBuilder;
2019-05-17 01:28:26 -07:00
import java.util.Scanner;
import java.io.File;
2019-05-17 01:28:26 -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 {
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
private JobServClientAPIConnector api;
private String[] programArgs;
2019-05-17 01:28:26 -07:00
2019-05-19 12:21:00 -07:00
/*
* Constructor
* takes program arguments and an api connector object
2019-05-19 12:21:00 -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
/*
* 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
*/
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 {
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
/*
* outputHelp()
* writes help information about all commands in the shell to screen
2019-05-19 12:21:00 -07:00
*/
public static void outputHelp() {
System.out.println("... new (command)\n"+
"Starts a new process on the server\n"+
"example: ./client key.pem cert.crt ca.crt localhost 8448 new echo hello world!\n\n"+
"... output (pid)\n"+
"Garners output from process on server\n"+
"example: ./client key.pem cert.crt ca.crt localhost 8448 output 0\n\n"+
"... status (pid)\n"+
"Returns whether process on server is running"+
"example: ./client key.pem cert.crt ca.crt localhost 8448 status 0\n\n"+
"... return (pid)\n"+
"Collects return code from remote process\n"+
"example: ./client key.pem cert.crt ca.crt localhost 8448 return 0\n\n"+
"... kill (pid)"+
"Immediately destroys remote process"+
"example: ./client key.pem cert.crt ca.crt localhost 8448 kill 0\n\n"+
}
2019-05-17 01:28:26 -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
}
String command = "";
for (int token = 6; token < this.programArgs.length; token++) {
command += " " + this.programArgs[token];
2019-05-17 01:28:26 -07:00
}
int newProcess = this.api.sendNewJobMessage(command);
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-19 12:21:00 -07:00
/*
* getOutput
* gets output from a process
2019-05-19 12:21:00 -07:00
*/
public void getOutput() {
int candidatePid = this.getPidArg(6);
if (candidatePid < 0) {
return;
}
String processOutput = this.api.getProcessOutput(candidatePid);
System.out.println(processOutput);
}
/*
* getStatus
* gets the running status of a process
*/
public void getStatus() {
int candidatePid = this.getPidArg(6);
if (candidatePid < 0) {
return;
}
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-19 12:21:00 -07:00
/*
* killProcess
* kills a process
2019-05-19 12:21:00 -07:00
*/
public void killProcess() {
int candidatePid = this.getPidArg(6);
if (candidatePid < 0) {
return;
}
int finalStatus = this.api.killProcess(candidatePid);
switch(finalStatus) {
case 0:
System.out.println("Process is still running");
break;
case 1:
System.out.println("Process was killed");
break;
case 2:
System.out.println("Process does not exist");
break;
case 3:
System.out.println(this.serversideTimeoutErrorMessage);
break;
case 4:
// error logged in API Connector
break;
}
}
2019-05-19 12:21:00 -07:00
/*
* getReturn
* gets return code from a process
2019-05-19 12:21:00 -07:00
*/
public void getReturn() {
int candidatePid = this.getPidArg(6);
if (candidatePid < 0) {
return;
}
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 01:28:26 -07:00
}
2019-05-19 12:21:00 -07:00
/*
* main()
* Client entrypoint
* 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;
}
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();
api = new JobServClientAPIConnector(channel);
// Likely bad port
2019-05-17 01:28:26 -07:00
} catch (NumberFormatException e) {
System.out.println("Invalid Port");
return;
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
}
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]) {
case "new":
client.makeNewProcess();
2019-05-17 01:28:26 -07:00
break;
case "output":
client.getOutput();
2019-05-17 01:28:26 -07:00
break;
case "status":
client.getStatus();
2019-05-17 01:28:26 -07:00
break;
case "kill":
client.killProcess();
2019-05-17 01:28:26 -07:00
break;
case "return":
client.getReturn();
break;
default:
System.out.println("Improper command, try 'help'");
break;
}
2019-05-17 01:28:26 -07:00
}
}