Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions hadoop-hdds/common/src/main/resources/ozone-default.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3936,6 +3936,16 @@
</description>
</property>

<property>
<name>ozone.om.snapshot.rename.allowed</name>
<value>false</value>
<tag>OZONE, OM</tag>
<description>
Allows the Ozone snapshot rename operation if set to true on the OM side.
Blocks it otherwise.
</description>
</property>

<property>
<name>ozone.snapshot.deleting.service.timeout</name>
<value>300s</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ These parameters, defined in `ozone-site.xml`, control how Ozone manages snapsho
* `ozone.om.ratis.snapshot.max.total.sst.size`: The maximum total size of SST files to be included in a Ratis snapshot (Default: 10737418240).
* `ozone.om.snapshot.load.native.lib`: Use native RocksDB library for snapshot operations (Default: true). Set to false as a workaround for native library issues.
* `ozone.om.snapshot.checkpoint.dir.creation.poll.timeout`: Timeout for polling the creation of the snapshot checkpoint directory (Default: 20s).
* `ozone.om.snapshot.rename.allowed`: Allow snapshot rename operation (Default: false).

* **SnapshotDiff Service**
* `ozone.om.snapshot.diff.db.dir`: Directory for SnapshotDiff job data. Defaults to OM metadata dir. Use a spacious location for large diffs.
Expand Down
2 changes: 1 addition & 1 deletion hadoop-hdds/docs/content/feature/Snapshot.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ Manage snapshots using `ozone sh` or `ozone fs` (Hadoop-compatible) commands:
```shell
ozone sh snapshot rename /vol1/bucket1 <oldName> <newName>
```
Requires bucket owner or admin.
Requires `ozone.om.snapshot.rename.allowed=true` on the OM side and bucket owner or admin privileges.

* **Snapshot Info:**
```shell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public final class OMConfigKeys {
public static final String OZONE_FILESYSTEM_SNAPSHOT_ENABLED_KEY =
"ozone.filesystem.snapshot.enabled";
public static final boolean OZONE_FILESYSTEM_SNAPSHOT_ENABLED_DEFAULT = true;
public static final String OZONE_OM_SNAPSHOT_RENAME_ALLOWED_KEY =
"ozone.om.snapshot.rename.allowed";
public static final boolean OZONE_OM_SNAPSHOT_RENAME_ALLOWED_DEFAULT = false;

// Location where the OM stores its DB files. In the future we may support
// multiple entries for performance (sharding)..
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@
import static org.apache.hadoop.ozone.OzoneConsts.OZONE_OFS_URI_SCHEME;
import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_SNAPSHOT_SST_FILTERING_SERVICE_INTERVAL;
import static org.apache.hadoop.ozone.om.OmSnapshotManager.getSnapshotPath;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.FEATURE_NOT_ENABLED;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
Expand All @@ -45,12 +49,16 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.hdds.cli.GenericCli;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.ozone.MiniOzoneCluster;
import org.apache.hadoop.ozone.client.OzoneClient;
import org.apache.hadoop.ozone.om.OMConfigKeys;
import org.apache.hadoop.ozone.om.OmConfig;
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.shell.OzoneShell;
import org.apache.hadoop.util.ToolRunner;
import org.apache.ozone.test.GenericTestUtils;
import org.junit.jupiter.api.AfterAll;
Expand All @@ -68,6 +76,9 @@
*/
class TestOzoneFsSnapshot {

private static final String SNAPSHOT_RENAME_NOT_ALLOWED_MESSAGE =
"Ozone snapshot rename feature is not allowed per Ozone Manager server config";

private static MiniOzoneCluster cluster;
private static final String OM_SERVICE_ID = "om-service-test1";
private static OzoneManager ozoneManager;
Expand Down Expand Up @@ -95,6 +106,8 @@ static void initClass() throws Exception {
conf.setInt(OZONE_SNAPSHOT_SST_FILTERING_SERVICE_INTERVAL, -1);
conf.setInt(OmConfig.Keys.SERVER_LIST_MAX_SIZE, 20);
conf.setInt(OZONE_FS_LISTING_PAGE_SIZE, 30);
// Explicitly disable snapshot rename for the test
conf.setBoolean(OMConfigKeys.OZONE_OM_SNAPSHOT_RENAME_ALLOWED_KEY, false);

// Start the cluster
cluster = MiniOzoneCluster.newHABuilder(conf)
Expand Down Expand Up @@ -212,6 +225,44 @@ void testCreateSnapshotSuccess(String snapshotName)
assertNotNull(snapshotInfo);
}

@Test
void testSnapshotRenameBlockedWhenConfigDisallows(@TempDir Path tempDir)
throws Exception {
assertFalse(cluster.getConf().getBoolean(
OMConfigKeys.OZONE_OM_SNAPSHOT_RENAME_ALLOWED_KEY,
OMConfigKeys.OZONE_OM_SNAPSHOT_RENAME_ALLOWED_DEFAULT));

String oldSnapshotName = createSnapshot();
String newSnapshotName = "snap-" + counter.incrementAndGet();

try (OzoneClient ozoneClient = cluster.newClient()) {
OMException omException = assertThrows(OMException.class,
() -> ozoneClient.getObjectStore().renameSnapshot(
VOLUME, BUCKET, oldSnapshotName, newSnapshotName));
assertEquals(FEATURE_NOT_ENABLED, omException.getResult());
assertEquals(SNAPSHOT_RENAME_NOT_ALLOWED_MESSAGE,
omException.getMessage());
Comment thread
smengcl marked this conversation as resolved.
}

Path confPath = tempDir.resolve("ozone-site.xml");
try (OutputStream outputStream = Files.newOutputStream(confPath)) {
cluster.getConf().writeXml(outputStream);
}

try (GenericTestUtils.SystemErrCapturer capture =
new GenericTestUtils.SystemErrCapturer()) {
OzoneShell ozoneShell = new OzoneShell();
int res = ozoneShell.execute(new String[] {
"-conf", confPath.toString(), "snapshot", "rename",
"o3://" + OM_SERVICE_ID + BUCKET_PATH,
oldSnapshotName, newSnapshotName});

assertEquals(GenericCli.EXECUTION_ERROR_EXIT_CODE, res);
assertThat(capture.getOutput()).contains(
SNAPSHOT_RENAME_NOT_ALLOWED_MESSAGE);
}
}

private static Stream<Arguments> createSnapshotFailureScenarios() {
String invalidBucketPath = "/invalid/uri";
return Stream.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ public void setup() throws Exception {
conf.setTimeDuration(OMConfigKeys.OZONE_DIR_DELETING_SERVICE_INTERVAL, 1000, TimeUnit.MILLISECONDS);
// For testing fs operations with legacy buckets.
conf.setBoolean(OMConfigKeys.OZONE_OM_ENABLE_FILESYSTEM_PATHS, true);
conf.setBoolean(OMConfigKeys.OZONE_OM_SNAPSHOT_RENAME_ALLOWED_KEY, true);
clusterBuilder = MiniOzoneCluster.newBuilder(conf).setNumDatanodes(5);
startCluster();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.apache.hadoop.ozone.client.VolumeArgs;
import org.apache.hadoop.ozone.client.io.OzoneOutputStream;
import org.apache.hadoop.ozone.om.KeyManagerImpl;
import org.apache.hadoop.ozone.om.OMConfigKeys;
import org.apache.hadoop.ozone.om.OMStorage;
import org.apache.hadoop.ozone.om.OmSnapshotManager;
import org.apache.hadoop.ozone.om.OzoneManager;
Expand Down Expand Up @@ -111,6 +112,7 @@ public static void init() throws Exception {
conf.setBoolean(OZONE_TEST_AUTHORIZATION_ENABLED, true);
conf.setBoolean(OZONE_ACL_ENABLED, true);
conf.set(OZONE_ACL_AUTHORIZER_CLASS, OZONE_ACL_AUTHORIZER_CLASS_NATIVE);
conf.setBoolean(OMConfigKeys.OZONE_OM_SNAPSHOT_RENAME_ALLOWED_KEY, true);

final String omServiceId = "om-service-test-1"
+ RandomStringUtils.secure().nextNumeric(32);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

package org.apache.hadoop.ozone.om.request.snapshot;

import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_SNAPSHOT_RENAME_ALLOWED_DEFAULT;
import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_SNAPSHOT_RENAME_ALLOWED_KEY;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.FEATURE_NOT_ENABLED;
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.LeveledResource.BUCKET_LOCK;
Expand Down Expand Up @@ -69,6 +72,13 @@ public OMSnapshotRenameRequest(OMRequest omRequest) {
public OMRequest preExecute(OzoneManager ozoneManager) throws IOException {
final OMRequest omRequest = super.preExecute(ozoneManager);

if (!ozoneManager.getConfiguration().getBoolean(
OZONE_OM_SNAPSHOT_RENAME_ALLOWED_KEY,
OZONE_OM_SNAPSHOT_RENAME_ALLOWED_DEFAULT)) {
throw new OMException("Ozone snapshot rename feature is not allowed per Ozone Manager server config",
Comment thread
smengcl marked this conversation as resolved.
FEATURE_NOT_ENABLED);
}

final RenameSnapshotRequest renameSnapshotRequest =
omRequest.getRenameSnapshotRequest();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.hadoop.ozone.om.request.snapshot;

import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor.THREE;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.FEATURE_NOT_ENABLED;
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;
Expand All @@ -26,6 +27,7 @@
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.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
Expand All @@ -38,6 +40,7 @@
import org.apache.hadoop.hdds.client.RatisReplicationConfig;
import org.apache.hadoop.hdds.utils.db.cache.CacheKey;
import org.apache.hadoop.hdds.utils.db.cache.CacheValue;
import org.apache.hadoop.ozone.om.OMConfigKeys;
import org.apache.hadoop.ozone.om.OzoneManager;
import org.apache.hadoop.ozone.om.ResolvedBucket;
import org.apache.hadoop.ozone.om.exceptions.OMException;
Expand Down Expand Up @@ -67,6 +70,8 @@ public class TestOMSnapshotRenameRequest extends TestSnapshotRequestAndResponse
public void setup() throws Exception {
snapshotName1 = UUID.randomUUID().toString();
snapshotName2 = UUID.randomUUID().toString();
getOzoneManager().getConfiguration().setBoolean(
OMConfigKeys.OZONE_OM_SNAPSHOT_RENAME_ALLOWED_KEY, true);
}

@ValueSource(strings = {
Expand All @@ -87,6 +92,21 @@ public void testPreExecute(String toSnapshotName) throws Exception {
doPreExecute(omRequest);
}

@Test
public void testPreExecuteFailsWhenSnapshotRenameNotAllowed() {
assertFalse(OMConfigKeys.OZONE_OM_SNAPSHOT_RENAME_ALLOWED_DEFAULT);
getOzoneManager().getConfiguration().unset(
OMConfigKeys.OZONE_OM_SNAPSHOT_RENAME_ALLOWED_KEY);

OzoneManagerProtocolProtos.OMRequest omRequest = renameSnapshotRequest(
getVolumeName(), getBucketName(), snapshotName1, snapshotName2);
OMException omException = assertThrows(OMException.class,
() -> doPreExecute(omRequest));
assertEquals(FEATURE_NOT_ENABLED, omException.getResult());
assertEquals("Ozone snapshot rename feature is not allowed per Ozone Manager server config",
Comment thread
smengcl marked this conversation as resolved.
omException.getMessage());
Comment thread
smengcl marked this conversation as resolved.
}

@ValueSource(strings = {
// '-' is allowed.
"9cdf0e8a-6946-41ad-a2d1-9eb724fab126",
Expand Down