This is an automated email from the ASF dual-hosted git repository.

hemant pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new d83f434274 HDDS-9423. Throw appropriate error messages when deleting a 
file in .snapshot path (#5814)
d83f434274 is described below

commit d83f434274b9c2d3fe4b7bdcff0b1862a8291c7d
Author: Hemant Kumar <[email protected]>
AuthorDate: Mon Dec 18 23:17:40 2023 -0800

    HDDS-9423. Throw appropriate error messages when deleting a file in 
.snapshot path (#5814)
---
 .../main/java/org/apache/hadoop/ozone/OmUtils.java | 31 +++++++++--
 .../ozone/om/request/key/OMKeyDeleteRequest.java   |  4 +-
 .../om/request/file/TestOMFileCreateRequest.java   | 64 ++++++++--------------
 .../om/request/key/TestOMKeyDeleteRequest.java     | 40 ++++++++++----
 .../ozone/BasicRootedOzoneClientAdapterImpl.java   |  7 ++-
 .../hadoop/ozone/shell/keys/DeleteKeyHandler.java  |  9 +++
 6 files changed, 95 insertions(+), 60 deletions(-)

diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
index babeb30548..f23a703bd0 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
@@ -629,15 +629,36 @@ public final class OmUtils {
         if (keyName.substring(OM_SNAPSHOT_INDICATOR.length())
             .startsWith(OM_KEY_PREFIX)) {
           throw new OMException(
-              "Cannot create key under path reserved for "
-                  + "snapshot: " + OM_SNAPSHOT_INDICATOR + OM_KEY_PREFIX,
+              "Cannot create key under path reserved for snapshot: " + 
OM_SNAPSHOT_INDICATOR + OM_KEY_PREFIX,
               OMException.ResultCodes.INVALID_KEY_NAME);
         }
       } else {
-        // We checked for startsWith OM_SNAPSHOT_INDICATOR and the length is
+        // We checked for startsWith OM_SNAPSHOT_INDICATOR, and the length is
         // the same, so it must be equal OM_SNAPSHOT_INDICATOR.
-        throw new OMException(
-            "Cannot create key with reserved name: " + OM_SNAPSHOT_INDICATOR,
+        throw new OMException("Cannot create key with reserved name: " + 
OM_SNAPSHOT_INDICATOR,
+            OMException.ResultCodes.INVALID_KEY_NAME);
+      }
+    }
+  }
+
+  /**
+   * Verify if key name contains snapshot reserved word.
+   * This is similar to verifyKeyNameWithSnapshotReservedWord. The only 
difference is exception message.
+   */
+  public static void verifyKeyNameWithSnapshotReservedWordForDeletion(String 
keyName)  throws OMException {
+    if (keyName != null &&
+        keyName.startsWith(OM_SNAPSHOT_INDICATOR)) {
+      if (keyName.length() > OM_SNAPSHOT_INDICATOR.length()) {
+        if (keyName.substring(OM_SNAPSHOT_INDICATOR.length())
+            .startsWith(OM_KEY_PREFIX)) {
+          throw new OMException(
+              "Cannot delete key under path reserved for snapshot: " + 
OM_SNAPSHOT_INDICATOR + OM_KEY_PREFIX,
+              OMException.ResultCodes.INVALID_KEY_NAME);
+        }
+      } else {
+        // We checked for startsWith OM_SNAPSHOT_INDICATOR, and the length is
+        // the same, so it must be equal OM_SNAPSHOT_INDICATOR.
+        throw new OMException("Cannot delete key with reserved name: " + 
OM_SNAPSHOT_INDICATOR,
             OMException.ResultCodes.INVALID_KEY_NAME);
       }
     }
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 9fefd70a2d..0998d00175 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
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.nio.file.InvalidPathException;
 import java.util.Map;
 
+import org.apache.hadoop.ozone.OmUtils;
 import org.apache.hadoop.ozone.om.helpers.BucketLayout;
 import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
 import org.apache.hadoop.ozone.om.request.util.OmResponseUtil;
@@ -76,8 +77,9 @@ public class OMKeyDeleteRequest extends OMKeyRequest {
     Preconditions.checkNotNull(deleteKeyRequest);
 
     OzoneManagerProtocolProtos.KeyArgs keyArgs = deleteKeyRequest.getKeyArgs();
-
     String keyPath = keyArgs.getKeyName();
+
+    OmUtils.verifyKeyNameWithSnapshotReservedWordForDeletion(keyPath);
     keyPath = validateAndNormalizeKey(ozoneManager.getEnableFileSystemPaths(),
         keyPath, getBucketLayout());
 
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/file/TestOMFileCreateRequest.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/file/TestOMFileCreateRequest.java
index dbd2a80964..0a7a352b38 100644
--- 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/file/TestOMFileCreateRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/file/TestOMFileCreateRequest.java
@@ -23,8 +23,6 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
 import java.util.stream.Collectors;
-import java.util.Map;
-import java.util.HashMap;
 
 import org.apache.hadoop.ozone.om.exceptions.OMException;
 import org.apache.hadoop.ozone.OzoneAcl;
@@ -41,15 +39,12 @@ import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo;
 import org.apache.hadoop.ozone.om.request.key.TestOMKeyRequest;
 import org.apache.hadoop.ozone.om.response.OMClientResponse;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
-import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
-    .CreateFileRequest;
-import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
-    .KeyArgs;
-import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
-    .OMRequest;
-
-import static org.apache.hadoop.ozone.OzoneConsts.OM_KEY_PREFIX;
-import static org.apache.hadoop.ozone.OzoneConsts.OM_SNAPSHOT_INDICATOR;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateFileRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyArgs;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
 import static 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status.VOLUME_NOT_FOUND;
 import static 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status.BUCKET_NOT_FOUND;
 import static 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status.FILE_ALREADY_EXISTS;
@@ -481,40 +476,25 @@ public class TestOMFileCreateRequest extends 
TestOMKeyRequest {
     }
   }
 
-  @Test
-  public void testPreExecuteWithInvalidKeyPrefix() throws Exception {
-    Map<String, String> invalidKeyScenarios = new HashMap<String, String>() {
-      {
-        put(OM_SNAPSHOT_INDICATOR + "/" + keyName,
-            "Cannot create key under path reserved for snapshot: "
-                + OM_SNAPSHOT_INDICATOR + OM_KEY_PREFIX);
-        put(OM_SNAPSHOT_INDICATOR + "/a/" + keyName,
-            "Cannot create key under path reserved for snapshot: "
-                + OM_SNAPSHOT_INDICATOR + OM_KEY_PREFIX);
-        put(OM_SNAPSHOT_INDICATOR + "/a/b" + keyName,
-            "Cannot create key under path reserved for snapshot: "
-                + OM_SNAPSHOT_INDICATOR + OM_KEY_PREFIX);
-        put(OM_SNAPSHOT_INDICATOR,
-            "Cannot create key with reserved name: " + OM_SNAPSHOT_INDICATOR);
-      }
-    };
-
-    for (Map.Entry<String, String> entry : invalidKeyScenarios.entrySet()) {
-      String invalidKeyName = entry.getKey();
-      String expectedErrorMessage = entry.getValue();
+  @ParameterizedTest
+  @CsvSource(value = {
+      ".snapshot/keyName,Cannot create key under path reserved for snapshot: 
.snapshot/",
+      ".snapshot/a/keyName,Cannot create key under path reserved for snapshot: 
.snapshot/",
+      ".snapshot/a/b/keyName,Cannot create key under path reserved for 
snapshot: .snapshot/",
+      ".snapshot,Cannot create key with reserved name: .snapshot"})
+  public void testPreExecuteWithInvalidKeyPrefix(String invalidKeyName,
+                                                 String expectedErrorMessage) {
 
-      OMRequest omRequest = createFileRequest(volumeName, bucketName,
-          invalidKeyName, HddsProtos.ReplicationFactor.ONE,
-          HddsProtos.ReplicationType.RATIS, false, false);
-
-      OMFileCreateRequest omFileCreateRequest =
-          getOMFileCreateRequest(omRequest);
+    OMRequest omRequest = createFileRequest(volumeName, bucketName,
+        invalidKeyName, HddsProtos.ReplicationFactor.ONE,
+        HddsProtos.ReplicationType.RATIS, false, false);
 
-      OMException ex = Assertions.assertThrows(OMException.class,
-          () -> omFileCreateRequest.preExecute(ozoneManager));
+    OMFileCreateRequest omFileCreateRequest =
+        getOMFileCreateRequest(omRequest);
 
-      Assertions.assertTrue(ex.getMessage().contains(expectedErrorMessage));
-    }
+    OMException ex = Assertions.assertThrows(OMException.class,
+        () -> omFileCreateRequest.preExecute(ozoneManager));
+    Assertions.assertTrue(ex.getMessage().contains(expectedErrorMessage));
   }
 
   protected void testNonRecursivePath(String key,
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyDeleteRequest.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyDeleteRequest.java
index fe84e3cfbe..907022cedd 100644
--- 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyDeleteRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/key/TestOMKeyDeleteRequest.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.ozone.om.request.key;
 
 import java.util.UUID;
 
+import org.apache.hadoop.ozone.om.exceptions.OMException;
 import org.apache.hadoop.ozone.om.helpers.BucketLayout;
 import org.apache.hadoop.ozone.om.request.OMRequestTestUtils;
 import org.junit.jupiter.api.Assertions;
@@ -28,21 +29,36 @@ import org.junit.jupiter.api.Test;
 import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
 import org.apache.hadoop.ozone.om.response.OMClientResponse;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
-import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
-    .DeleteKeyRequest;
-import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
-    .OMRequest;
-import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
-    .KeyArgs;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DeleteKeyRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyArgs;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.ValueSource;
 
 /**
  * Tests OmKeyDelete request.
  */
 public class TestOMKeyDeleteRequest extends TestOMKeyRequest {
 
-  @Test
-  public void testPreExecute() throws Exception {
-    doPreExecute(createDeleteKeyRequest());
+  @ParameterizedTest
+  @ValueSource(strings = {"keyName", "a/b/keyName", "a/.snapshot/keyName", 
"a.snapshot/b/keyName"})
+  public void testPreExecute(String testKeyName) throws Exception {
+    doPreExecute(createDeleteKeyRequest(testKeyName));
+  }
+
+  @ParameterizedTest
+  @CsvSource(value = {".snapshot,Cannot delete key with reserved name: 
.snapshot",
+      ".snapshot/snapName,Cannot delete key under path reserved for snapshot: 
.snapshot/",
+      ".snapshot/snapName/keyName,Cannot delete key under path reserved for 
snapshot: .snapshot/"})
+  public void testPreExecuteFailure(String testKeyName,
+                                    String expectedExceptionMessage) {
+    OMKeyDeleteRequest deleteKeyRequest =
+        getOmKeyDeleteRequest(createDeleteKeyRequest(testKeyName));
+    OMException omException = Assertions.assertThrows(OMException.class,
+        () -> deleteKeyRequest.preExecute(ozoneManager));
+    Assertions.assertEquals(expectedExceptionMessage, 
omException.getMessage());
+    Assertions.assertEquals(OMException.ResultCodes.INVALID_KEY_NAME, 
omException.getResult());
   }
 
   @Test
@@ -154,8 +170,12 @@ public class TestOMKeyDeleteRequest extends 
TestOMKeyRequest {
    * @return OMRequest
    */
   private OMRequest createDeleteKeyRequest() {
+    return createDeleteKeyRequest(keyName);
+  }
+
+  private OMRequest createDeleteKeyRequest(String testKeyName) {
     KeyArgs keyArgs = KeyArgs.newBuilder().setBucketName(bucketName)
-        .setVolumeName(volumeName).setKeyName(keyName).build();
+        .setVolumeName(volumeName).setKeyName(testKeyName).build();
 
     DeleteKeyRequest deleteKeyRequest =
         DeleteKeyRequest.newBuilder().setKeyArgs(keyArgs).build();
diff --git 
a/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicRootedOzoneClientAdapterImpl.java
 
b/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicRootedOzoneClientAdapterImpl.java
index e565c2bedf..193e080f0e 100644
--- 
a/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicRootedOzoneClientAdapterImpl.java
+++ 
b/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicRootedOzoneClientAdapterImpl.java
@@ -40,6 +40,7 @@ import org.apache.hadoop.fs.FileStatus;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.PathIsNotEmptyDirectoryException;
+import org.apache.hadoop.fs.PathPermissionException;
 import org.apache.hadoop.fs.SafeModeAction;
 import org.apache.hadoop.fs.permission.FsPermission;
 import org.apache.hadoop.hdds.client.ReplicationConfig;
@@ -545,13 +546,15 @@ public class BasicRootedOzoneClientAdapterImpl
       bucket.deleteDirectory(keyName, recursive);
       return true;
     } catch (OMException ome) {
-      LOG.error("delete key failed {}", ome.getMessage());
+      LOG.error("Delete key failed. {}", ome.getMessage());
       if (OMException.ResultCodes.DIRECTORY_NOT_EMPTY == ome.getResult()) {
         throw new PathIsNotEmptyDirectoryException(ome.getMessage());
+      } else if (OMException.ResultCodes.INVALID_KEY_NAME == ome.getResult()) {
+        throw new PathPermissionException(ome.getMessage());
       }
       return false;
     } catch (IOException ioe) {
-      LOG.error("delete key failed " + ioe.getMessage());
+      LOG.error("Delete key failed. {}", ioe.getMessage());
       return false;
     }
   }
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/keys/DeleteKeyHandler.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/keys/DeleteKeyHandler.java
index 5e56cda478..d1a6a4e156 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/keys/DeleteKeyHandler.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/keys/DeleteKeyHandler.java
@@ -19,11 +19,13 @@
 package org.apache.hadoop.ozone.shell.keys;
 
 import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.ozone.OmUtils;
 import org.apache.hadoop.ozone.client.OzoneBucket;
 import org.apache.hadoop.ozone.client.OzoneClient;
 import org.apache.hadoop.ozone.client.OzoneClientException;
 import org.apache.hadoop.ozone.client.OzoneKeyDetails;
 import org.apache.hadoop.ozone.client.OzoneVolume;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
 import org.apache.hadoop.ozone.om.helpers.OzoneFileStatus;
 import org.apache.hadoop.ozone.shell.OzoneAddress;
 import org.apache.hadoop.ozone.om.OMConfigKeys;
@@ -59,6 +61,13 @@ public class DeleteKeyHandler extends KeyHandler {
     OzoneBucket bucket = vol.getBucket(bucketName);
     String keyName = address.getKeyName();
 
+    try {
+      OmUtils.verifyKeyNameWithSnapshotReservedWordForDeletion(keyName);
+    } catch (OMException omException) {
+      out().printf("Operation not permitted: %s %n", omException.getMessage());
+      return;
+    }
+
     if (bucket.getBucketLayout().isFileSystemOptimized()) {
       // Handle FSO delete key which supports trash also
       deleteFSOKey(bucket, keyName);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to