001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hdfs.tools;
019
020import com.google.common.base.Preconditions;
021import org.apache.hadoop.conf.Configuration;
022import org.apache.hadoop.fs.FileSystem;
023import org.apache.hadoop.hdfs.DFSUtil;
024import org.apache.hadoop.hdfs.DistributedFileSystem;
025import org.apache.hadoop.hdfs.protocol.CachePoolInfo;
026import org.apache.hadoop.tools.TableListing;
027
028import java.io.IOException;
029import java.util.List;
030
031/**
032 * Helper methods for CacheAdmin/CryptoAdmin/StoragePolicyAdmin
033 */
034public class AdminHelper {
035  /**
036   * Maximum length for printed lines
037   */
038  static final int MAX_LINE_WIDTH = 80;
039  static final String HELP_COMMAND_NAME = "-help";
040
041  static DistributedFileSystem getDFS(Configuration conf)
042      throws IOException {
043    FileSystem fs = FileSystem.get(conf);
044    if (!(fs instanceof DistributedFileSystem)) {
045      throw new IllegalArgumentException("FileSystem " + fs.getUri() +
046          " is not an HDFS file system");
047    }
048    return (DistributedFileSystem)fs;
049  }
050
051  /**
052   * NN exceptions contain the stack trace as part of the exception message.
053   * When it's a known error, pretty-print the error and squish the stack trace.
054   */
055  static String prettifyException(Exception e) {
056    return e.getClass().getSimpleName() + ": "
057        + e.getLocalizedMessage().split("\n")[0];
058  }
059
060  static TableListing getOptionDescriptionListing() {
061    return new TableListing.Builder()
062        .addField("").addField("", true)
063        .wrapWidth(MAX_LINE_WIDTH).hideHeaders().build();
064  }
065
066  /**
067   * Parses a time-to-live value from a string
068   * @return The ttl in milliseconds
069   * @throws IOException if it could not be parsed
070   */
071  static Long parseTtlString(String maxTtlString) throws IOException {
072    Long maxTtl = null;
073    if (maxTtlString != null) {
074      if (maxTtlString.equalsIgnoreCase("never")) {
075        maxTtl = CachePoolInfo.RELATIVE_EXPIRY_NEVER;
076      } else {
077        maxTtl = DFSUtil.parseRelativeTime(maxTtlString);
078      }
079    }
080    return maxTtl;
081  }
082
083  static Long parseLimitString(String limitString) {
084    Long limit = null;
085    if (limitString != null) {
086      if (limitString.equalsIgnoreCase("unlimited")) {
087        limit = CachePoolInfo.LIMIT_UNLIMITED;
088      } else {
089        limit = Long.parseLong(limitString);
090      }
091    }
092    return limit;
093  }
094
095  static Command determineCommand(String commandName, Command[] commands) {
096    Preconditions.checkNotNull(commands);
097    if (HELP_COMMAND_NAME.equals(commandName)) {
098      return new HelpCommand(commands);
099    }
100    for (Command command : commands) {
101      if (command.getName().equals(commandName)) {
102        return command;
103      }
104    }
105    return null;
106  }
107
108  static void printUsage(boolean longUsage, String toolName,
109      Command[] commands) {
110    Preconditions.checkNotNull(commands);
111    System.err.println("Usage: bin/hdfs " + toolName + " [COMMAND]");
112    final HelpCommand helpCommand = new HelpCommand(commands);
113    for (AdminHelper.Command command : commands) {
114      if (longUsage) {
115        System.err.print(command.getLongUsage());
116      } else {
117        System.err.print("          " + command.getShortUsage());
118      }
119    }
120    System.err.print(longUsage ? helpCommand.getLongUsage() :
121        ("          " + helpCommand.getShortUsage()));
122    System.err.println();
123  }
124
125  interface Command {
126    String getName();
127    String getShortUsage();
128    String getLongUsage();
129    int run(Configuration conf, List<String> args) throws IOException;
130  }
131
132  static class HelpCommand implements Command {
133    private final Command[] commands;
134
135    public HelpCommand(Command[] commands) {
136      Preconditions.checkNotNull(commands != null);
137      this.commands = commands;
138    }
139
140    @Override
141    public String getName() {
142      return HELP_COMMAND_NAME;
143    }
144
145    @Override
146    public String getShortUsage() {
147      return "[-help <command-name>]\n";
148    }
149
150    @Override
151    public String getLongUsage() {
152      final TableListing listing = AdminHelper.getOptionDescriptionListing();
153      listing.addRow("<command-name>", "The command for which to get " +
154          "detailed help. If no command is specified, print detailed help for " +
155          "all commands");
156      return getShortUsage() + "\n" +
157          "Get detailed help about a command.\n\n" +
158          listing.toString();
159    }
160
161    @Override
162    public int run(Configuration conf, List<String> args) throws IOException {
163      if (args.size() == 0) {
164        for (AdminHelper.Command command : commands) {
165          System.err.println(command.getLongUsage());
166        }
167        return 0;
168      }
169      if (args.size() != 1) {
170        System.out.println("You must give exactly one argument to -help.");
171        return 0;
172      }
173      final String commandName = args.get(0);
174      // prepend a dash to match against the command names
175      final AdminHelper.Command command = AdminHelper
176          .determineCommand("-" + commandName, commands);
177      if (command == null) {
178        System.err.print("Unknown command '" + commandName + "'.\n");
179        System.err.print("Valid help command names are:\n");
180        String separator = "";
181        for (AdminHelper.Command c : commands) {
182          System.err.print(separator + c.getName().substring(1));
183          separator = ", ";
184        }
185        System.err.print("\n");
186        return 1;
187      }
188      System.err.print(command.getLongUsage());
189      return 0;
190    }
191  }
192}