package voldemort.tools;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Random;
import joptsimple.OptionException;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import voldemort.client.protocol.admin.AdminClient;
import voldemort.cluster.Node;
import voldemort.tools.admin.AdminToolUtils;
import voldemort.utils.Utils;
public class GenerateScriptCLI {
private static OptionParser setupParser() {
OptionParser parser = new OptionParser();
parser.accepts("help", "Print usage information").withOptionalArg();
parser.acceptsAll(Arrays.asList("s", "script"), "Script")
.withRequiredArg()
.describedAs("script")
.ofType(String.class);
parser.acceptsAll(Arrays.asList("u", "url"), "bootstrapUrl")
.withRequiredArg()
.describedAs("url")
.ofType(String.class);
parser.acceptsAll(Arrays.asList("scp", "scpFile"), "file to be scp ed")
.withRequiredArg()
.describedAs("scp")
.ofType(String.class);
parser.acceptsAll(Arrays.asList("o", "output"), "outputScript")
.withRequiredArg()
.describedAs("output")
.ofType(String.class);
return parser;
}
private static void printUsage() {
StringBuilder help = new StringBuilder();
help.append("GenerateScriptCLI\n");
help.append(" Given a script, Generates a new script which will use SSH to run the given \n");
help.append(" script on all hosts in a given cluster. The variable @@ID@@ , @@HOST@@ , @@URL@@ \n");
help.append(" will be replaced with the node id, host name and bootstrap Url respectively\n");
help.append("Options:\n");
help.append(" Required:\n");
help.append(" --url <bootstrapUrl>\n");
help.append(" --script <Script to run on each host>\n");
System.out.print(help.toString());
}
private static void printUsageAndDie(String errMessage) {
printUsage();
Utils.croak("\n" + errMessage);
}
public static String getFilePath(OptionSet options, String name) {
String path = (String) options.valueOf(name);
return path.replace("~", System.getProperty("user.home"));
}
public static void main(String[] args) throws IOException {
OptionParser parser = null;
OptionSet options = null;
try {
parser = setupParser();
options = parser.parse(args);
} catch(OptionException oe) {
parser.printHelpOn(System.out);
printUsageAndDie("Exception when parsing arguments : " + oe.getMessage());
return;
}
/* validate options */
if(options.has("help")) {
printUsage();
return;
}
if(!options.hasArgument("url") || !options.hasArgument("script")
|| !options.hasArgument("output")) {
printUsageAndDie("Missing a required argument.");
return;
}
String url = (String) options.valueOf("url");
String inputScriptPath = getFilePath(options, "script");
String outputScriptPath = getFilePath(options, "output");
String scpFilePath = getFilePath(options, "scp");
AdminClient client = AdminToolUtils.getAdminClient(url);
PrintWriter writer = new PrintWriter(outputScriptPath, "UTF-8");
for(Node node: client.getAdminClientCluster().getNodes()) {
FileInputStream fis = new FileInputStream(inputScriptPath);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
if(scpFilePath != null && scpFilePath.length() > 0) {
writer.println("scp " + scpFilePath + " " + node.getHost() + ":~");
}
int randomNumber = 1000 + new Random().nextInt(100000);
String hereDocumentTag = "NODE_" + node.getId() + "_" + randomNumber;
// Use SSH here script
writer.println("ssh -T " + node.getHost() + " << " + hereDocumentTag);
String line = null;
while((line = br.readLine()) != null) {
line = line.replace("@@ID@@", Integer.toString(node.getId()));
line = line.replace("@@HOST@@", node.getHost());
line = line.replace("@@URL@@", node.getSocketUrl().toString());
writer.println(line);
}
writer.println(hereDocumentTag);
writer.println("\n\n\n");
br.close();
}
writer.close();
System.out.println("Output script generated at " + outputScriptPath);
}
}