This is an automated email from the ASF dual-hosted git repository.
lupeng pushed a commit to branch branch-2.5
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/branch-2.5 by this push:
new 52b991381d9 HBASE-29296 Missing critical snapshot expiration checks
(#7195)
52b991381d9 is described below
commit 52b991381d905634187c84ddacfe3d0dfca35fb7
Author: Dimas Shidqi Parikesit <[email protected]>
AuthorDate: Sat Aug 16 11:54:57 2025 -0400
HBASE-29296 Missing critical snapshot expiration checks (#7195)
Signed-off-by: Peng Lu <[email protected]>
---
.../hbase/master/snapshot/TakeSnapshotHandler.java | 10 ++++++++++
.../hbase/client/TestSnapshotWithTTLFromClient.java | 8 ++++----
.../hbase/master/snapshot/TestTakeSnapshotHandler.java | 17 +++++++++++++++++
3 files changed, 31 insertions(+), 4 deletions(-)
diff --git
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/TakeSnapshotHandler.java
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/TakeSnapshotHandler.java
index e51321f3273..f967beec892 100644
---
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/TakeSnapshotHandler.java
+++
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/snapshot/TakeSnapshotHandler.java
@@ -50,7 +50,9 @@ import org.apache.hadoop.hbase.procedure2.LockType;
import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
import org.apache.hadoop.hbase.snapshot.SnapshotManifest;
+import org.apache.hadoop.hbase.snapshot.SnapshotTTLExpiredException;
import org.apache.hadoop.hbase.util.CommonFSUtils;
+import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.yetus.audience.InterfaceAudience;
import org.apache.zookeeper.KeeperException;
@@ -238,6 +240,14 @@ public abstract class TakeSnapshotHandler extends
EventHandler
status.setStatus("Verifying snapshot: " + snapshot.getName());
verifier.verifySnapshot(this.workingDir, serverNames);
+ // HBASE-29296 check snapshot is not expired
+ if (
+ SnapshotDescriptionUtils.isExpiredSnapshot(snapshot.getTtl(),
snapshot.getCreationTime(),
+ EnvironmentEdgeManager.currentTime())
+ ) {
+ throw new
SnapshotTTLExpiredException(ProtobufUtil.createSnapshotDesc(snapshot));
+ }
+
// complete the snapshot, atomically moving from tmp to .snapshot dir.
SnapshotDescriptionUtils.completeSnapshot(this.snapshotDir,
this.workingDir, this.rootFs,
this.workingDirFs, this.conf);
diff --git
a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestSnapshotWithTTLFromClient.java
b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestSnapshotWithTTLFromClient.java
index 4309b922b8f..9713569e406 100644
---
a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestSnapshotWithTTLFromClient.java
+++
b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestSnapshotWithTTLFromClient.java
@@ -143,7 +143,7 @@ public class TestSnapshotWithTTLFromClient {
assertTrue(UTIL.getAdmin().tableExists(TABLE_NAME));
// create snapshot fo given table with specified ttl
- createSnapshotWithTTL(TABLE_NAME, snapshotName, 1);
+ createSnapshotWithTTL(TABLE_NAME, snapshotName, 5);
Admin admin = UTIL.getAdmin();
// Disable and drop table
@@ -152,7 +152,7 @@ public class TestSnapshotWithTTLFromClient {
assertFalse(UTIL.getAdmin().tableExists(TABLE_NAME));
// Sleep so that TTL may expire
- Threads.sleep(2000);
+ Threads.sleep(10000);
// restore snapshot which has expired
try {
@@ -192,13 +192,13 @@ public class TestSnapshotWithTTLFromClient {
assertTrue(UTIL.getAdmin().tableExists(TABLE_NAME));
// create snapshot fo given table with specified ttl
- createSnapshotWithTTL(TABLE_NAME, snapshotName, 1);
+ createSnapshotWithTTL(TABLE_NAME, snapshotName, 5);
Admin admin = UTIL.getAdmin();
assertTrue(UTIL.getAdmin().tableExists(TABLE_NAME));
// Sleep so that TTL may expire
- Threads.sleep(2000);
+ Threads.sleep(10000);
// clone snapshot which has expired
try {
diff --git
a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/snapshot/TestTakeSnapshotHandler.java
b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/snapshot/TestTakeSnapshotHandler.java
index e9d3b9784d6..edf232394ed 100644
---
a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/snapshot/TestTakeSnapshotHandler.java
+++
b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/snapshot/TestTakeSnapshotHandler.java
@@ -18,6 +18,8 @@
package org.apache.hadoop.hbase.master.snapshot;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import java.util.HashMap;
import java.util.Map;
@@ -29,6 +31,8 @@ import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.client.TableDescriptor;
import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
+import org.apache.hadoop.hbase.snapshot.HBaseSnapshotException;
+import org.apache.hadoop.hbase.snapshot.SnapshotTTLExpiredException;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
@@ -100,6 +104,19 @@ public class TestTakeSnapshotHandler {
assertEquals(-1, UTIL.getAdmin().getDescriptor(cloned).getMaxFileSize());
}
+ @Test
+ public void testSnapshotEarlyExpiration() throws Exception {
+ UTIL.startMiniCluster();
+ Map<String, Object> snapshotProps = new HashMap<>();
+ snapshotProps.put("TTL", 1L);
+ HBaseSnapshotException hBaseSnapshotException =
assertThrows(HBaseSnapshotException.class,
+ () -> createTableInsertDataAndTakeSnapshot(snapshotProps));
+ assertTrue(
+
hBaseSnapshotException.toString().contains(SnapshotTTLExpiredException.class.getName()));
+ assertTrue(hBaseSnapshotException.getMessage()
+ .contains("TTL for snapshot 'snaptestSnapshotEarlyExpiration' has
already expired"));
+ }
+
@After
public void shutdown() throws Exception {
UTIL.shutdownMiniCluster();