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 org.apache.hadoop.conf.Configuration;
021import org.apache.hadoop.conf.Configured;
022import org.apache.hadoop.fs.Path;
023import org.apache.hadoop.hdfs.DistributedFileSystem;
024import org.apache.hadoop.hdfs.protocol.BlockStoragePolicy;
025import org.apache.hadoop.hdfs.protocol.HdfsConstants;
026import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
027import org.apache.hadoop.tools.TableListing;
028import org.apache.hadoop.util.StringUtils;
029import org.apache.hadoop.util.Tool;
030
031import java.io.IOException;
032import java.util.Arrays;
033import java.util.Collection;
034import java.util.LinkedList;
035import java.util.List;
036
037/**
038 * This class implements block storage policy operations.
039 */
040public class StoragePolicyAdmin extends Configured implements Tool {
041
042  public static void main(String[] argsArray) throws Exception {
043    final StoragePolicyAdmin admin = new StoragePolicyAdmin(new
044        Configuration());
045    System.exit(admin.run(argsArray));
046  }
047
048  public StoragePolicyAdmin(Configuration conf) {
049    super(conf);
050  }
051
052  @Override
053  public int run(String[] args) throws Exception {
054    if (args.length == 0) {
055      AdminHelper.printUsage(false, "storagepolicies", COMMANDS);
056      return 1;
057    }
058    final AdminHelper.Command command = AdminHelper.determineCommand(args[0],
059        COMMANDS);
060    if (command == null) {
061      System.err.println("Can't understand command '" + args[0] + "'");
062      if (!args[0].startsWith("-")) {
063        System.err.println("Command names must start with dashes.");
064      }
065      AdminHelper.printUsage(false, "storagepolicies", COMMANDS);
066      return 1;
067    }
068    final List<String> argsList = new LinkedList<>();
069    argsList.addAll(Arrays.asList(args).subList(1, args.length));
070    try {
071      return command.run(getConf(), argsList);
072    } catch (IllegalArgumentException e) {
073      System.err.println(AdminHelper.prettifyException(e));
074      return -1;
075    }
076  }
077
078  /** Command to list all the existing storage policies */
079  private static class ListStoragePoliciesCommand
080      implements AdminHelper.Command {
081    @Override
082    public String getName() {
083      return "-listPolicies";
084    }
085
086    @Override
087    public String getShortUsage() {
088      return "[" + getName() + "]\n";
089    }
090
091    @Override
092    public String getLongUsage() {
093      return getShortUsage() + "\n" +
094          "List all the existing block storage policies.\n";
095    }
096
097    @Override
098    public int run(Configuration conf, List<String> args) throws IOException {
099      final DistributedFileSystem dfs = AdminHelper.getDFS(conf);
100      try {
101        Collection<BlockStoragePolicy> policies = dfs.getAllStoragePolicies();
102        System.out.println("Block Storage Policies:");
103        for (BlockStoragePolicy policy : policies) {
104          if (policy != null) {
105            System.out.println("\t" + policy);
106          }
107        }
108      } catch (IOException e) {
109        System.err.println(AdminHelper.prettifyException(e));
110        return 2;
111      }
112      return 0;
113    }
114  }
115
116  /** Command to get the storage policy of a file/directory */
117  private static class GetStoragePolicyCommand implements AdminHelper.Command {
118    @Override
119    public String getName() {
120      return "-getStoragePolicy";
121    }
122
123    @Override
124    public String getShortUsage() {
125      return "[" + getName() + " -path <path>]\n";
126    }
127
128    @Override
129    public String getLongUsage() {
130      final TableListing listing = AdminHelper.getOptionDescriptionListing();
131      listing.addRow("<path>",
132          "The path of the file/directory for getting the storage policy");
133      return getShortUsage() + "\n" +
134          "Get the storage policy of a file/directory.\n\n" +
135          listing.toString();
136    }
137
138    @Override
139    public int run(Configuration conf, List<String> args) throws IOException {
140      final String path = StringUtils.popOptionWithArgument("-path", args);
141      if (path == null) {
142        System.err.println("Please specify the path with -path.\nUsage:" +
143            getLongUsage());
144        return 1;
145      }
146
147      final DistributedFileSystem dfs = AdminHelper.getDFS(conf);
148      try {
149        HdfsFileStatus status = dfs.getClient().getFileInfo(path);
150        if (status == null) {
151          System.err.println("File/Directory does not exist: " + path);
152          return 2;
153        }
154        byte storagePolicyId = status.getStoragePolicy();
155        if (storagePolicyId == HdfsConstants.BLOCK_STORAGE_POLICY_ID_UNSPECIFIED) {
156          System.out.println("The storage policy of " + path + " is unspecified");
157          return 0;
158        }
159        Collection<BlockStoragePolicy> policies = dfs.getAllStoragePolicies();
160        for (BlockStoragePolicy p : policies) {
161          if (p.getId() == storagePolicyId) {
162            System.out.println("The storage policy of " + path + ":\n" + p);
163            return 0;
164          }
165        }
166      } catch (Exception e) {
167        System.err.println(AdminHelper.prettifyException(e));
168        return 2;
169      }
170      System.err.println("Cannot identify the storage policy for " + path);
171      return 2;
172    }
173  }
174
175  /** Command to set the storage policy to a file/directory */
176  private static class SetStoragePolicyCommand implements AdminHelper.Command {
177    @Override
178    public String getName() {
179      return "-setStoragePolicy";
180    }
181
182    @Override
183    public String getShortUsage() {
184      return "[" + getName() + " -path <path> -policy <policy>]\n";
185    }
186
187    @Override
188    public String getLongUsage() {
189      TableListing listing = AdminHelper.getOptionDescriptionListing();
190      listing.addRow("<path>", "The path of the file/directory to set storage" +
191          " policy");
192      listing.addRow("<policy>", "The name of the block storage policy");
193      return getShortUsage() + "\n" +
194          "Set the storage policy to a file/directory.\n\n" +
195          listing.toString();
196    }
197
198    @Override
199    public int run(Configuration conf, List<String> args) throws IOException {
200      final String path = StringUtils.popOptionWithArgument("-path", args);
201      if (path == null) {
202        System.err.println("Please specify the path for setting the storage " +
203            "policy.\nUsage: " + getLongUsage());
204        return 1;
205      }
206
207      final String policyName = StringUtils.popOptionWithArgument("-policy",
208          args);
209      if (policyName == null) {
210        System.err.println("Please specify the policy name.\nUsage: " +
211            getLongUsage());
212        return 1;
213      }
214
215      final DistributedFileSystem dfs = AdminHelper.getDFS(conf);
216      try {
217        dfs.setStoragePolicy(new Path(path), policyName);
218        System.out.println("Set storage policy " + policyName + " on " + path);
219      } catch (Exception e) {
220        System.err.println(AdminHelper.prettifyException(e));
221        return 2;
222      }
223      return 0;
224    }
225  }
226
227  /* Command to unset the storage policy set for a file/directory */
228  private static class UnsetStoragePolicyCommand
229      implements AdminHelper.Command {
230
231    @Override
232    public String getName() {
233      return "-unsetStoragePolicy";
234    }
235
236    @Override
237    public String getShortUsage() {
238      return "[" + getName() + " -path <path>]\n";
239    }
240
241    @Override
242    public String getLongUsage() {
243      TableListing listing = AdminHelper.getOptionDescriptionListing();
244      listing.addRow("<path>", "The path of the file/directory "
245          + "from which the storage policy will be unset.");
246      return getShortUsage() + "\n"
247          + "Unset the storage policy set for a file/directory.\n\n"
248          + listing.toString();
249    }
250
251    @Override
252    public int run(Configuration conf, List<String> args) throws IOException {
253      final String path = StringUtils.popOptionWithArgument("-path", args);
254      if (path == null) {
255        System.err.println("Please specify the path from which "
256            + "the storage policy will be unsetd.\nUsage: " + getLongUsage());
257        return 1;
258      }
259
260      final DistributedFileSystem dfs = AdminHelper.getDFS(conf);
261      try {
262        dfs.unsetStoragePolicy(new Path(path));
263        System.out.println("Unset storage policy from " + path);
264      } catch (Exception e) {
265        System.err.println(AdminHelper.prettifyException(e));
266        return 2;
267      }
268      return 0;
269    }
270  }
271
272  private static final AdminHelper.Command[] COMMANDS = {
273      new ListStoragePoliciesCommand(),
274      new SetStoragePolicyCommand(),
275      new GetStoragePolicyCommand(),
276      new UnsetStoragePolicyCommand()
277  };
278}