diff --git a/hadoop-hdds/common/src/main/resources/ozone-default.xml b/hadoop-hdds/common/src/main/resources/ozone-default.xml index d8fc591a1795..b474ac38c2f1 100644 --- a/hadoop-hdds/common/src/main/resources/ozone-default.xml +++ b/hadoop-hdds/common/src/main/resources/ozone-default.xml @@ -2478,4 +2478,19 @@ rules in Amazon S3's object key naming guide. + + + ozone.om.enable.filesystem.paths + OZONE, OM + false + If true, key names will be interpreted as file system paths. + "/" will be treated as a special character and paths will be normalized + and must follow Unix filesystem path naming conventions. This flag will + be helpful when objects created by S3G need to be accessed using OFS/O3Fs. + If false, it will fallback to default behavior of Key/MPU create + requests where key paths are not normalized and any intermediate + directories will not be created or any file checks happens to check + filesystem semantics. + + diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java index 4f512a55032d..f16679a681eb 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/OMConfigKeys.java @@ -239,4 +239,11 @@ private OMConfigKeys() { "ozone.om.keyname.character.check.enabled"; public static final boolean OZONE_OM_KEYNAME_CHARACTER_CHECK_ENABLED_DEFAULT = false; + + // This config needs to be enabled, when S3G created objects used via + // FileSystem API. + public static final String OZONE_OM_ENABLE_FILESYSTEM_PATHS = + "ozone.om.enable.filesystem.paths"; + public static final boolean OZONE_OM_ENABLE_FILESYSTEM_PATHS_DEFAULT = + false; } diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestOzoneFSWithObjectStoreCreate.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestOzoneFSWithObjectStoreCreate.java new file mode 100644 index 000000000000..b872a3d8694a --- /dev/null +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestOzoneFSWithObjectStoreCreate.java @@ -0,0 +1,132 @@ +/** + * 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.fs.ozone; + +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.hadoop.fs.FileStatus; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hdds.conf.OzoneConfiguration; +import org.apache.hadoop.ozone.MiniOzoneCluster; +import org.apache.hadoop.ozone.TestDataUtil; +import org.apache.hadoop.ozone.client.OzoneBucket; +import org.apache.hadoop.ozone.client.OzoneVolume; +import org.apache.hadoop.ozone.client.io.OzoneOutputStream; +import org.apache.hadoop.ozone.om.OMConfigKeys; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.Timeout; + +import java.net.URI; +import java.util.Arrays; + +import static org.apache.hadoop.ozone.OzoneConsts.OZONE_URI_SCHEME; + +/** + * Class tests create with object store and getFileStatus. + */ +public class TestOzoneFSWithObjectStoreCreate { + + @Rule + public Timeout timeout = new Timeout(300000); + + private String rootPath; + + private MiniOzoneCluster cluster = null; + + private OzoneFileSystem o3fs; + + private String volumeName; + + private String bucketName; + + + @Before + public void init() throws Exception { + volumeName = RandomStringUtils.randomAlphabetic(10).toLowerCase(); + bucketName = RandomStringUtils.randomAlphabetic(10).toLowerCase(); + + OzoneConfiguration conf = new OzoneConfiguration(); + + conf.setBoolean(OMConfigKeys.OZONE_OM_ENABLE_FILESYSTEM_PATHS, true); + cluster = MiniOzoneCluster.newBuilder(conf) + .setNumDatanodes(3) + .build(); + cluster.waitForClusterToBeReady(); + + // create a volume and a bucket to be used by OzoneFileSystem + OzoneBucket bucket = + TestDataUtil.createVolumeAndBucket(cluster, volumeName, bucketName); + + rootPath = String.format("%s://%s.%s/", OZONE_URI_SCHEME, bucketName, + volumeName); + o3fs = (OzoneFileSystem) FileSystem.get(new URI(rootPath), conf); + } + + + @Test + public void test() throws Exception { + + OzoneVolume ozoneVolume = + cluster.getRpcClient().getObjectStore().getVolume(volumeName); + + OzoneBucket ozoneBucket = ozoneVolume.getBucket(bucketName); + + String key1 = "///dir1/dir2/file1"; + String key2 = "///dir1/dir2/file2"; + int length = 10; + OzoneOutputStream ozoneOutputStream = ozoneBucket.createKey(key1, length); + byte[] b = new byte[10]; + Arrays.fill(b, (byte)96); + ozoneOutputStream.write(b); + ozoneOutputStream.close(); + + ozoneOutputStream = ozoneBucket.createKey(key2, length); + ozoneOutputStream.write(b); + ozoneOutputStream.close(); + + // Adding "/" here otherwise Path will be considered as relative path and + // workingDir will be added. + key1 = "///dir1/dir2/file1"; + Path p = new Path(key1); + Assert.assertTrue(o3fs.getFileStatus(p).isFile()); + + p = p.getParent(); + checkAncestors(p); + + + key2 = "///dir1/dir2/file2"; + p = new Path(key2); + Assert.assertTrue(o3fs.getFileStatus(p).isFile()); + checkAncestors(p); + + } + + private void checkAncestors(Path p) throws Exception { + p = p.getParent(); + while(p.getParent() != null) { + FileStatus fileStatus = o3fs.getFileStatus(p); + Assert.assertTrue(fileStatus.isDirectory()); + p = p.getParent(); + } + } + +} diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java index 8a49fa780b37..43ae99835a91 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java @@ -200,6 +200,8 @@ import static org.apache.hadoop.ozone.OzoneConsts.OM_METRICS_TEMP_FILE; import static org.apache.hadoop.ozone.OzoneConsts.RPC_PORT; import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ADDRESS_KEY; +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ENABLE_FILESYSTEM_PATHS; +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ENABLE_FILESYSTEM_PATHS_DEFAULT; import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_HANDLER_COUNT_DEFAULT; import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_HANDLER_COUNT_KEY; import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_KERBEROS_KEYTAB_FILE_KEY; @@ -3494,4 +3496,10 @@ private Pair resolveBucketLink( void setExitManagerForTesting(ExitManager exitManagerForTesting) { this.exitManager = exitManagerForTesting; } + + + public boolean getEnableFileSystemPaths() { + return configuration.getBoolean(OZONE_OM_ENABLE_FILESYSTEM_PATHS, + OZONE_OM_ENABLE_FILESYSTEM_PATHS_DEFAULT); + } } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/OMClientRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/OMClientRequest.java index 4ced9fdfdba3..0fa9ca1a8d2c 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/OMClientRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/OMClientRequest.java @@ -20,6 +20,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.ipc.ProtobufRpcEngine; import org.apache.hadoop.ozone.OzoneConsts; @@ -38,13 +39,18 @@ import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer; import org.apache.hadoop.ozone.security.acl.OzoneObj; import org.apache.hadoop.security.UserGroupInformation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; import java.io.IOException; import java.net.InetAddress; +import java.nio.file.Paths; import java.util.LinkedHashMap; import java.util.Map; +import static org.apache.hadoop.ozone.OzoneConsts.OM_KEY_PREFIX; +import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.INVALID_KEY_NAME; /** * OMClientRequest provides methods which every write OM request should @@ -52,6 +58,8 @@ */ public abstract class OMClientRequest implements RequestAuditor { + private static final Logger LOG = + LoggerFactory.getLogger(OMClientRequest.class); private OMRequest omRequest; /** @@ -265,4 +273,72 @@ public Map buildVolumeAuditMap(String volume) { auditMap.put(OzoneConsts.VOLUME, volume); return auditMap; } + + + public static String validateAndNormalizeKey(boolean enableFileSystemPaths, + String keyName) throws OMException { + if (enableFileSystemPaths) { + return validateAndNormalizeKey(keyName); + } else { + return keyName; + } + } + + @SuppressFBWarnings("DMI_HARDCODED_ABSOLUTE_FILENAME") + public static String validateAndNormalizeKey(String keyName) + throws OMException { + String normalizedKeyName; + if (keyName.startsWith(OM_KEY_PREFIX)) { + normalizedKeyName = Paths.get(keyName).toUri().normalize().getPath(); + } else { + normalizedKeyName = Paths.get(OM_KEY_PREFIX, keyName).toUri() + .normalize().getPath(); + } + if (!keyName.equals(normalizedKeyName)) { + LOG.debug("Normalized key {} to {} ", keyName, + normalizedKeyName.substring(1)); + } + return isValidKeyPath(normalizedKeyName.substring(1)); + } + + /** + * Whether the pathname is valid. Check key names which contain a + * ":", ".", "..", "//", "". If it has any of these characters throws + * OMException, else return the path. + */ + private static String isValidKeyPath(String path) throws OMException { + boolean isValid = true; + + // If keyName is empty string throw error. + if (path.length() == 0) { + throw new OMException("Invalid KeyPath, empty keyName" + path, + INVALID_KEY_NAME); + } else if(path.startsWith("/")) { + isValid = false; + } else { + // Check for ".." "." ":" "/" + String[] components = StringUtils.split(path, '/'); + for (int i = 0; i < components.length; i++) { + String element = components[i]; + if (element.equals(".") || + (element.contains(":")) || + (element.contains("/") || element.equals(".."))) { + isValid = false; + break; + } + + // The string may end with a /, but not have + // "//" in the middle. + if (element.isEmpty() && i != components.length - 1) { + isValid = false; + } + } + } + + if (isValid) { + return path; + } else { + throw new OMException("Invalid KeyPath " + path, INVALID_KEY_NAME); + } + } } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMFileRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMFileRequest.java index 3367ec7e4758..21ffff815e09 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMFileRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMFileRequest.java @@ -197,7 +197,7 @@ public boolean directParentExists() { /** * Return codes used by verifyFilesInPath method. */ - enum OMDirectoryResult { + public enum OMDirectoryResult { // In below examples path is assumed as "a/b/c" in volume volume1 and // bucket b1. diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMAllocateBlockRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMAllocateBlockRequest.java index 9e82888be457..94d700f271b0 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMAllocateBlockRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMAllocateBlockRequest.java @@ -110,9 +110,11 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { ozoneManager.getPreallocateBlocksMax(), ozoneManager.isGrpcBlockTokenEnabled(), ozoneManager.getOMNodeId()); - // Set modification time + // Set modification time and normalize key if required. KeyArgs.Builder newKeyArgs = keyArgs.toBuilder() - .setModificationTime(Time.now()); + .setModificationTime(Time.now()) + .setKeyName(validateAndNormalizeKey( + ozoneManager.getEnableFileSystemPaths(), keyArgs.getKeyName())); AllocateBlockRequest.Builder newAllocatedBlockRequest = AllocateBlockRequest.newBuilder() diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java index eb3769b70ddd..dccb93bb9da3 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java @@ -91,7 +91,9 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { } KeyArgs.Builder newKeyArgs = - keyArgs.toBuilder().setModificationTime(Time.now()); + keyArgs.toBuilder().setModificationTime(Time.now()) + .setKeyName(validateAndNormalizeKey( + ozoneManager.getEnableFileSystemPaths(), keyArgs.getKeyName())); return getOmRequest().toBuilder() .setCommitKeyRequest(commitKeyRequest.toBuilder() diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCreateRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCreateRequest.java index f7f08dc75c09..8927c1931c0d 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCreateRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCreateRequest.java @@ -19,6 +19,7 @@ package org.apache.hadoop.ozone.om.request.key; import java.io.IOException; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -27,7 +28,11 @@ import com.google.common.base.Optional; import com.google.common.base.Preconditions; import org.apache.hadoop.ozone.OmUtils; +import org.apache.hadoop.ozone.OzoneAcl; import org.apache.hadoop.ozone.om.OMConfigKeys; +import org.apache.hadoop.ozone.om.exceptions.OMException; +import org.apache.hadoop.ozone.om.request.file.OMDirectoryCreateRequest; +import org.apache.hadoop.ozone.om.request.file.OMFileRequest; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,7 +68,10 @@ import org.apache.hadoop.util.Time; import org.apache.hadoop.hdds.utils.UniqueId; +import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.NOT_A_FILE; import static org.apache.hadoop.ozone.om.lock.OzoneManagerLock.Resource.BUCKET_LOCK; +import static org.apache.hadoop.ozone.om.request.file.OMFileRequest.OMDirectoryResult.DIRECTORY_EXISTS; +import static org.apache.hadoop.ozone.om.request.file.OMFileRequest.OMDirectoryResult.FILE_EXISTS_IN_GIVENPATH; /** * Handles CreateKey request. @@ -91,6 +99,20 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { if(checkKeyNameEnabled){ OmUtils.validateKeyName(keyArgs.getKeyName()); } + + String keyPath = keyArgs.getKeyName(); + if (ozoneManager.getEnableFileSystemPaths()) { + // If enabled, disallow keys with trailing /. As in fs semantics + // directories end with trailing /. + keyPath = validateAndNormalizeKey( + ozoneManager.getEnableFileSystemPaths(), keyPath); + if (keyPath.endsWith("/")) { + throw new OMException("Invalid KeyPath, key names with trailing / " + + "are not allowed." + keyPath, + OMException.ResultCodes.INVALID_KEY_NAME); + } + } + // We cannot allocate block for multipart upload part when // createMultipartKey is called, as we will not know type and factor with // which initiateMultipartUpload has started for this key. When @@ -131,7 +153,7 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { // As for a client for the first time this can be executed on any OM, // till leader is identified. - List< OmKeyLocationInfo > omKeyLocationInfoList = + List omKeyLocationInfoList = allocateBlock(ozoneManager.getScmClient(), ozoneManager.getBlockTokenSecretManager(), type, factor, new ExcludeList(), requestedSize, scmBlockSize, @@ -149,7 +171,10 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { newKeyArgs = keyArgs.toBuilder().setModificationTime(Time.now()); } + newKeyArgs.setKeyName(keyPath); + generateRequiredEncryptionInfo(keyArgs, newKeyArgs, ozoneManager); + newCreateKeyRequest = createKeyRequest.toBuilder().setKeyArgs(newKeyArgs) .setClientID(UniqueId.next()); @@ -160,6 +185,7 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { } @Override + @SuppressWarnings("methodlength") public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, long trxnLogIndex, OzoneManagerDoubleBufferHelper omDoubleBufferHelper) { CreateKeyRequest createKeyRequest = getOmRequest().getCreateKeyRequest(); @@ -184,6 +210,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, getOmRequest()); IOException exception = null; Result result = null; + List missingParentInfos = null; try { keyArgs = resolveBucketLink(ozoneManager, keyArgs, auditMap); volumeName = keyArgs.getVolumeName(); @@ -209,8 +236,41 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, OmBucketInfo bucketInfo = omMetadataManager.getBucketTable().get( omMetadataManager.getBucketKey(volumeName, bucketName)); + // If FILE_EXISTS we just override like how we used to do for Key Create. + List< OzoneAcl > inheritAcls; + if (ozoneManager.getEnableFileSystemPaths()) { + OMFileRequest.OMPathInfo pathInfo = + OMFileRequest.verifyFilesInPath(omMetadataManager, volumeName, + bucketName, keyName, Paths.get(keyName)); + OMFileRequest.OMDirectoryResult omDirectoryResult = + pathInfo.getDirectoryResult(); + inheritAcls = pathInfo.getAcls(); + + // Check if a file or directory exists with same key name. + if (omDirectoryResult == DIRECTORY_EXISTS) { + throw new OMException("Cannot write to " + + "directory. createIntermediateDirs behavior is enabled and " + + "hence / has special interpretation: " + keyName, NOT_A_FILE); + } else + if (omDirectoryResult == FILE_EXISTS_IN_GIVENPATH) { + throw new OMException("Can not create file: " + keyName + + " as there is already file in the given path", NOT_A_FILE); + } + + missingParentInfos = OMDirectoryCreateRequest + .getAllParentInfo(ozoneManager, keyArgs, + pathInfo.getMissingParents(), inheritAcls, trxnLogIndex); + + // Add cache entries for the prefix directories. + // Skip adding for the file key itself, until Key Commit. + OMFileRequest.addKeyTableCacheEntries(omMetadataManager, volumeName, + bucketName, Optional.absent(), Optional.of(missingParentInfos), + trxnLogIndex); + + } + omKeyInfo = prepareKeyInfo(omMetadataManager, keyArgs, dbKeyInfo, - keyArgs.getDataSize(), locations, getFileEncryptionInfo(keyArgs), + keyArgs.getDataSize(), locations, getFileEncryptionInfo(keyArgs), ozoneManager.getPrefixManager(), bucketInfo, trxnLogIndex, ozoneManager.isRatisEnabled()); @@ -238,7 +298,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, .setOpenVersion(openVersion).build()) .setCmdType(Type.CreateKey); omClientResponse = new OMKeyCreateResponse(omResponse.build(), - omKeyInfo, null, clientID); + omKeyInfo, missingParentInfos, clientID); result = Result.SUCCESS; } catch (IOException ex) { @@ -269,7 +329,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, break; case FAILURE: LOG.error("Key creation failed. Volume:{}, Bucket:{}, Key{}. " + - "Exception:{}", volumeName, bucketName, keyName, exception); + "Exception:{}", volumeName, bucketName, keyName, exception); break; default: LOG.error("Unrecognized Result for OMKeyCreateRequest: {}", diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java index 8b7541734206..4d8562c206d6 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java @@ -75,7 +75,9 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { OzoneManagerProtocolProtos.KeyArgs keyArgs = deleteKeyRequest.getKeyArgs(); OzoneManagerProtocolProtos.KeyArgs.Builder newKeyArgs = - keyArgs.toBuilder().setModificationTime(Time.now()); + keyArgs.toBuilder().setModificationTime(Time.now()) + .setKeyName(validateAndNormalizeKey( + ozoneManager.getEnableFileSystemPaths(), keyArgs.getKeyName())); return getOmRequest().toBuilder() .setDeleteKeyRequest(deleteKeyRequest.toBuilder() diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java index 91db347c1470..e6e9839062b1 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java @@ -85,13 +85,22 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { OmUtils.validateKeyName(renameKeyRequest.getToKeyName()); } - // Set modification time. - KeyArgs.Builder newKeyArgs = renameKeyRequest.getKeyArgs().toBuilder() - .setModificationTime(Time.now()); + KeyArgs renameKeyArgs = renameKeyRequest.getKeyArgs(); + + // Set modification time and normalize key if needed. + KeyArgs.Builder newKeyArgs = renameKeyArgs.toBuilder() + .setModificationTime(Time.now()) + .setKeyName(validateAndNormalizeKey( + ozoneManager.getEnableFileSystemPaths(), + renameKeyArgs.getKeyName())); return getOmRequest().toBuilder() .setRenameKeyRequest(renameKeyRequest.toBuilder() - .setKeyArgs(newKeyArgs)).setUserInfo(getUserInfo()).build(); + .setKeyArgs(newKeyArgs) + .setToKeyName(validateAndNormalizeKey( + ozoneManager.getEnableFileSystemPaths(), + renameKeyRequest.getToKeyName()))) + .setUserInfo(getUserInfo()).build(); } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3InitiateMultipartUploadRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3InitiateMultipartUploadRequest.java index aa96ba995ab9..f7951a296807 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3InitiateMultipartUploadRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3InitiateMultipartUploadRequest.java @@ -33,7 +33,7 @@ import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.response.OMClientResponse; import org.apache.hadoop.ozone.om.response.s3.multipart.S3InitiateMultipartUploadResponse; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyArgs; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.MultipartInfoInitiateRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.MultipartInfoInitiateResponse; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; @@ -67,15 +67,17 @@ public S3InitiateMultipartUploadRequest(OMRequest omRequest) { } @Override - public OMRequest preExecute(OzoneManager ozoneManager) { + public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { MultipartInfoInitiateRequest multipartInfoInitiateRequest = getOmRequest().getInitiateMultiPartUploadRequest(); Preconditions.checkNotNull(multipartInfoInitiateRequest); - OzoneManagerProtocolProtos.KeyArgs.Builder newKeyArgs = - multipartInfoInitiateRequest.getKeyArgs().toBuilder() + KeyArgs keyArgs = multipartInfoInitiateRequest.getKeyArgs(); + KeyArgs.Builder newKeyArgs = keyArgs.toBuilder() .setMultipartUploadID(UUID.randomUUID().toString() + "-" + - UniqueId.next()).setModificationTime(Time.now()); + UniqueId.next()).setModificationTime(Time.now()) + .setKeyName(validateAndNormalizeKey( + ozoneManager.getEnableFileSystemPaths(), keyArgs.getKeyName())); return getOmRequest().toBuilder() .setUserInfo(getUserInfo()) @@ -92,7 +94,7 @@ public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, MultipartInfoInitiateRequest multipartInfoInitiateRequest = getOmRequest().getInitiateMultiPartUploadRequest(); - OzoneManagerProtocolProtos.KeyArgs keyArgs = + KeyArgs keyArgs = multipartInfoInitiateRequest.getKeyArgs(); Preconditions.checkNotNull(keyArgs.getMultipartUploadID()); diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadAbortRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadAbortRequest.java index 0726fe4a9c7e..c0ef8b378261 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadAbortRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadAbortRequest.java @@ -73,7 +73,10 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { return getOmRequest().toBuilder().setAbortMultiPartUploadRequest( getOmRequest().getAbortMultiPartUploadRequest().toBuilder() - .setKeyArgs(keyArgs.toBuilder().setModificationTime(Time.now()))) + .setKeyArgs(keyArgs.toBuilder().setModificationTime(Time.now()) + .setKeyName(validateAndNormalizeKey( + ozoneManager.getEnableFileSystemPaths(), + keyArgs.getKeyName())))) .setUserInfo(getUserInfo()).build(); } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCommitPartRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCommitPartRequest.java index 283a22dc37b7..1e29d5f3f212 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCommitPartRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCommitPartRequest.java @@ -70,14 +70,17 @@ public S3MultipartUploadCommitPartRequest(OMRequest omRequest) { } @Override - public OMRequest preExecute(OzoneManager ozoneManager) { + public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { MultipartCommitUploadPartRequest multipartCommitUploadPartRequest = getOmRequest().getCommitMultiPartUploadRequest(); + KeyArgs keyArgs = multipartCommitUploadPartRequest.getKeyArgs(); return getOmRequest().toBuilder().setCommitMultiPartUploadRequest( multipartCommitUploadPartRequest.toBuilder() - .setKeyArgs(multipartCommitUploadPartRequest.getKeyArgs() - .toBuilder().setModificationTime(Time.now()))) + .setKeyArgs(keyArgs.toBuilder().setModificationTime(Time.now()) + .setKeyName(validateAndNormalizeKey( + ozoneManager.getEnableFileSystemPaths(), + keyArgs.getKeyName())))) .setUserInfo(getUserInfo()).build(); } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCompleteRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCompleteRequest.java index a9aefa08a5b8..83cc28b01070 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCompleteRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCompleteRequest.java @@ -81,7 +81,10 @@ public OMRequest preExecute(OzoneManager ozoneManager) throws IOException { return getOmRequest().toBuilder() .setCompleteMultiPartUploadRequest(multipartUploadCompleteRequest .toBuilder().setKeyArgs(keyArgs.toBuilder() - .setModificationTime(Time.now()))) + .setModificationTime(Time.now()) + .setKeyName(validateAndNormalizeKey( + ozoneManager.getEnableFileSystemPaths(), + keyArgs.getKeyName())))) .setUserInfo(getUserInfo()).build(); } diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestNormalizePaths.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestNormalizePaths.java new file mode 100644 index 000000000000..6137444b2296 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestNormalizePaths.java @@ -0,0 +1,109 @@ +/* + * 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.ozone.om.request; + +import org.apache.hadoop.ozone.om.exceptions.OMException; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.apache.hadoop.ozone.om.request.OMClientRequest.validateAndNormalizeKey; +import static org.junit.Assert.fail; + +/** + * Class to test normalize paths. + */ +public class TestNormalizePaths { + + @Rule + public ExpectedException exceptionRule = ExpectedException.none(); + + @Test + public void testNormalizePathsEnabled() throws Exception { + + Assert.assertEquals("a/b/c/d", + validateAndNormalizeKey(true, "a/b/c/d")); + Assert.assertEquals("a/b/c/d", + validateAndNormalizeKey(true, "/a/b/c/d")); + Assert.assertEquals("a/b/c/d", + validateAndNormalizeKey(true, "////a/b/c/d")); + Assert.assertEquals("a/b/c/d", + validateAndNormalizeKey(true, "////a/b/////c/d")); + Assert.assertEquals("a/b/c/...../d", + validateAndNormalizeKey(true, "////a/b/////c/...../d")); + Assert.assertEquals("a/b/d", + validateAndNormalizeKey(true, "/a/b/c/../d")); + Assert.assertEquals("a", + validateAndNormalizeKey(true, "a")); + Assert.assertEquals("a/b", + validateAndNormalizeKey(true, "/a/./b")); + Assert.assertEquals("a/b", + validateAndNormalizeKey(true, ".//a/./b")); + Assert.assertEquals("a/", + validateAndNormalizeKey(true, "/a/.")); + Assert.assertEquals("b/c", + validateAndNormalizeKey(true, "//./b/c/")); + Assert.assertEquals("a/b/c/d", + validateAndNormalizeKey(true, "a/b/c/d/")); + Assert.assertEquals("a/b/c/...../d", + validateAndNormalizeKey(true, "////a/b/////c/...../d/")); + } + + @Test + public void testNormalizeKeyInvalidPaths() throws OMException { + checkInvalidPath("/a/b/c/../../../../../d"); + checkInvalidPath("../a/b/c/"); + checkInvalidPath("/../..a/b/c/"); + checkInvalidPath("//"); + checkInvalidPath("/////"); + checkInvalidPath(""); + checkInvalidPath("/"); + checkInvalidPath("/:/:"); + } + + private void checkInvalidPath(String keyName) { + try { + validateAndNormalizeKey(true, keyName); + fail("checkInvalidPath failed for path " + keyName); + } catch (OMException ex) { + Assert.assertTrue(ex.getMessage().contains("Invalid KeyPath")); + } + } + + + + @Test + public void testNormalizePathsDisable() throws OMException { + + Assert.assertEquals("/a/b/c/d", + validateAndNormalizeKey(false, "/a/b/c/d")); + Assert.assertEquals("////a/b/c/d", + validateAndNormalizeKey(false, "////a/b/c/d")); + Assert.assertEquals("////a/b/////c/d", + validateAndNormalizeKey(false, "////a/b/////c/d")); + Assert.assertEquals("////a/b/////c/...../d", + validateAndNormalizeKey(false, "////a/b/////c/...../d")); + Assert.assertEquals("/a/b/c/../d", + validateAndNormalizeKey(false, "/a/b/c/../d")); + Assert.assertEquals("/a/b/c/../../d", + validateAndNormalizeKey(false, "/a/b/c/../../d")); + } +} diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyCreateRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyCreateRequest.java index b26505b32d37..2b8ffce49958 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyCreateRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyCreateRequest.java @@ -18,10 +18,15 @@ package org.apache.hadoop.ozone.om.request.key; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; import java.util.UUID; +import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.ozone.OzoneConsts; +import org.apache.hadoop.ozone.om.exceptions.OMException; import org.junit.Assert; import org.junit.Test; @@ -37,7 +42,14 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos .OMRequest; +import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor.THREE; +import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationType.RATIS; +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ENABLE_FILESYSTEM_PATHS; import static org.apache.hadoop.ozone.om.request.TestOMRequestUtils.addVolumeAndBucketToDB; +import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status.NOT_A_FILE; +import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status.OK; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.when; /** * Tests OMCreateKeyRequest class. @@ -82,7 +94,7 @@ public void testValidateAndUpdateCache() throws Exception { omKeyCreateRequest.validateAndUpdateCache(ozoneManager, 100L, ozoneManagerDoubleBufferHelper); - Assert.assertEquals(OzoneManagerProtocolProtos.Status.OK, + Assert.assertEquals(OK, omKeyCreateResponse.getOMResponse().getStatus()); // Check open table whether key is added or not. @@ -310,6 +322,11 @@ private OMRequest doPreExecute(OMRequest originalOMRequest) throws Exception { @SuppressWarnings("parameterNumber") private OMRequest createKeyRequest(boolean isMultipartKey, int partNumber) { + return createKeyRequest(isMultipartKey, partNumber, keyName); + } + + private OMRequest createKeyRequest(boolean isMultipartKey, int partNumber, + String keyName) { KeyArgs.Builder keyArgs = KeyArgs.newBuilder() .setVolumeName(volumeName).setBucketName(bucketName) @@ -327,7 +344,170 @@ private OMRequest createKeyRequest(boolean isMultipartKey, int partNumber) { .setCmdType(OzoneManagerProtocolProtos.Type.CreateKey) .setClientId(UUID.randomUUID().toString()) .setCreateKeyRequest(createKeyRequest).build(); + } + + @Test + public void testKeyCreateWithFileSystemPathsEnabled() throws Exception { + + OzoneConfiguration configuration = new OzoneConfiguration(); + configuration.setBoolean(OZONE_OM_ENABLE_FILESYSTEM_PATHS, true); + when(ozoneManager.getConfiguration()).thenReturn(configuration); + when(ozoneManager.getEnableFileSystemPaths()).thenReturn(true); + + // Add volume and bucket entries to DB. + addVolumeAndBucketToDB(volumeName, bucketName, + omMetadataManager); + + + keyName = "dir1/dir2/dir3/file1"; + createAndCheck(keyName); + + // Key with leading '/'. + String keyName = "/a/b/c/file1"; + createAndCheck(keyName); + + // Commit openKey entry. + TestOMRequestUtils.addKeyToTable(false, volumeName, bucketName, + keyName.substring(1), 0L, RATIS, THREE, omMetadataManager); + + // Now create another file in same dir path. + keyName = "/a/b/c/file2"; + createAndCheck(keyName); + + // Create key with multiple /'s + // converted to a/b/c/file5 + keyName = "///a/b///c///file5"; + createAndCheck(keyName); + + // converted to a/b/c/.../file3 + keyName = "///a/b///c//.../file3"; + createAndCheck(keyName); + + // converted to r1/r2 + keyName = "././r1/r2/"; + createAndCheck(keyName); + + // converted to ..d1/d2/d3 + keyName = "..d1/d2/d3/"; + createAndCheck(keyName); + + // Create a file, where a file already exists in the path. + // Now try with a file exists in path. Should fail. + keyName = "/a/b/c/file1/file3"; + checkNotAFile(keyName); + + // Empty keyName. + keyName = ""; + checkNotAValidPath(keyName); + + // Key name ends with / + keyName = "/a/./"; + checkNotAValidPath(keyName); + + keyName = "/////"; + checkNotAValidPath(keyName); + + keyName = "../../b/c"; + checkNotAValidPath(keyName); + + keyName = "../../b/c/"; + checkNotAValidPath(keyName); + + keyName = "../../b:/c/"; + checkNotAValidPath(keyName); + + keyName = ":/c/"; + checkNotAValidPath(keyName); + + keyName = ""; + checkNotAValidPath(keyName); + + keyName = "../a/b"; + checkNotAValidPath(keyName); + + keyName = "/../a/b"; + checkNotAValidPath(keyName); + + } + + private void checkNotAValidPath(String keyName) { + OMRequest omRequest = createKeyRequest(false, 0, keyName); + OMKeyCreateRequest omKeyCreateRequest = new OMKeyCreateRequest(omRequest); + + try { + omKeyCreateRequest.preExecute(ozoneManager); + fail("checkNotAValidPath failed for path" + keyName); + } catch (IOException ex) { + Assert.assertTrue(ex instanceof OMException); + OMException omException = (OMException) ex; + Assert.assertEquals(OMException.ResultCodes.INVALID_KEY_NAME, + omException.getResult()); + } + + + } + private void checkNotAFile(String keyName) throws Exception { + OMRequest omRequest = createKeyRequest(false, 0, keyName); + + OMKeyCreateRequest omKeyCreateRequest = new OMKeyCreateRequest(omRequest); + + omRequest = omKeyCreateRequest.preExecute(ozoneManager); + + omKeyCreateRequest = new OMKeyCreateRequest(omRequest); + + OMClientResponse omClientResponse = + omKeyCreateRequest.validateAndUpdateCache(ozoneManager, + 101L, ozoneManagerDoubleBufferHelper); + + Assert.assertEquals(NOT_A_FILE, + omClientResponse.getOMResponse().getStatus()); + } + + + private void createAndCheck(String keyName) throws Exception { + OMRequest omRequest = createKeyRequest(false, 0, keyName); + + OMKeyCreateRequest omKeyCreateRequest = new OMKeyCreateRequest(omRequest); + + omRequest = omKeyCreateRequest.preExecute(ozoneManager); + + omKeyCreateRequest = new OMKeyCreateRequest(omRequest); + + OMClientResponse omClientResponse = + omKeyCreateRequest.validateAndUpdateCache(ozoneManager, + 101L, ozoneManagerDoubleBufferHelper); + + Assert.assertEquals(OK, omClientResponse.getOMResponse().getStatus()); + + checkCreatedPaths(omKeyCreateRequest, omRequest, keyName); + } + + private void checkCreatedPaths(OMKeyCreateRequest omKeyCreateRequest, + OMRequest omRequest, String keyName) throws Exception { + keyName = omKeyCreateRequest.validateAndNormalizeKey(true, keyName); + // Check intermediate directories created or not. + Path keyPath = Paths.get(keyName); + checkIntermediatePaths(keyPath); + + // Check open key entry + String openKey = omMetadataManager.getOpenKey(volumeName, bucketName, + keyName, omRequest.getCreateKeyRequest().getClientID()); + OmKeyInfo omKeyInfo = omMetadataManager.getOpenKeyTable().get(openKey); + Assert.assertNotNull(omKeyInfo); + } + + + + private void checkIntermediatePaths(Path keyPath) throws Exception { + // Check intermediate paths are created + keyPath = keyPath.getParent(); + while(keyPath != null) { + Assert.assertNotNull(omMetadataManager.getKeyTable().get( + omMetadataManager.getOzoneDirKey(volumeName, bucketName, + keyPath.toString()))); + keyPath = keyPath.getParent(); + } } } diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3InitiateMultipartUploadRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3InitiateMultipartUploadRequest.java index 1d785609b566..5633c726c54e 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3InitiateMultipartUploadRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3InitiateMultipartUploadRequest.java @@ -36,7 +36,7 @@ public class TestS3InitiateMultipartUploadRequest extends TestS3MultipartRequest { @Test - public void testPreExecute() { + public void testPreExecute() throws Exception { doPreExecuteInitiateMPU(UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString()); } diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3MultipartRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3MultipartRequest.java index 0271a7a400b1..f0f040f39479 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3MultipartRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3MultipartRequest.java @@ -107,7 +107,7 @@ public void stop() { * @return OMRequest - returned from preExecute. */ protected OMRequest doPreExecuteInitiateMPU( - String volumeName, String bucketName, String keyName) { + String volumeName, String bucketName, String keyName) throws Exception { OMRequest omRequest = TestOMRequestUtils.createInitiateMPURequest(volumeName, bucketName, keyName); @@ -141,7 +141,8 @@ protected OMRequest doPreExecuteInitiateMPU( */ protected OMRequest doPreExecuteCommitMPU( String volumeName, String bucketName, String keyName, - long clientID, String multipartUploadID, int partNumber) { + long clientID, String multipartUploadID, int partNumber) + throws Exception { // Just set dummy size long dataSize = 100L; diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3MultipartUploadCommitPartRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3MultipartUploadCommitPartRequest.java index 5b220bf4c874..d623b17dcfe1 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3MultipartUploadCommitPartRequest.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/s3/multipart/TestS3MultipartUploadCommitPartRequest.java @@ -38,7 +38,7 @@ public class TestS3MultipartUploadCommitPartRequest extends TestS3MultipartRequest { @Test - public void testPreExecute() { + public void testPreExecute() throws Exception { String volumeName = UUID.randomUUID().toString(); String bucketName = UUID.randomUUID().toString(); String keyName = UUID.randomUUID().toString();