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 a1f839036a HDDS-10010. Support snapshot rename operation (#6006)
a1f839036a is described below

commit a1f839036a77cb7d6e95dfa181d29bee93a3ea91
Author: Cyrill <[email protected]>
AuthorDate: Tue Feb 20 21:57:29 2024 +0300

    HDDS-10010. Support snapshot rename operation (#6006)
---
 .../apache/hadoop/ozone/client/ObjectStore.java    |  15 +
 .../ozone/client/protocol/ClientProtocol.java      |  13 +
 .../apache/hadoop/ozone/client/rpc/RpcClient.java  |  25 ++
 .../main/java/org/apache/hadoop/ozone/OmUtils.java |   1 +
 .../ozone/om/protocol/OzoneManagerProtocol.java    |  15 +
 ...OzoneManagerProtocolClientSideTranslatorPB.java |  43 ++-
 .../src/main/proto/OmClientProtocol.proto          |  15 +
 .../org/apache/hadoop/ozone/audit/OMAction.java    |   1 +
 .../hadoop/ozone/om/SnapshotChainManager.java      |   8 +
 .../om/ratis/utils/OzoneManagerRatisUtils.java     |   3 +
 .../request/snapshot/OMSnapshotRenameRequest.java  | 230 +++++++++++++
 .../snapshot/OMSnapshotRenameResponse.java         |  67 ++++
 .../ozone/om/request/OMRequestTestUtils.java       |  35 ++
 .../snapshot/TestOMSnapshotRenameRequest.java      | 359 +++++++++++++++++++++
 .../fs/ozone/BasicOzoneClientAdapterImpl.java      |  10 +
 .../hadoop/fs/ozone/BasicOzoneFileSystem.java      |   6 +
 .../ozone/BasicRootedOzoneClientAdapterImpl.java   |  10 +
 .../fs/ozone/BasicRootedOzoneFileSystem.java       |   6 +
 .../apache/hadoop/fs/ozone/OzoneClientAdapter.java |   2 +
 .../hadoop/ozone/client/ClientProtocolStub.java    |   7 +
 .../shell/snapshot/RenameSnapshotHandler.java      |  64 ++++
 .../ozone/shell/snapshot/SnapshotCommands.java     |   3 +-
 22 files changed, 931 insertions(+), 7 deletions(-)

diff --git 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java
 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java
index 481bdbbd5c..e96d0f84a4 100644
--- 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java
+++ 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/ObjectStore.java
@@ -565,6 +565,21 @@ public class ObjectStore {
     return proxy.createSnapshot(volumeName, bucketName, snapshotName);
   }
 
+  /**
+   * Rename snapshot.
+   *
+   * @param volumeName vol to be used
+   * @param bucketName bucket to be used
+   * @param snapshotOldName Old name of the snapshot
+   * @param snapshotNewName New name of the snapshot
+   *
+   * @throws IOException
+   */
+  public void renameSnapshot(String volumeName,
+      String bucketName, String snapshotOldName, String snapshotNewName) 
throws IOException {
+    proxy.renameSnapshot(volumeName, bucketName, snapshotOldName, 
snapshotNewName);
+  }
+
   /**
    * Delete snapshot.
    * @param volumeName vol to be used
diff --git 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
index 46e7e20b51..492cd31b67 100644
--- 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
+++ 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java
@@ -1092,6 +1092,19 @@ public interface ClientProtocol {
   String createSnapshot(String volumeName,
       String bucketName, String snapshotName) throws IOException;
 
+  /**
+   * Rename snapshot.
+   *
+   * @param volumeName Vol to be used
+   * @param bucketName Bucket to be used
+   * @param snapshotOldName Old name of the snapshot
+   * @param snapshotNewName New name of the snapshot
+   *
+   * @throws IOException
+   */
+  void renameSnapshot(String volumeName,
+      String bucketName, String snapshotOldName, String snapshotNewName) 
throws IOException;
+
   /**
    * Delete snapshot.
    * @param volumeName vol to be used
diff --git 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
index 94d6ae9769..3e71262040 100644
--- 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
+++ 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
@@ -964,6 +964,31 @@ public class RpcClient implements ClientProtocol {
         bucketName, snapshotName);
   }
 
+  /**
+   * Rename Snapshot.
+   *
+   * @param volumeName vol to be used
+   * @param bucketName bucket to be used
+   * @param snapshotOldName Old name of the snapshot
+   * @param snapshotNewName New name of the snapshot
+   *
+   * @throws IOException
+   */
+  @Override
+  public void renameSnapshot(String volumeName,
+      String bucketName, String snapshotOldName, String snapshotNewName) 
throws IOException {
+    Preconditions.checkArgument(StringUtils.isNotBlank(volumeName),
+                                "volume can't be null or empty.");
+    Preconditions.checkArgument(StringUtils.isNotBlank(bucketName),
+                                "bucket can't be null or empty.");
+    Preconditions.checkArgument(StringUtils.isNotBlank(snapshotOldName),
+                                "old snapshot name can't be null or empty.");
+    Preconditions.checkArgument(StringUtils.isNotBlank(snapshotNewName),
+                                "new snapshot name can't be null or empty.");
+
+    ozoneManagerClient.renameSnapshot(volumeName, bucketName, snapshotOldName, 
snapshotNewName);
+  }
+
   /**
    * Delete Snapshot.
    * @param volumeName vol to be used
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 f23a703bd0..d58d922b0e 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
@@ -319,6 +319,7 @@ public final class OmUtils {
     case SetRangerServiceVersion:
     case CreateSnapshot:
     case DeleteSnapshot:
+    case RenameSnapshot:
     case SnapshotMoveDeletedKeys:
     case SnapshotPurge:
     case RecoverLease:
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
index 9fc8e82f03..ab3f576d44 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
@@ -681,6 +681,21 @@ public interface OzoneManagerProtocol
         "this to be implemented");
   }
 
+  /**
+   * Rename snapshot.
+   * @param volumeName vol to be used
+   * @param bucketName bucket to be used
+   * @param snapshotOldName Old name of the snapshot
+   * @param snapshotNewName New name of the snapshot
+   *
+   * @throws IOException
+   */
+  default void renameSnapshot(String volumeName,
+      String bucketName, String snapshotOldName, String snapshotNewName) 
throws IOException {
+    throw new UnsupportedOperationException("OzoneManager does not require " +
+         "this to be implemented");
+  }
+
   /**
    * Delete snapshot.
    * @param volumeName vol to be used
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
index 5864102758..dd201a4262 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
@@ -85,6 +85,8 @@ import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Allocat
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.BucketArgs;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.BucketInfo;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CancelDelegationTokenResponseProto;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CancelPrepareRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CancelPrepareResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CheckVolumeAccessRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CommitKeyRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.CreateBucketRequest;
@@ -106,6 +108,8 @@ import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DeleteS
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DeleteTenantRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DeleteTenantResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.DeleteVolumeRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.EchoRPCRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.EchoRPCResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.FinalizeUpgradeProgressRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.FinalizeUpgradeProgressResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.FinalizeUpgradeRequest;
@@ -121,7 +125,6 @@ import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3Se
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3SecretResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3VolumeContextRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.GetS3VolumeContextResponse;
-import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SnapshotInfoRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoBucketRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoBucketResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoVolumeRequest;
@@ -129,14 +132,14 @@ import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.InfoVol
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.KeyArgs;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListBucketsRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListBucketsResponse;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListKeysLightResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListKeysRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListKeysResponse;
-import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListKeysLightResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListMultipartUploadsRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListMultipartUploadsResponse;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListStatusLightResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListStatusRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListStatusResponse;
-import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListStatusLightResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListTenantRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListTenantResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ListTrashRequest;
@@ -161,6 +164,11 @@ import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRespo
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneAclInfo;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneFileStatusProto;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneFileStatusProtoLight;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.PrepareRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.PrepareRequestArgs;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.PrepareResponse;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.PrepareStatusRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.PrepareStatusResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.PrintCompactionLogDagRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RangerBGSyncRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RangerBGSyncResponse;
@@ -172,12 +180,14 @@ import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Refetch
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RefetchSecretKeyResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RemoveAclRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RemoveAclResponse;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RenameKeyRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RenameKeysArgs;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RenameKeysMap;
-import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RenameKeyRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RenameKeysRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RenameSnapshotRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RenewDelegationTokenResponseProto;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RevokeS3SecretRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.S3Authentication;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.S3Secret;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SafeMode;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServiceListRequest;
@@ -185,12 +195,15 @@ import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Service
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetAclRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetAclResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetBucketPropertyRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetBucketPropertyResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetS3SecretRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetS3SecretResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetSafeModeRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetSafeModeResponse;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetTimesRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetVolumePropertyRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SetVolumePropertyResponse;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.SnapshotInfoRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantAssignAdminRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantAssignUserAccessIdRequest;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantAssignUserAccessIdResponse;
@@ -202,8 +215,6 @@ import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantR
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.TenantRevokeUserAccessIdRequest;
 import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type;
 import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.VolumeInfo;
-import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.EchoRPCRequest;
-import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.EchoRPCResponse;
 import org.apache.hadoop.ozone.protocolPB.OMPBHelper;
 import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
 import org.apache.hadoop.ozone.security.acl.OzoneObj;
@@ -1224,6 +1235,26 @@ public final class 
OzoneManagerProtocolClientSideTranslatorPB
     return snapshotInfo.getName();
   }
 
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void renameSnapshot(String volumeName, String bucketName,
+      String snapshotOldName, String snapshotNewName) throws IOException {
+    RenameSnapshotRequest.Builder requestBuilder =
+        RenameSnapshotRequest.newBuilder()
+            .setVolumeName(volumeName)
+            .setBucketName(bucketName)
+            .setSnapshotOldName(snapshotOldName)
+            .setSnapshotNewName(snapshotNewName);
+
+    final OMRequest omRequest = createOMRequest(Type.RenameSnapshot)
+        .setRenameSnapshotRequest(requestBuilder)
+        .build();
+    final OMResponse omResponse = submitRequest(omRequest);
+    handleError(omResponse);
+  }
+
   /**
    * {@inheritDoc}
    */
diff --git 
a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto 
b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
index 5c737fdad9..b0d26020c8 100644
--- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
+++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
@@ -146,6 +146,7 @@ enum Type {
   SetSnapshotProperty = 128;
   ListStatusLight = 129;
   GetSnapshotInfo = 130;
+  RenameSnapshot = 131;
 }
 
 enum SafeMode {
@@ -281,6 +282,7 @@ message OMRequest {
   optional MultipartUploadsExpiredAbortRequest 
multipartUploadsExpiredAbortRequest = 126;
   optional SetSnapshotPropertyRequest       SetSnapshotPropertyRequest     = 
127;
   optional SnapshotInfoRequest              SnapshotInfoRequest            = 
128;
+  optional RenameSnapshotRequest            RenameSnapshotRequest          = 
129;
 }
 
 message OMResponse {
@@ -403,6 +405,7 @@ message OMResponse {
   optional ListStatusLightResponse           listStatusLightResponse       = 
129;
   optional SnapshotInfoResponse              SnapshotInfoResponse          = 
130;
   optional OMLockDetailsProto                omLockDetails                 = 
131;
+  optional RenameSnapshotResponse            RenameSnapshotResponse        = 
132;
 }
 
 enum Status {
@@ -1830,6 +1833,14 @@ message CreateSnapshotRequest {
   optional uint64 creationTime = 5;
 }
 
+message RenameSnapshotRequest {
+  optional string volumeName = 1;
+  optional string bucketName = 2;
+  optional string snapshotOldName = 3;
+  optional string snapshotNewName = 4;
+  optional uint64 renameTime = 5;
+}
+
 message ListSnapshotRequest {
   optional string volumeName = 1;
   optional string bucketName = 2;
@@ -1992,6 +2003,10 @@ message DeleteSnapshotResponse {
 
 }
 
+message RenameSnapshotResponse {
+  optional SnapshotInfo snapshotInfo = 1;
+}
+
 message SnapshotInfoResponse {
   optional SnapshotInfo snapshotInfo = 1;
 }
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java
index 4e9039252f..4804b317bc 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java
@@ -98,6 +98,7 @@ public enum OMAction implements AuditAction {
   CREATE_SNAPSHOT,
   LIST_SNAPSHOT,
   DELETE_SNAPSHOT,
+  RENAME_SNAPSHOT,
   SNAPSHOT_MOVE_DELETED_KEYS,
   SNAPSHOT_INFO,
   SET_TIMES,
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/SnapshotChainManager.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/SnapshotChainManager.java
index 18deca1a4f..60353590e7 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/SnapshotChainManager.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/SnapshotChainManager.java
@@ -348,6 +348,14 @@ public class SnapshotChainManager {
         snapshotInfo.getTableKey());
   }
 
+  /**
+   * Update snapshot chain when snapshot changes (e.g. renamed).
+   */
+  public synchronized void updateSnapshot(SnapshotInfo snapshotInfo) {
+    snapshotIdToTableKey.computeIfPresent(snapshotInfo.getSnapshotId(),
+        (snapshotId, dbTableKey) -> snapshotInfo.getTableKey());
+  }
+
   /**
    * Delete snapshot from snapshot chain.
    */
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java
index 3ab65346e7..b055a1f92f 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java
@@ -79,6 +79,7 @@ import 
org.apache.hadoop.ozone.om.request.snapshot.OMSnapshotCreateRequest;
 import org.apache.hadoop.ozone.om.request.snapshot.OMSnapshotDeleteRequest;
 import 
org.apache.hadoop.ozone.om.request.snapshot.OMSnapshotMoveDeletedKeysRequest;
 import org.apache.hadoop.ozone.om.request.snapshot.OMSnapshotPurgeRequest;
+import org.apache.hadoop.ozone.om.request.snapshot.OMSnapshotRenameRequest;
 import 
org.apache.hadoop.ozone.om.request.snapshot.OMSnapshotSetPropertyRequest;
 import org.apache.hadoop.ozone.om.request.upgrade.OMCancelPrepareRequest;
 import org.apache.hadoop.ozone.om.request.upgrade.OMFinalizeUpgradeRequest;
@@ -224,6 +225,8 @@ public final class OzoneManagerRatisUtils {
       return new OMSnapshotCreateRequest(omRequest);
     case DeleteSnapshot:
       return new OMSnapshotDeleteRequest(omRequest);
+    case RenameSnapshot:
+      return new OMSnapshotRenameRequest(omRequest);
     case SnapshotMoveDeletedKeys:
       return new OMSnapshotMoveDeletedKeysRequest(omRequest);
     case SnapshotPurge:
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotRenameRequest.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotRenameRequest.java
new file mode 100644
index 0000000000..9f1875f65d
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/snapshot/OMSnapshotRenameRequest.java
@@ -0,0 +1,230 @@
+/*
+ * 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.snapshot;
+
+import static 
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.FILE_ALREADY_EXISTS;
+import static 
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.FILE_NOT_FOUND;
+import static 
org.apache.hadoop.ozone.om.lock.OzoneManagerLock.Resource.BUCKET_LOCK;
+import static 
org.apache.hadoop.ozone.om.lock.OzoneManagerLock.Resource.SNAPSHOT_LOCK;
+import static 
org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature.FILESYSTEM_SNAPSHOT;
+
+import java.io.IOException;
+import java.nio.file.InvalidPathException;
+import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
+import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
+import org.apache.hadoop.ozone.OmUtils;
+import org.apache.hadoop.ozone.audit.AuditLogger;
+import org.apache.hadoop.ozone.audit.OMAction;
+import org.apache.hadoop.ozone.om.OmMetadataManagerImpl;
+import org.apache.hadoop.ozone.om.OzoneManager;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
+import org.apache.hadoop.ozone.om.helpers.SnapshotInfo;
+import org.apache.hadoop.ozone.om.request.OMClientRequest;
+import org.apache.hadoop.ozone.om.request.util.OmResponseUtil;
+import org.apache.hadoop.ozone.om.response.OMClientResponse;
+import org.apache.hadoop.ozone.om.response.snapshot.OMSnapshotRenameResponse;
+import org.apache.hadoop.ozone.om.snapshot.RequireSnapshotFeatureState;
+import org.apache.hadoop.ozone.om.upgrade.DisallowedUntilLayoutVersion;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RenameSnapshotRequest;
+import 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.UserInfo;
+import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer;
+import org.apache.hadoop.ozone.security.acl.OzoneObj;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.util.Time;
+import org.apache.ratis.server.protocol.TermIndex;
+
+/**
+ * Changes snapshot name.
+ */
+public class OMSnapshotRenameRequest extends OMClientRequest {
+
+  public OMSnapshotRenameRequest(OMRequest omRequest) {
+    super(omRequest);
+  }
+
+  @Override
+  @DisallowedUntilLayoutVersion(FILESYSTEM_SNAPSHOT)
+  @RequireSnapshotFeatureState(true)
+  public OMRequest preExecute(OzoneManager ozoneManager) throws IOException {
+    final OMRequest omRequest = super.preExecute(ozoneManager);
+
+    final RenameSnapshotRequest renameSnapshotRequest =
+        omRequest.getRenameSnapshotRequest();
+
+    final String snapshotNewName = renameSnapshotRequest.getSnapshotNewName();
+
+    OmUtils.validateSnapshotName(snapshotNewName);
+
+    String volumeName = renameSnapshotRequest.getVolumeName();
+    String bucketName = renameSnapshotRequest.getBucketName();
+
+    // Permission check
+    UserGroupInformation ugi = createUGIForApi();
+    String bucketOwner = ozoneManager.getBucketOwner(volumeName, bucketName,
+                                                     
IAccessAuthorizer.ACLType.READ, OzoneObj.ResourceType.BUCKET);
+    if (!ozoneManager.isAdmin(ugi) &&
+        !ozoneManager.isOwner(ugi, bucketOwner)) {
+      throw new OMException(
+          "Only bucket owners and Ozone admins can rename snapshots",
+          OMException.ResultCodes.PERMISSION_DENIED);
+    }
+
+    // Set rename time here so OM leader and follower would have the
+    // exact same timestamp.
+    OMRequest.Builder omRequestBuilder = omRequest.toBuilder()
+        .setRenameSnapshotRequest(
+            RenameSnapshotRequest.newBuilder()
+                .setVolumeName(volumeName)
+                .setBucketName(bucketName)
+                .setSnapshotNewName(snapshotNewName)
+                .setSnapshotOldName(renameSnapshotRequest.getSnapshotOldName())
+                .setRenameTime(Time.now()));
+
+    return omRequestBuilder.build();
+  }
+
+
+  @Override
+  public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager,
+                                                 TermIndex termIndex) {
+    boolean acquiredBucketLock = false;
+    boolean acquiredSnapshotOldLock = false;
+    boolean acquiredSnapshotNewLock = false;
+    Exception exception = null;
+    OmMetadataManagerImpl omMetadataManager = (OmMetadataManagerImpl)
+        ozoneManager.getMetadataManager();
+
+    OMResponse.Builder omResponse = OmResponseUtil.getOMResponseBuilder(
+        getOmRequest());
+    OMClientResponse omClientResponse = null;
+    AuditLogger auditLogger = ozoneManager.getAuditLogger();
+
+    UserInfo userInfo = getOmRequest().getUserInfo();
+
+    final RenameSnapshotRequest request =
+        getOmRequest().getRenameSnapshotRequest();
+
+    final String volumeName = request.getVolumeName();
+    final String bucketName = request.getBucketName();
+    final String snapshotNewName = request.getSnapshotNewName();
+    final String snapshotOldName = request.getSnapshotOldName();
+
+    SnapshotInfo snapshotOldInfo = null;
+
+    try {
+      // Acquire bucket lock
+      mergeOmLockDetails(
+          omMetadataManager.getLock().acquireWriteLock(BUCKET_LOCK,
+                                                       volumeName, 
bucketName));
+      acquiredBucketLock = getOmLockDetails().isLockAcquired();
+
+      
mergeOmLockDetails(omMetadataManager.getLock().acquireWriteLock(SNAPSHOT_LOCK,
+                                                       volumeName, bucketName, 
snapshotOldName));
+      acquiredSnapshotOldLock = getOmLockDetails().isLockAcquired();
+
+      
mergeOmLockDetails(omMetadataManager.getLock().acquireWriteLock(SNAPSHOT_LOCK,
+                                                       volumeName, bucketName, 
snapshotNewName));
+      acquiredSnapshotNewLock = getOmLockDetails().isLockAcquired();
+
+      // Retrieve SnapshotInfo from the table
+      String snapshotNewTableKey = SnapshotInfo.getTableKey(volumeName, 
bucketName, snapshotNewName);
+
+      if 
(omMetadataManager.getSnapshotInfoTable().isExist(snapshotNewTableKey)) {
+        throw new OMException("Snapshot with name " + snapshotNewName + 
"already exist",
+            FILE_ALREADY_EXISTS);
+      }
+
+      // Retrieve SnapshotInfo from the table
+      String snapshotOldTableKey = SnapshotInfo.getTableKey(volumeName, 
bucketName,
+                                                 snapshotOldName);
+      snapshotOldInfo =
+          omMetadataManager.getSnapshotInfoTable().get(snapshotOldTableKey);
+
+      if (snapshotOldInfo == null) {
+        // Snapshot does not exist
+        throw new OMException("Snapshot with name " + snapshotOldName + "does 
not exist",
+            FILE_NOT_FOUND);
+      }
+
+      switch (snapshotOldInfo.getSnapshotStatus()) {
+      case SNAPSHOT_DELETED:
+        throw new OMException("Snapshot is already deleted. "
+            + "Pending reclamation.", FILE_NOT_FOUND);
+      case SNAPSHOT_ACTIVE:
+        break;
+      default:
+          // Unknown snapshot non-active state
+        throw new OMException("Snapshot exists but no longer in active state",
+            FILE_NOT_FOUND);
+      }
+
+      snapshotOldInfo.setName(snapshotNewName);
+
+      omMetadataManager.getSnapshotInfoTable().addCacheEntry(
+          new CacheKey<>(snapshotOldTableKey),
+          CacheValue.get(termIndex.getIndex()));
+
+      omMetadataManager.getSnapshotInfoTable().addCacheEntry(
+          new CacheKey<>(snapshotNewTableKey),
+          CacheValue.get(termIndex.getIndex(), snapshotOldInfo));
+
+      
omMetadataManager.getSnapshotChainManager().updateSnapshot(snapshotOldInfo);
+
+      omResponse.setRenameSnapshotResponse(
+          OzoneManagerProtocolProtos.RenameSnapshotResponse.newBuilder()
+              .setSnapshotInfo(snapshotOldInfo.getProtobuf()));
+      omClientResponse = new OMSnapshotRenameResponse(
+          omResponse.build(), snapshotOldTableKey, snapshotNewTableKey, 
snapshotOldInfo);
+
+    } catch (IOException | InvalidPathException ex) {
+      exception = ex;
+      omClientResponse = new OMSnapshotRenameResponse(
+          createErrorOMResponse(omResponse, exception));
+    } finally {
+      if (acquiredSnapshotNewLock) {
+        
mergeOmLockDetails(omMetadataManager.getLock().releaseWriteLock(SNAPSHOT_LOCK, 
volumeName,
+                                                     bucketName, 
snapshotNewName));
+      }
+      if (acquiredSnapshotOldLock) {
+        
mergeOmLockDetails(omMetadataManager.getLock().releaseWriteLock(SNAPSHOT_LOCK, 
volumeName,
+                                                     bucketName, 
snapshotOldName));
+      }
+      if (acquiredBucketLock) {
+        
mergeOmLockDetails(omMetadataManager.getLock().releaseWriteLock(BUCKET_LOCK, 
volumeName,
+                                                     bucketName));
+      }
+      if (omClientResponse != null) {
+        omClientResponse.setOmLockDetails(getOmLockDetails());
+      }
+    }
+
+    if (snapshotOldInfo == null) {
+      // Dummy SnapshotInfo for logging and audit logging when erred
+      snapshotOldInfo = SnapshotInfo.newInstance(volumeName, bucketName,
+                                              snapshotOldName, null, 
Time.now());
+    }
+
+    // Perform audit logging outside the lock
+    auditLog(auditLogger, buildAuditMessage(OMAction.RENAME_SNAPSHOT,
+                                            snapshotOldInfo.toAuditMap(), 
exception, userInfo));
+    return omClientResponse;
+  }
+}
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/snapshot/OMSnapshotRenameResponse.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/snapshot/OMSnapshotRenameResponse.java
new file mode 100644
index 0000000000..05bb16a8f5
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/snapshot/OMSnapshotRenameResponse.java
@@ -0,0 +1,67 @@
+/*
+ * 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.response.snapshot;
+
+import static 
org.apache.hadoop.ozone.om.OmMetadataManagerImpl.SNAPSHOT_INFO_TABLE;
+
+import jakarta.annotation.Nonnull;
+import java.io.IOException;
+import org.apache.hadoop.hdds.utils.db.BatchOperation;
+import org.apache.hadoop.ozone.om.OMMetadataManager;
+import org.apache.hadoop.ozone.om.helpers.SnapshotInfo;
+import org.apache.hadoop.ozone.om.response.CleanupTableInfo;
+import org.apache.hadoop.ozone.om.response.OMClientResponse;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+
+/**
+ * Response for OMSnapshotRenameRequest.
+ */
+@CleanupTableInfo(cleanupTables = {SNAPSHOT_INFO_TABLE})
+public class OMSnapshotRenameResponse extends OMClientResponse {
+
+  private String snapshotOldName;
+  private String snapshotNewName;
+  private SnapshotInfo renamedInfo;
+
+  public OMSnapshotRenameResponse(OzoneManagerProtocolProtos.OMResponse 
omResponse,
+                                  String snapshotOldName, String 
snapshotNewName,
+                                  @Nonnull SnapshotInfo renamedInfo) {
+    super(omResponse);
+    this.snapshotOldName = snapshotOldName;
+    this.snapshotNewName = snapshotNewName;
+    this.renamedInfo = renamedInfo;
+  }
+
+  /**
+   * For when the request is not successful.
+   * For a successful request, the other constructor should be used.
+   */
+  public OMSnapshotRenameResponse(@Nonnull 
OzoneManagerProtocolProtos.OMResponse omResponse) {
+    super(omResponse);
+    checkStatusNotOK();
+  }
+
+  @Override
+  protected void addToDBBatch(OMMetadataManager omMetadataManager, 
BatchOperation batchOperation)
+      throws IOException {
+    omMetadataManager.getSnapshotInfoTable()
+        .putWithBatch(batchOperation, snapshotNewName, renamedInfo);
+    omMetadataManager.getSnapshotInfoTable()
+        .deleteWithBatch(batchOperation, snapshotOldName);
+  }
+}
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/OMRequestTestUtils.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/OMRequestTestUtils.java
index 1bd642fce7..e85675e9b0 100644
--- 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/OMRequestTestUtils.java
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/OMRequestTestUtils.java
@@ -1298,6 +1298,41 @@ public final class OMRequestTestUtils {
         .build();
   }
 
+  /**
+   * Create OMRequest for Rename Snapshot.
+   *
+   * @param volumeName vol to be used
+   * @param bucketName bucket to be used
+   * @param snapshotOldName Old name of the snapshot
+   * @param snapshotNewName New name of the snapshot
+   */
+  public static OMRequest renameSnapshotRequest(String volumeName,
+                                                String bucketName,
+                                                String snapshotOldName,
+                                                String snapshotNewName) {
+    OzoneManagerProtocolProtos.RenameSnapshotRequest renameSnapshotRequest =
+        OzoneManagerProtocolProtos.RenameSnapshotRequest.newBuilder()
+            .setVolumeName(volumeName)
+            .setBucketName(bucketName)
+            .setSnapshotOldName(snapshotOldName)
+            .setSnapshotNewName(snapshotNewName)
+            .build();
+
+    OzoneManagerProtocolProtos.UserInfo userInfo =
+        OzoneManagerProtocolProtos.UserInfo.newBuilder()
+            .setUserName("user")
+            .setHostName("host")
+            .setRemoteAddress("remote-address")
+            .build();
+
+    return OMRequest.newBuilder()
+        .setRenameSnapshotRequest(renameSnapshotRequest)
+        .setCmdType(Type.RenameSnapshot)
+        .setClientId(UUID.randomUUID().toString())
+        .setUserInfo(userInfo)
+        .build();
+  }
+
   /**
    * Create OMRequest for Delete Snapshot.
    * @param volumeName vol to be used
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/snapshot/TestOMSnapshotRenameRequest.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/snapshot/TestOMSnapshotRenameRequest.java
new file mode 100644
index 0000000000..14af3e28b8
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/snapshot/TestOMSnapshotRenameRequest.java
@@ -0,0 +1,359 @@
+/*
+ * 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.snapshot;
+
+import org.apache.hadoop.hdds.client.RatisReplicationConfig;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.utils.db.BatchOperation;
+import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
+import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
+import org.apache.hadoop.ozone.OzoneConfigKeys;
+import org.apache.hadoop.ozone.audit.AuditLogger;
+import org.apache.hadoop.ozone.audit.AuditMessage;
+import org.apache.hadoop.ozone.om.OMConfigKeys;
+import org.apache.hadoop.ozone.om.OMMetrics;
+import org.apache.hadoop.ozone.om.OmMetadataManagerImpl;
+import org.apache.hadoop.ozone.om.OmSnapshotManager;
+import org.apache.hadoop.ozone.om.OzoneManager;
+import org.apache.hadoop.ozone.om.exceptions.OMException;
+import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
+import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
+import org.apache.hadoop.ozone.om.helpers.SnapshotInfo;
+import org.apache.hadoop.ozone.om.request.OMRequestTestUtils;
+import org.apache.hadoop.ozone.om.response.OMClientResponse;
+import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager;
+import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
+import org.apache.hadoop.util.Time;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.io.File;
+import java.util.UUID;
+
+import static 
org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor.THREE;
+import static 
org.apache.hadoop.ozone.om.helpers.SnapshotInfo.SnapshotStatus.SNAPSHOT_ACTIVE;
+import static org.apache.hadoop.ozone.om.helpers.SnapshotInfo.getFromProtobuf;
+import static org.apache.hadoop.ozone.om.helpers.SnapshotInfo.getTableKey;
+import static 
org.apache.hadoop.ozone.om.request.OMRequestTestUtils.createSnapshotRequest;
+import static 
org.apache.hadoop.ozone.om.request.OMRequestTestUtils.renameSnapshotRequest;
+import static 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status.OK;
+import static 
org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type.RenameSnapshot;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.framework;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests OMSnapshotRenameRequest class, which handles RenameSnapshot request.
+ */
+public class TestOMSnapshotRenameRequest {
+
+  @TempDir
+  private File anotherTempDir;
+
+  private OzoneManager ozoneManager;
+  private OMMetrics omMetrics;
+  private OmMetadataManagerImpl omMetadataManager;
+  private BatchOperation batchOperation;
+
+  private String volumeName;
+  private String bucketName;
+  private String snapshotName1;
+  private String snapshotName2;
+
+  @BeforeEach
+  public void setup() throws Exception {
+    ozoneManager = mock(OzoneManager.class);
+    omMetrics = OMMetrics.create();
+    OzoneConfiguration ozoneConfiguration = new OzoneConfiguration();
+    ozoneConfiguration.set(OMConfigKeys.OZONE_OM_DB_DIRS,
+        anotherTempDir.getAbsolutePath());
+    ozoneConfiguration.set(OzoneConfigKeys.OZONE_METADATA_DIRS,
+        anotherTempDir.getAbsolutePath());
+    omMetadataManager = new OmMetadataManagerImpl(ozoneConfiguration,
+        ozoneManager);
+    when(ozoneManager.getMetrics()).thenReturn(omMetrics);
+    when(ozoneManager.getMetadataManager()).thenReturn(omMetadataManager);
+    when(ozoneManager.isRatisEnabled()).thenReturn(true);
+    when(ozoneManager.isFilesystemSnapshotEnabled()).thenReturn(true);
+    when(ozoneManager.isAdmin(any())).thenReturn(false);
+    when(ozoneManager.isOwner(any(), any())).thenReturn(false);
+    when(ozoneManager.getBucketOwner(any(), any(),
+        any(), any())).thenReturn("dummyBucketOwner");
+    OMLayoutVersionManager lvm = mock(OMLayoutVersionManager.class);
+    when(lvm.isAllowed(anyString())).thenReturn(true);
+    when(ozoneManager.getVersionManager()).thenReturn(lvm);
+    AuditLogger auditLogger = mock(AuditLogger.class);
+    when(ozoneManager.getAuditLogger()).thenReturn(auditLogger);
+    doNothing().when(auditLogger).logWrite(any(AuditMessage.class));
+    batchOperation = omMetadataManager.getStore().initBatchOperation();
+    when(ozoneManager.getConfiguration()).thenReturn(ozoneConfiguration);
+    OmSnapshotManager omSnapshotManager = new OmSnapshotManager(ozoneManager);
+    when(ozoneManager.getOmSnapshotManager()).thenReturn(omSnapshotManager);
+
+    volumeName = UUID.randomUUID().toString();
+    bucketName = UUID.randomUUID().toString();
+    snapshotName1 = UUID.randomUUID().toString();
+    snapshotName2 = UUID.randomUUID().toString();
+    OMRequestTestUtils.addVolumeAndBucketToDB(volumeName, bucketName,
+        omMetadataManager);
+  }
+
+  @AfterEach
+  public void stop() {
+    omMetrics.unRegister();
+    framework().clearInlineMocks();
+    if (batchOperation != null) {
+      batchOperation.close();
+    }
+  }
+
+  @ValueSource(strings = {
+      // '-' is allowed.
+      "9cdf0e8a-6946-41ad-a2d1-9eb724fab126",
+      // 3 chars name is allowed.
+      "sn1",
+      // less than or equal to 63 chars are allowed.
+      "snap75795657617173401188448010125899089001363595171500499231286"
+  })
+  @ParameterizedTest
+  public void testPreExecute(String toSnapshotName) throws Exception {
+    when(ozoneManager.isOwner(any(), any())).thenReturn(true);
+
+    String currentSnapshotName = "current";
+    OzoneManagerProtocolProtos.OMRequest omRequest = 
renameSnapshotRequest(volumeName,
+        bucketName, currentSnapshotName, toSnapshotName);
+    doPreExecute(omRequest);
+  }
+
+  @ValueSource(strings = {
+      // ? is not allowed in snapshot name.
+      "a?b",
+      // only numeric name not allowed.
+      "1234",
+      // less than 3 chars are not allowed.
+      "s1",
+      // more than or equal to 64 chars are not allowed.
+      "snap156808943643007724443266605711479126926050896107709081166294",
+      // Underscore is not allowed.
+      "snap_1",
+      // CamelCase is not allowed.
+      "NewSnapshot"
+  })
+  @ParameterizedTest
+  public void testPreExecuteFailure(String toSnapshotName) {
+    when(ozoneManager.isOwner(any(), any())).thenReturn(true);
+    String currentSnapshotName = "current";
+    OzoneManagerProtocolProtos.OMRequest omRequest = 
renameSnapshotRequest(volumeName,
+        bucketName, currentSnapshotName, toSnapshotName);
+    OMException omException =
+        assertThrows(OMException.class, () -> doPreExecute(omRequest));
+    assertEquals("Invalid snapshot name: " + toSnapshotName,
+        omException.getMessage());
+  }
+
+  @Test
+  public void testPreExecuteBadOwner() {
+    // Owner is not set for the request.
+    OzoneManagerProtocolProtos.OMRequest omRequest = 
renameSnapshotRequest(volumeName,
+        bucketName, snapshotName1, snapshotName2);
+
+    OMException omException = assertThrows(OMException.class,
+        () -> doPreExecute(omRequest));
+    assertEquals("Only bucket owners and Ozone admins can rename snapshots",
+        omException.getMessage());
+  }
+
+  @Test
+  public void testValidateAndUpdateCache() throws Exception {
+    when(ozoneManager.isAdmin(any())).thenReturn(true);
+    OzoneManagerProtocolProtos.OMRequest omRequest = 
renameSnapshotRequest(volumeName,
+        bucketName, snapshotName1, snapshotName2);
+    OMSnapshotRenameRequest omSnapshotRenameRequest = doPreExecute(omRequest);
+    String key = getTableKey(volumeName, bucketName, snapshotName1);
+    String bucketKey = omMetadataManager.getBucketKey(volumeName, bucketName);
+
+    // Add a 1000-byte key to the bucket
+    OmKeyInfo key1 = addKey("key-testValidateAndUpdateCache", 12345L);
+    addKeyToTable(key1);
+
+    OmBucketInfo omBucketInfo = omMetadataManager.getBucketTable().get(
+        bucketKey);
+    long bucketDataSize = key1.getDataSize();
+    long bucketUsedBytes = omBucketInfo.getUsedBytes();
+    assertEquals(key1.getReplicatedSize(), bucketUsedBytes);
+
+    // Value in cache should be null as of now.
+    assertNull(omMetadataManager.getSnapshotInfoTable().get(key));
+
+    // Add key to cache.
+    SnapshotInfo snapshotInfo = SnapshotInfo.newInstance(volumeName, 
bucketName,
+        snapshotName1, UUID.randomUUID(), Time.now());
+    snapshotInfo.setReferencedSize(1000L);
+    snapshotInfo.setReferencedReplicatedSize(3 * 1000L);
+    assertEquals(SNAPSHOT_ACTIVE, snapshotInfo.getSnapshotStatus());
+    omMetadataManager.getSnapshotInfoTable().addCacheEntry(
+        new CacheKey<>(key),
+        CacheValue.get(1L, snapshotInfo));
+
+    // Run validateAndUpdateCache.
+    OMClientResponse omClientResponse =
+        omSnapshotRenameRequest.validateAndUpdateCache(ozoneManager, 2L);
+
+    assertNotNull(omClientResponse.getOMResponse());
+
+    OzoneManagerProtocolProtos.OMResponse omResponse = 
omClientResponse.getOMResponse();
+    assertNotNull(omResponse.getRenameSnapshotResponse());
+    assertEquals(RenameSnapshot, omResponse.getCmdType());
+    assertEquals(OK, omResponse.getStatus());
+
+    // verify table data with response data.
+    OzoneManagerProtocolProtos.SnapshotInfo snapshotInfoProto =
+        omClientResponse
+            .getOMResponse()
+            .getRenameSnapshotResponse()
+            .getSnapshotInfo();
+
+    assertEquals(bucketDataSize, snapshotInfoProto.getReferencedSize());
+    assertEquals(bucketUsedBytes,
+        snapshotInfoProto.getReferencedReplicatedSize());
+
+    SnapshotInfo snapshotInfoOldProto = getFromProtobuf(snapshotInfoProto);
+
+    String key2 = getTableKey(volumeName, bucketName, snapshotName2);
+
+    // Get value from cache
+    SnapshotInfo snapshotInfoNewInCache =
+        omMetadataManager.getSnapshotInfoTable().get(key2);
+    assertNotNull(snapshotInfoNewInCache);
+    assertEquals(snapshotInfoOldProto, snapshotInfoNewInCache);
+    assertEquals(snapshotInfo.getSnapshotId(), 
snapshotInfoNewInCache.getSnapshotId());
+
+    SnapshotInfo snapshotInfoOldInCache =
+        omMetadataManager.getSnapshotInfoTable().get(key);
+    assertNull(snapshotInfoOldInCache);
+  }
+
+  @Test
+  public void testEntryExists() throws Exception {
+    when(ozoneManager.isAdmin(any())).thenReturn(true);
+
+    String keyNameOld = getTableKey(volumeName, bucketName, snapshotName1);
+    String keyNameNew = getTableKey(volumeName, bucketName, snapshotName2);
+
+    assertNull(omMetadataManager.getSnapshotInfoTable().get(keyNameOld));
+    assertNull(omMetadataManager.getSnapshotInfoTable().get(keyNameNew));
+
+    // First make sure we have two snapshots.
+    OzoneManagerProtocolProtos.OMRequest createOmRequest =
+        createSnapshotRequest(volumeName, bucketName, snapshotName1);
+    OMSnapshotCreateRequest omSnapshotCreateRequest =
+        TestOMSnapshotCreateRequest.doPreExecute(createOmRequest, 
ozoneManager);
+    omSnapshotCreateRequest.validateAndUpdateCache(ozoneManager, 1);
+
+    createOmRequest =
+        createSnapshotRequest(volumeName, bucketName, snapshotName2);
+    omSnapshotCreateRequest =
+        TestOMSnapshotCreateRequest.doPreExecute(createOmRequest, 
ozoneManager);
+    omSnapshotCreateRequest.validateAndUpdateCache(ozoneManager, 2);
+
+    assertNotNull(omMetadataManager.getSnapshotInfoTable().get(keyNameOld));
+    assertNotNull(omMetadataManager.getSnapshotInfoTable().get(keyNameNew));
+
+    // Now try renaming and get an error.
+    OzoneManagerProtocolProtos.OMRequest omRequest =
+        renameSnapshotRequest(volumeName, bucketName, snapshotName1, 
snapshotName2);
+    OMSnapshotRenameRequest omSnapshotRenameRequest = doPreExecute(omRequest);
+
+    OMClientResponse omClientResponse =
+        omSnapshotRenameRequest.validateAndUpdateCache(ozoneManager, 3);
+
+    assertNotNull(omMetadataManager.getSnapshotInfoTable().get(keyNameOld));
+    assertNotNull(omMetadataManager.getSnapshotInfoTable().get(keyNameNew));
+
+    OzoneManagerProtocolProtos.OMResponse omResponse = 
omClientResponse.getOMResponse();
+    assertNotNull(omResponse.getRenameSnapshotResponse());
+    assertEquals(OzoneManagerProtocolProtos.Status.FILE_ALREADY_EXISTS,
+        omResponse.getStatus());
+  }
+
+  @Test
+  public void testEntryNotFound() throws Exception {
+    when(ozoneManager.isAdmin(any())).thenReturn(true);
+
+    String keyNameOld = getTableKey(volumeName, bucketName, snapshotName1);
+    String keyNameNew = getTableKey(volumeName, bucketName, snapshotName2);
+
+    assertNull(omMetadataManager.getSnapshotInfoTable().get(keyNameOld));
+    assertNull(omMetadataManager.getSnapshotInfoTable().get(keyNameNew));
+
+    // Now try renaming and get an error.
+    OzoneManagerProtocolProtos.OMRequest omRequest =
+        renameSnapshotRequest(volumeName, bucketName, snapshotName1, 
snapshotName2);
+    OMSnapshotRenameRequest omSnapshotRenameRequest = doPreExecute(omRequest);
+
+    OMClientResponse omClientResponse =
+        omSnapshotRenameRequest.validateAndUpdateCache(ozoneManager, 3);
+
+    assertNull(omMetadataManager.getSnapshotInfoTable().get(keyNameOld));
+    assertNull(omMetadataManager.getSnapshotInfoTable().get(keyNameNew));
+
+    OzoneManagerProtocolProtos.OMResponse omResponse = 
omClientResponse.getOMResponse();
+    assertNotNull(omResponse.getRenameSnapshotResponse());
+    assertEquals(OzoneManagerProtocolProtos.Status.FILE_NOT_FOUND,
+        omResponse.getStatus());
+  }
+
+  private OMSnapshotRenameRequest doPreExecute(
+      OzoneManagerProtocolProtos.OMRequest originalRequest) throws Exception {
+    return doPreExecute(originalRequest, ozoneManager);
+  }
+
+  public static OMSnapshotRenameRequest doPreExecute(
+      OzoneManagerProtocolProtos.OMRequest originalRequest, OzoneManager 
ozoneManager) throws Exception {
+    OMSnapshotRenameRequest omSnapshotRenameRequest =
+        new OMSnapshotRenameRequest(originalRequest);
+
+    OzoneManagerProtocolProtos.OMRequest modifiedRequest =
+        omSnapshotRenameRequest.preExecute(ozoneManager);
+    return new OMSnapshotRenameRequest(modifiedRequest);
+  }
+
+  private OmKeyInfo addKey(String keyName, long objectId) {
+    return OMRequestTestUtils.createOmKeyInfo(volumeName, bucketName, keyName,
+            RatisReplicationConfig.getInstance(THREE)).setObjectID(objectId)
+        .build();
+  }
+
+  protected String addKeyToTable(OmKeyInfo keyInfo) throws Exception {
+    OMRequestTestUtils.addKeyToTable(false, true, keyInfo, 0, 0L,
+        omMetadataManager);
+    return omMetadataManager.getOzoneKey(keyInfo.getVolumeName(),
+        keyInfo.getBucketName(), keyInfo.getKeyName());
+  }
+
+}
diff --git 
a/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicOzoneClientAdapterImpl.java
 
b/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicOzoneClientAdapterImpl.java
index e6892d9784..1614f81087 100644
--- 
a/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicOzoneClientAdapterImpl.java
+++ 
b/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicOzoneClientAdapterImpl.java
@@ -604,6 +604,16 @@ public class BasicOzoneClientAdapterImpl implements 
OzoneClientAdapter {
         snapshotName);
   }
 
+  @Override
+  public void renameSnapshot(String pathStr, String snapshotOldName, String 
snapshotNewName)
+      throws IOException {
+    OFSPath ofsPath = new OFSPath(pathStr, config);
+    objectStore.renameSnapshot(ofsPath.getVolumeName(),
+        ofsPath.getBucketName(),
+        snapshotOldName,
+        snapshotNewName);
+  }
+
   @Override
   public void deleteSnapshot(String pathStr, String snapshotName)
       throws IOException {
diff --git 
a/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicOzoneFileSystem.java
 
b/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicOzoneFileSystem.java
index dbe3b517e5..cd09cf1d5a 100644
--- 
a/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicOzoneFileSystem.java
+++ 
b/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicOzoneFileSystem.java
@@ -954,6 +954,12 @@ public class BasicOzoneFileSystem extends FileSystem {
         OM_SNAPSHOT_INDICATOR + OZONE_URI_DELIMITER + snapshot);
   }
 
+  @Override
+  public void renameSnapshot(Path path, String snapshotOldName, String 
snapshotNewName)
+      throws IOException {
+    getAdapter().renameSnapshot(pathToKey(path), snapshotOldName, 
snapshotNewName);
+  }
+
   @Override
   public void deleteSnapshot(Path path, String snapshotName)
       throws IOException {
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 8804278612..7a80878549 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
@@ -1254,6 +1254,16 @@ public class BasicRootedOzoneClientAdapterImpl
             snapshotName);
   }
 
+  @Override
+  public void renameSnapshot(String pathStr, String snapshotOldName, String 
snapshotNewName)
+      throws IOException {
+    OFSPath ofsPath = new OFSPath(pathStr, config);
+    proxy.renameSnapshot(ofsPath.getVolumeName(),
+        ofsPath.getBucketName(),
+        snapshotOldName,
+        snapshotNewName);
+  }
+
   @Override
   public void deleteSnapshot(String pathStr, String snapshotName)
       throws IOException {
diff --git 
a/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicRootedOzoneFileSystem.java
 
b/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicRootedOzoneFileSystem.java
index b13d726371..1fcb1554b6 100644
--- 
a/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicRootedOzoneFileSystem.java
+++ 
b/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicRootedOzoneFileSystem.java
@@ -532,6 +532,12 @@ public class BasicRootedOzoneFileSystem extends FileSystem 
{
         OM_SNAPSHOT_INDICATOR + OZONE_URI_DELIMITER + snapshot);
   }
 
+  @Override
+  public void renameSnapshot(Path path, String snapshotOldName, String 
snapshotNewName)
+      throws IOException {
+    getAdapter().renameSnapshot(pathToKey(path), snapshotOldName, 
snapshotNewName);
+  }
+
   @Override
   public void deleteSnapshot(Path path, String snapshotName)
       throws IOException {
diff --git 
a/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/OzoneClientAdapter.java
 
b/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/OzoneClientAdapter.java
index c48f1a6366..1a6462c1bb 100644
--- 
a/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/OzoneClientAdapter.java
+++ 
b/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/OzoneClientAdapter.java
@@ -89,6 +89,8 @@ public interface OzoneClientAdapter {
 
   String createSnapshot(String pathStr, String snapshotName) throws 
IOException;
 
+  void renameSnapshot(String pathStr, String snapshotOldName, String 
snapshotNewName) throws IOException;
+
   void deleteSnapshot(String pathStr, String snapshotName) throws IOException;
 
   SnapshotDiffReport getSnapshotDiffReport(Path snapshotDir,
diff --git 
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ClientProtocolStub.java
 
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ClientProtocolStub.java
index 7515d991eb..d9b834c318 100644
--- 
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ClientProtocolStub.java
+++ 
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/ClientProtocolStub.java
@@ -650,6 +650,13 @@ public class ClientProtocolStub implements ClientProtocol {
     return "";
   }
 
+  @Override
+  public void renameSnapshot(String volumeName, String bucketName,
+      String snapshotOldName, String snapshotNewName)
+      throws IOException {
+
+  }
+
   @Override
   public List<OzoneSnapshot> listSnapshot(
       String volumeName, String bucketName, String snapshotPrefix,
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/snapshot/RenameSnapshotHandler.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/snapshot/RenameSnapshotHandler.java
new file mode 100644
index 0000000000..63b61b1ec6
--- /dev/null
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/snapshot/RenameSnapshotHandler.java
@@ -0,0 +1,64 @@
+/*
+ * 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.shell.snapshot;
+
+import java.io.IOException;
+import org.apache.hadoop.ozone.OmUtils;
+import org.apache.hadoop.ozone.client.OzoneClient;
+import org.apache.hadoop.ozone.client.OzoneClientException;
+import org.apache.hadoop.ozone.shell.Handler;
+import org.apache.hadoop.ozone.shell.OzoneAddress;
+import org.apache.hadoop.ozone.shell.bucket.BucketUri;
+import picocli.CommandLine;
+
+/**
+ * ozone sh snapshot rename.
+ */
[email protected](name = "rename",
+    description = "Rename a snapshot")
+public class RenameSnapshotHandler extends Handler {
+
+  @CommandLine.Mixin
+  private BucketUri snapshotPath;
+
+  @CommandLine.Parameters(description = "Current snapshot name",
+      index = "1", arity = "1")
+  private String snapshotOldName;
+
+  @CommandLine.Parameters(description = "New snapshot name",
+      index = "2", arity = "1")
+  private String snapshotNewName;
+
+  @Override
+  protected OzoneAddress getAddress() {
+    return snapshotPath.getValue();
+  }
+
+  @Override
+  protected void execute(OzoneClient client, OzoneAddress address) throws 
IOException, OzoneClientException {
+    String volumeName = snapshotPath.getValue().getVolumeName();
+    String bucketName = snapshotPath.getValue().getBucketName();
+    OmUtils.validateSnapshotName(snapshotNewName);
+    client.getObjectStore()
+        .renameSnapshot(volumeName, bucketName, snapshotOldName, 
snapshotNewName);
+    if (isVerbose()) {
+      out().format("Renamed snapshot from'%s' to %s under '%s/%s'.%n",
+          snapshotOldName, snapshotNewName, volumeName, bucketName);
+    }
+  }
+}
diff --git 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/snapshot/SnapshotCommands.java
 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/snapshot/SnapshotCommands.java
index cf513b9e91..25a3c1c66f 100644
--- 
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/snapshot/SnapshotCommands.java
+++ 
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/snapshot/SnapshotCommands.java
@@ -43,7 +43,8 @@ import picocli.CommandLine.ParentCommand;
         ListSnapshotHandler.class,
         SnapshotDiffHandler.class,
         ListSnapshotDiffHandler.class,
-        InfoSnapshotHandler.class
+        InfoSnapshotHandler.class,
+        RenameSnapshotHandler.class
     },
     mixinStandardHelpOptions = true,
     versionProvider = HddsVersionProvider.class)


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

Reply via email to