/** * 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.ambari.fast_hdfs_resource; import java.io.FileNotFoundException; import java.io.IOException; import java.io.File; import java.lang.System; import java.util.ArrayList; import java.util.HashSet; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.FileSystem; /** * Used to: * 1) copy files/directories from localFS to hadoopFs * 2) create empty * 3) download files/directories from hadoopFs to localFS * files/directories in hadoopFs */ public class Resource { private String source; private String target; private String type; private String action; private String owner; private String group; private String mode; private boolean recursiveChown; private boolean recursiveChmod; private boolean changePermissionforParents; private boolean manageIfExists; public String getSource() { return source; } public void setSource(String source) { this.source = source; } public String getTarget() { return target; } public void setTarget(String target) { this.target = target; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getAction() { return action; } public void setAction(String action) { this.action = action; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public String getGroup() { return group; } public void setGroup(String group) { this.group = group; } public String getMode() { return mode; } public void setMode(String mode) { this.mode = mode; } public boolean isRecursiveChown() { return recursiveChown; } public void setRecursiveChown(boolean recursiveChown) { this.recursiveChown = recursiveChown; } public boolean isRecursiveChmod() { return recursiveChmod; } public void setRecursiveChmod(boolean recursiveChmod) { this.recursiveChmod = recursiveChmod; } public boolean isChangePermissionOnParents() { return changePermissionforParents; } public void setChangePermissionOnParents(boolean changePermissionforParents) { this.changePermissionforParents = changePermissionforParents; } public boolean isManageIfExists() { return manageIfExists; } public void setManageIfExists(boolean manageIfExists) { this.manageIfExists = manageIfExists; } @Override public String toString() { return "Resource [source=" + source + ", target=" + target + ", type=" + type + ", action=" + action + ", owner=" + owner + ", group=" + group + ", mode=" + mode + ", recursiveChown=" + recursiveChown + ", recursiveChmod=" + recursiveChmod + ", changePermissionforParents=" + changePermissionforParents + ", manageIfExists=" + manageIfExists + "]"; } /* * Check if parameters are correctly set */ public static void checkResourceParameters(Resource resource, FileSystem dfs) throws IllegalArgumentException, IOException { ArrayList<String> actionsAvailable = new ArrayList<String>(); actionsAvailable.add("create"); actionsAvailable.add("delete"); actionsAvailable.add("download"); ArrayList<String> typesAvailable = new ArrayList<String>(); typesAvailable.add("file"); typesAvailable.add("directory"); if (resource.getAction() == null || !actionsAvailable.contains(resource.getAction())) { throw new IllegalArgumentException("Action is not supported."); } String dfsPath = resource.getTarget(); String localPath = resource.getSource(); if (resource.getAction().equals("download")) { dfsPath = resource.getSource(); localPath = resource.getTarget(); } if (dfsPath == null) { throw new IllegalArgumentException("Path to resource in HadoopFs must be filled."); } if (resource.getType() == null || !typesAvailable.contains(resource.getType())) { throw new IllegalArgumentException("Type is not supported."); } // Check consistency for ("type":"file" == file in hadoop) if (dfs.isFile(new Path(dfsPath)) && !"file".equals(resource.getType())) { throw new IllegalArgumentException( "Cannot create a directory " + dfsPath + " because file is present on the given path."); } // Check consistency for ("type":"directory" == directory in hadoop) else if (dfs.isDirectory(new Path(dfsPath)) && !"directory".equals(resource.getType())) { throw new IllegalArgumentException( "Cannot create a file " + dfsPath + " because directory is present on the given path."); } if(localPath != null) { File local = new File(localPath); if(local.isFile() && !"file".equals(resource.getType())) { throw new IllegalArgumentException( "Cannot create a directory " + dfsPath + " because source " + localPath + "is a file"); } else if(local.isDirectory() && !"directory".equals(resource.getType())) { throw new IllegalArgumentException( "Cannot create a file " + dfsPath + " because source " + localPath + "is a directory"); } } } /* * Create/copy resource - {type} */ public static void createResource(Resource resource, FileSystem dfs, Path pathHadoop) throws IOException { boolean isCreate = (resource.getSource() == null) ? true : false; if (isCreate && resource.getType().equals("directory")) { dfs.mkdirs(pathHadoop); // empty dir(s) } else if (isCreate && resource.getType().equals("file")) { dfs.createNewFile(pathHadoop); // empty file } else { if(dfs.exists(pathHadoop) && dfs.getFileStatus(pathHadoop).isDir()) { System.out.println("Skipping copy from local, as target " + pathHadoop + " is an existing directory."); // Copy from local to existing directory is not supported by dfs. } else { dfs.copyFromLocalFile(new Path(resource.getSource()), pathHadoop); } } } /* * Set permissions on resource - {mode} */ public static void setMode(Resource resource, FileSystem dfs, Path pathHadoop) throws IOException { if (resource.getMode() != null) { FsPermission permission = new FsPermission((short)Integer.parseInt(resource.getMode(), 8)); dfs.setPermission(pathHadoop, permission); // Recursive // Get the list of sub-directories and files HashSet<String> resultSet = new HashSet<String>(); if (resource.isRecursiveChmod()) resource.fillDirectoryList(dfs, resource.getTarget(), resultSet); if(resource.isChangePermissionOnParents()) resource.fillInParentDirectories(dfs, resource.getTarget(), resultSet); for (String path : resultSet) { dfs.setPermission(new Path(path), permission); } } } /* * Set owner on resource - {owner} */ public static void setOwner(Resource resource, FileSystem dfs, Path pathHadoop) throws IOException { if (!(resource.getOwner() == null && resource.getGroup() == null)) { dfs.setOwner(pathHadoop, resource.getOwner(), resource.getGroup()); // Get the list of sub-directories and files HashSet<String> resultSet = new HashSet<String>(); if (resource.isRecursiveChown()) resource.fillDirectoryList(dfs, resource.getTarget(), resultSet); if(resource.isChangePermissionOnParents()) resource.fillInParentDirectories(dfs, resource.getTarget(), resultSet); for (String path : resultSet) { dfs.setOwner(new Path(path), resource.getOwner(), resource.getGroup()); } } } public void fillInParentDirectories(FileSystem dfs, String path, HashSet<String> resultSet) throws IOException { Path filePath = new Path(path); while(true) { filePath = filePath.getParent(); // if(filePath.isRoot()) { if(filePath.getParent() == null) { break; } resultSet.add(filePath.toString()); } } /* * List all files and sub-directories recursively */ public void fillDirectoryList(FileSystem dfs, String path, HashSet<String> resultSet) throws IOException { FileStatus[] fileStatus = dfs.listStatus(new Path(path)); if (fileStatus != null) { // Go through all resources in directory for (FileStatus fs : fileStatus) { String pathToResource = path + "/" + fs.getPath().getName(); resultSet.add(pathToResource); if (fs.isDir()) { // recursive fillDirectoryList(dfs, pathToResource, resultSet); } } } } }