org.apache.hadoop.registry.cli.RegistryCli.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.registry.cli.RegistryCli.java

Source

/*
 * 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.registry.cli;

import static org.apache.hadoop.registry.client.binding.RegistryTypeUtils.*;

import java.io.Closeable;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Map;

import com.google.common.base.Preconditions;
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.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.PathNotFoundException;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.service.ServiceOperations;
import org.apache.hadoop.util.ExitUtil;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import org.apache.hadoop.registry.client.api.BindFlags;
import org.apache.hadoop.registry.client.api.RegistryOperations;
import org.apache.hadoop.registry.client.api.RegistryOperationsFactory;
import org.apache.hadoop.registry.client.exceptions.AuthenticationFailedException;
import org.apache.hadoop.registry.client.exceptions.InvalidPathnameException;
import org.apache.hadoop.registry.client.exceptions.InvalidRecordException;
import org.apache.hadoop.registry.client.exceptions.NoPathPermissionsException;
import org.apache.hadoop.registry.client.exceptions.NoRecordException;
import org.apache.hadoop.registry.client.types.Endpoint;
import org.apache.hadoop.registry.client.types.ProtocolTypes;
import org.apache.hadoop.registry.client.types.ServiceRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Command line for registry operations.
 */
public class RegistryCli extends Configured implements Tool, Closeable {
    private static final Logger LOG = LoggerFactory.getLogger(RegistryCli.class);
    protected final PrintStream sysout;
    protected final PrintStream syserr;

    private RegistryOperations registry;

    private static final String LS_USAGE = "ls pathName";
    private static final String RESOLVE_USAGE = "resolve pathName";
    private 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";
    private static final String MKNODE_USAGE = "mknode directoryName";
    private static final String RM_USAGE = "rm pathName";
    private static final String USAGE = "\n" + LS_USAGE + "\n" + RESOLVE_USAGE + "\n" + BIND_USAGE + "\n"
            + MKNODE_USAGE + "\n" + RM_USAGE;

    public RegistryCli(PrintStream sysout, PrintStream syserr) {
        Configuration conf = new Configuration();
        super.setConf(conf);
        registry = RegistryOperationsFactory.createInstance(conf);
        registry.start();
        this.sysout = sysout;
        this.syserr = syserr;
    }

    public RegistryCli(RegistryOperations reg, Configuration conf, PrintStream sysout, PrintStream syserr) {
        super(conf);
        Preconditions.checkArgument(reg != null, "Null registry");
        registry = reg;
        this.sysout = sysout;
        this.syserr = syserr;
    }

    @SuppressWarnings("UseOfSystemOutOrSystemErr")
    public static void main(String[] args) throws Exception {
        int res = -1;
        try (RegistryCli cli = new RegistryCli(System.out, System.err)) {
            res = ToolRunner.run(cli, args);
        } catch (Exception e) {
            ExitUtil.terminate(res, e);
        }
        ExitUtil.terminate(res);
    }

    /**
     * Close the object by stopping the registry.
     * <p>
     * <i>Important:</i>
     * <p>
     *   After this call is made, no operations may be made of this
     *   object, <i>or of a YARN registry instance used when constructing
     *   this object. </i>
     * @throws IOException
     */
    @Override
    public void close() throws IOException {
        ServiceOperations.stopQuietly(registry);
        registry = null;
    }

    private int usageError(String err, String usage) {
        syserr.println("Error: " + err);
        syserr.println("Usage: " + usage);
        return -1;
    }

    private boolean validatePath(String path) {
        if (!path.startsWith("/")) {
            syserr.println("Path must start with /; given path was: " + path);
            return false;
        }
        return true;
    }

    @Override
    public int run(String[] args) throws Exception {
        Preconditions.checkArgument(getConf() != null, "null configuration");
        if (args.length > 0) {
            switch (args[0]) {
            case "ls":
                return ls(args);
            case "resolve":
                return resolve(args);
            case "bind":
                return bind(args);
            case "mknode":
                return mknode(args);
            case "rm":
                return rm(args);
            default:
                return usageError("Invalid command: " + args[0], USAGE);
            }
        }
        return usageError("No command arg passed.", USAGE);
    }

    @SuppressWarnings("unchecked")
    public int ls(String[] args) {

        Options lsOption = new Options();
        CommandLineParser parser = new GnuParser();
        try {
            CommandLine line = parser.parse(lsOption, args);

            List<String> 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 {
                List<String> children = registry.list(argsList.get(1));
                for (String child : children) {
                    sysout.println(child);
                }
                return 0;

            } catch (Exception e) {
                syserr.println(analyzeException("ls", e, argsList));
            }
            return -1;
        } catch (ParseException exp) {
            return usageError("Invalid syntax " + exp, LS_USAGE);
        }
    }

    @SuppressWarnings("unchecked")
    public int resolve(String[] args) {
        Options resolveOption = new Options();
        CommandLineParser parser = new GnuParser();
        try {
            CommandLine line = parser.parse(resolveOption, args);

            List<String> 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 (Endpoint endpoint : record.external) {
                    sysout.println(" Endpoint(ProtocolType=" + endpoint.protocolType + ", Api=" + endpoint.api
                            + ");" + " Addresses(AddressType=" + endpoint.addressType + ") are: ");

                    for (Map<String, String> address : endpoint.addresses) {
                        sysout.println("[ ");
                        for (Map.Entry<String, String> entry : address.entrySet()) {
                            sysout.print("\t" + entry.getKey() + ":" + entry.getValue());
                        }

                        sysout.println("\n]");
                    }
                    sysout.println();
                }
                return 0;
            } catch (Exception e) {
                syserr.println(analyzeException("resolve", e, argsList));
            }
            return -1;
        } catch (ParseException exp) {
            return usageError("Invalid syntax " + exp, 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();
        CommandLine line;
        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")) {
                try {
                    portNum = Integer.parseInt(line.getOptionValue("p"));
                } catch (NumberFormatException exp) {
                    return usageError("Invalid Port - int required" + exp.getMessage(), BIND_USAGE);
                }
                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;
                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<String> 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.bind(argsList.get(1), sr, BindFlags.OVERWRITE);
            return 0;
        } catch (Exception e) {
            syserr.println(analyzeException("bind", e, argsList));
        }

        return -1;
    }

    @SuppressWarnings("unchecked")
    public int mknode(String[] args) {
        Options mknodeOption = new Options();
        CommandLineParser parser = new GnuParser();
        try {
            CommandLine line = parser.parse(mknodeOption, args);

            List<String> 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 (Exception e) {
                syserr.println(analyzeException("mknode", e, argsList));
            }
            return -1;
        } catch (ParseException exp) {
            return usageError("Invalid syntax " + exp.toString(), MKNODE_USAGE);
        }
    }

    @SuppressWarnings("unchecked")
    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);

            List<String> 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 (Exception e) {
                syserr.println(analyzeException("rm", e, argsList));
            }
            return -1;
        } catch (ParseException exp) {
            return usageError("Invalid syntax " + exp.toString(), RM_USAGE);
        }
    }

    /**
     * Given an exception and a possibly empty argument list, generate
     * a diagnostics string for use in error messages
     * @param operation the operation that failed
     * @param e exception
     * @param argsList arguments list
     * @return a string intended for the user
     */
    String analyzeException(String operation, Exception e, List<String> argsList) {

        String pathArg = !argsList.isEmpty() ? argsList.get(1) : "(none)";
        if (LOG.isDebugEnabled()) {
            LOG.debug("Operation {} on path {} failed with exception {}", operation, pathArg, e, e);
        }
        if (e instanceof InvalidPathnameException) {
            return "InvalidPath :" + pathArg + ": " + e;
        }
        if (e instanceof PathNotFoundException) {
            return "Path not found: " + pathArg;
        }
        if (e instanceof NoRecordException) {
            return "No service record at path " + pathArg;
        }
        if (e instanceof AuthenticationFailedException) {
            return "Failed to authenticate to registry : " + e;
        }
        if (e instanceof NoPathPermissionsException) {
            return "No Permission to path: " + pathArg + ": " + e;
        }
        if (e instanceof AccessControlException) {
            return "No Permission to path: " + pathArg + ": " + e;
        }
        if (e instanceof InvalidRecordException) {
            return "Unable to read record at: " + pathArg + ": " + e;
        }
        if (e instanceof IOException) {
            return "IO Exception when accessing path :" + pathArg + ": " + e;
        }
        // something else went very wrong here
        return "Exception " + e;

    }
}