diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/yarn/registry/cli/RegistryCli.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/yarn/registry/cli/RegistryCli.java new file mode 100644 index 0000000..278f83b --- /dev/null +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/yarn/registry/cli/RegistryCli.java @@ -0,0 +1,416 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.yarn.registry.cli; + +import static org.apache.hadoop.yarn.registry.client.binding.RegistryTypeUtils.inetAddrEndpoint; +import static org.apache.hadoop.yarn.registry.client.binding.RegistryTypeUtils.restEndpoint; +import static org.apache.hadoop.yarn.registry.client.binding.RegistryTypeUtils.webEndpoint; + +import java.io.IOException; +import java.io.PrintStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.GnuParser; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionBuilder; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.hadoop.conf.Configured; +import org.apache.hadoop.fs.PathNotFoundException; +import org.apache.hadoop.security.AccessControlException; +import org.apache.hadoop.util.Tool; +import org.apache.hadoop.util.ToolRunner; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import org.apache.hadoop.yarn.registry.client.api.CreateFlags; +import org.apache.hadoop.yarn.registry.client.exceptions.InvalidPathnameException; +import org.apache.hadoop.yarn.registry.client.exceptions.InvalidRecordException; +import org.apache.hadoop.yarn.registry.client.types.ProtocolTypes; +import org.apache.hadoop.yarn.registry.client.types.RegistryPathStatus; +import org.apache.hadoop.yarn.registry.client.types.ServiceRecord; +import org.apache.hadoop.yarn.registry.server.services.RMRegistryOperationsService; + +public class RegistryCli extends Configured implements Tool { + + protected PrintStream sysout; + protected PrintStream syserr; + + + static RMRegistryOperationsService registry = new RMRegistryOperationsService("yarnRegistry"); + static final String LS_USAGE = "ls pathName"; + static final String RESOLVE_USAGE = "resolve pathName"; + static final String BIND_USAGE = "bind -inet -api apiName -p portNumber -h hostName pathName" + "\n" + + "bind -webui uriString -api apiName pathName" + "\n" + + "bind -rest uriString -api apiName pathName" ; + static final String MKNODE_USAGE = "mknode directoryName"; + static final String RM_USAGE = "rm pathName"; + static final String USAGE = "\n" + LS_USAGE + "\n" + RESOLVE_USAGE + "\n" + BIND_USAGE + "\n" + MKNODE_USAGE + "\n" + RM_USAGE; + + int usageError(String err, String usage) { + syserr.println("Error: " + err); + syserr.println("Usage: " + usage); + return -1; + } + boolean validatePath(String path) { + if (! path.startsWith("/")) { + syserr.println("Path must start with /; given path was: " + path); + return false; + } + return true; + } + public RegistryCli() { + super(new YarnConfiguration()); + registry.init(new YarnConfiguration()); + registry.start(); + } + + public void setSysOutPrintStream(PrintStream sysout) { + this.sysout = sysout; + } + + public void setSysErrPrintStream(PrintStream syserr) { + this.syserr = syserr; + } + + + public static void main(String [] args) throws Exception { + RegistryCli cli = new RegistryCli(); + cli.setSysOutPrintStream(System.out); + cli.setSysErrPrintStream(System.err); + int res = ToolRunner.run(cli, args); + System.exit(res); + } + + @Override + public int run(String[] args) throws Exception { + + if(args.length > 0) { + if(args[0].equals("ls") ) { + return ls(args); + } else if(args[0].equals("resolve")) { + return resolve(args); + } else if(args[0].equals("bind")) { + return bind(args); + } else if(args[0].equals("mknode")) { + return mknode(args); + } else if(args[0].equals("rm")) { + return rm(args); + } + } + return usageError("Invalid command: " + args[0], USAGE); + } + + public int ls(String [] args) { + + Options lsOption = new Options(); + CommandLineParser parser = new GnuParser(); + try { + CommandLine line = parser.parse(lsOption, args); + @SuppressWarnings("unchecked") + List argsList = line.getArgList(); + if (argsList.size() != 2) { + return usageError("ls requires exactly one path argument", LS_USAGE); + } + if (!validatePath(argsList.get(1))) + return -1; + + try { + RegistryPathStatus[] path = registry.list(argsList.get(1)); + for (int i=0; i argsList = line.getArgList(); + if (argsList.size() != 2) { + return usageError("resolve requires exactly one path argument", RESOLVE_USAGE); + } + if (!validatePath(argsList.get(1))) + return -1; + + try { + ServiceRecord record = registry.resolve(argsList.get(1)); + + for (org.apache.hadoop.yarn.registry.client.types.Endpoint endpoint : record.external) { + if ((endpoint.protocolType.equals(ProtocolTypes.PROTOCOL_WEBUI)) + || (endpoint.protocolType.equals(ProtocolTypes.PROTOCOL_REST))) { + sysout.print(" Endpoint(ProtocolType=" + + endpoint.protocolType + ", Api=" + + endpoint.api + "); Uris are: "); + } else { + sysout.print(" Endpoint(ProtocolType=" + + endpoint.protocolType + ", Api=" + + endpoint.api + ");" + + " Addresses(AddressType=" + + endpoint.addressType + ") are: "); + + } + for (List a : endpoint.addresses) { + sysout.print(a + " "); + } + sysout.println(); + } + return 0; + + } catch (InvalidPathnameException e) { + syserr.println("InvalidPath :" + argsList.get(1)); + } catch (PathNotFoundException e) { + syserr.println("Path not found: " + argsList.get(1)); + } catch (AccessControlException e) { + syserr.println("No Permision to path: " + argsList.get(1)); + } catch (InvalidRecordException e) { + syserr.println("No Service record binding at path: " + argsList.get(1)); + } catch (IOException e) { + syserr.println("IO Exception when accessing path :" + argsList.get(1) + ", Error Messsage: " +e.getMessage()); + } + return -1; + } catch (org.apache.commons.cli.ParseException exp) { + return usageError("Invalid syntax " + exp.getMessage(), RESOLVE_USAGE); + } + + } + + public int bind(String [] args) { + Option rest = OptionBuilder.withArgName("rest") + .hasArg() + .withDescription("rest Option") + .create("rest"); + Option webui = OptionBuilder.withArgName("webui") + .hasArg() + .withDescription("webui Option") + .create("webui"); + Option inet = OptionBuilder.withArgName("inet") + .withDescription("inet Option") + .create("inet"); + Option port = OptionBuilder.withArgName("port") + .hasArg() + .withDescription("port to listen on [9999]") + .create("p"); + Option host = OptionBuilder.withArgName("host") + .hasArg() + .withDescription("host name") + .create("h"); + Option apiOpt = OptionBuilder.withArgName("api") + .hasArg() + .withDescription("api") + .create("api"); + Options inetOption = new Options(); + inetOption.addOption(inet); + inetOption.addOption(port); + inetOption.addOption(host); + inetOption.addOption(apiOpt); + + Options webuiOpt = new Options(); + webuiOpt.addOption(webui); + webuiOpt.addOption(apiOpt); + + Options restOpt = new Options(); + restOpt.addOption(rest); + restOpt.addOption(apiOpt); + + + + CommandLineParser parser = new GnuParser(); + ServiceRecord sr = new ServiceRecord("NoID", "NoDescription", 0, "NoData"); + CommandLine line = null; + if (args.length <= 1) { + return usageError("Invalid syntax ", BIND_USAGE); + } + if (args[1].equals("-inet")) { + int portNum; + String hostName; + String api; + + try { + line = parser.parse(inetOption, args); + } catch (ParseException exp) { + return usageError("Invalid syntax " + exp.getMessage(), BIND_USAGE); + } + if(line.hasOption("inet") && line.hasOption("p") && line.hasOption("h") && line.hasOption("api")) { + portNum = Integer.parseInt(line.getOptionValue("p")); + hostName = line.getOptionValue("h"); + api = line.getOptionValue("api"); + sr.addExternalEndpoint(inetAddrEndpoint(api, ProtocolTypes.PROTOCOL_HADOOP_IPC, hostName, portNum)); + + } else { + return usageError("Missing options: must have host, port and api", BIND_USAGE); + } + + } else if (args[1].equals("-webui")) { + try { + line = parser.parse(webuiOpt, args); + } catch (ParseException exp) { + return usageError("Invalid syntax " + exp.getMessage(), BIND_USAGE); + } + if(line.hasOption("webui") && line.hasOption("api")) { + URI theUri = null; + try { + theUri = new URI(line.getOptionValue("webui")); + } catch (URISyntaxException e) { + return usageError("Invalid URI: " + e.getMessage(), BIND_USAGE); + } + sr.addExternalEndpoint(webEndpoint(line.getOptionValue("api"), theUri)); + + } else { + return usageError("Missing options: must have value for uri and api", BIND_USAGE); + } + } else if (args[1].equals("-rest")) { + try { + line = parser.parse(restOpt, args); + } catch (ParseException exp) { + return usageError("Invalid syntax " + exp.getMessage(), BIND_USAGE); + } + if(line.hasOption("rest") && line.hasOption("api")) { + URI theUri = null; + try { + theUri = new URI(line.getOptionValue("rest")); + } catch (URISyntaxException e) { + return usageError("Invalid URI: " + e.getMessage(), BIND_USAGE); + } + sr.addExternalEndpoint(restEndpoint(line.getOptionValue("api"), theUri)); + + } else { + return usageError("Missing options: must have value for uri and api", BIND_USAGE); + } + + } else { + return usageError("Invalid syntax", BIND_USAGE); + } + @SuppressWarnings("unchecked") + List argsList = line.getArgList(); + if (argsList.size() != 2) { + return usageError("bind requires exactly one path argument", BIND_USAGE); + } + if (!validatePath(argsList.get(1))) + return -1; + + try { + registry.create(argsList.get(1), sr, CreateFlags.OVERWRITE); + return 0; + } catch (InvalidPathnameException e) { + syserr.println("InvalidPath :" + argsList.get(1)); + } catch (PathNotFoundException e) { + syserr.println("Path not found: " + argsList.get(1)); + } catch (AccessControlException e) { + syserr.println("No Permision to path: " + argsList.get(1)); + } catch (IOException e) { + syserr.println("IO Exception when accessing path :" + argsList.get(1)); + } + return -1; + } + + public int mknode(String [] args) { + Options mknodeOption = new Options(); + CommandLineParser parser = new GnuParser(); + try { + CommandLine line = parser.parse(mknodeOption, args); + @SuppressWarnings("unchecked") + List argsList = line.getArgList(); + if (argsList.size() != 2) { + return usageError("mknode requires exactly one path argument", MKNODE_USAGE); + } + if (!validatePath(argsList.get(1))) + return -1; + + try { + registry.mknode(args[1], false); + return 0; + } catch (InvalidPathnameException e) { + syserr.println("InvalidPath :" + argsList.get(1)); + } catch (PathNotFoundException e) { + syserr.println("Path not found: " + argsList.get(1)); + } catch (AccessControlException e) { + syserr.println("No Permision to path: " + argsList.get(1)); + } catch (IOException e) { + syserr.println("IO Exception when accessing path :" + argsList.get(1)); + } + return -1; + } catch (org.apache.commons.cli.ParseException exp) { + return usageError("Invalid syntax " + exp.getMessage(), MKNODE_USAGE); + } + } + + public int rm(String[] args) { + Option recursive = OptionBuilder.withArgName("recursive") + .withDescription("delete recursively").create("r"); + + Options rmOption = new Options(); + rmOption.addOption(recursive); + + boolean recursiveOpt = false; + + CommandLineParser parser = new GnuParser(); + try { + CommandLine line = parser.parse(rmOption, args); + @SuppressWarnings("unchecked") + List argsList = line.getArgList(); + if (argsList.size() != 2) { + return usageError("RM requires exactly one path argument", RM_USAGE); + } + if (!validatePath(argsList.get(1))) + return -1; + + try { + if (line.hasOption("r")) { + recursiveOpt = true; + } + + registry.delete(argsList.get(1), recursiveOpt); + return 0; + } catch (InvalidPathnameException e) { + syserr.println("InvalidPath :" + argsList.get(1)); + } catch (PathNotFoundException e) { + syserr.println("Path not found: " + argsList.get(1)); + } catch (AccessControlException e) { + syserr.println("No Permision to path: " + argsList.get(1)); + } catch (IOException e) { + syserr.println("IO Exception (" + e.getMessage() + ") when accessing path :" + + argsList.get(1)); + } + return -1; + } catch (org.apache.commons.cli.ParseException exp) { + return usageError("Invalid syntax " + exp.getMessage(), RM_USAGE); + } + + } +} +