Skip to content
Open
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
14 changes: 14 additions & 0 deletions hadoop-ozone/dist/src/main/smoketest/basic/links.robot
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,20 @@ Link to non-existent bucket
Execute ozone sh bucket link ${source}/no-such-bucket ${target}/dangling-link
${result} = Execute And Ignore Error ozone sh key list ${target}/dangling-link
Should Contain ${result} BUCKET_NOT_FOUND
Comment thread
sarvekshayr marked this conversation as resolved.
Should Contain ${result} Cannot follow bucket link

Link to non-existent source volume
Execute ozone sh bucket link no-such-volume/no-such-bucket ${target}/dangling-missing-vol
${result} = Execute And Ignore Error ozone sh key list ${target}/dangling-missing-vol
Should Contain ${result} BUCKET_NOT_FOUND
Should Contain ${result} Cannot follow bucket link

Link chain to broken source
Execute ozone sh bucket link no-such-volume/no-such-bucket ${target}/link-bucket2
Execute ozone sh bucket link ${target}/link-bucket2 ${target}/link-bucket1
${result} = Execute And Ignore Error ozone sh key list ${target}/link-bucket1
Should Contain ${result} BUCKET_NOT_FOUND
Should Contain ${result} Cannot follow bucket link

Key create passthrough
Ozone Shell Batch bucket link ${source}/bucket1 ${target}/link1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_SERVER_DEFAULT_REPLICATION_TYPE_KEY;
import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_SNAPSHOT_SST_FILTERING_SERVICE_INTERVAL;
import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_THREAD_NUMBER_DIR_DELETION;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.BUCKET_NOT_FOUND;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.DETECTED_LOOP_IN_BUCKET_LINKS;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.FEATURE_NOT_ENABLED;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.INTERNAL_ERROR;
Expand All @@ -104,6 +105,7 @@
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.NOT_SUPPORTED_OPERATION;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.PERMISSION_DENIED;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.TOKEN_ERROR_OTHER;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.VOLUME_NOT_FOUND;
import static org.apache.hadoop.ozone.om.lock.OzoneManagerLock.LeveledResource.BUCKET_LOCK;
import static org.apache.hadoop.ozone.om.lock.OzoneManagerLock.LeveledResource.VOLUME_LOCK;
import static org.apache.hadoop.ozone.om.ratis.OzoneManagerRatisServer.RaftServerStatus.LEADER_AND_NOT_READY;
Expand Down Expand Up @@ -5494,6 +5496,13 @@ private OmBucketInfo resolveBucketLink(
if (allowDanglingBuckets) {
return null;
}

if (!visited.isEmpty()
&& (e.getResult() == VOLUME_NOT_FOUND || e.getResult() == BUCKET_NOT_FOUND)) {
throw new OMException(
"Cannot follow bucket link: linked source bucket does not exist",
BUCKET_NOT_FOUND);
Comment thread
sarvekshayr marked this conversation as resolved.
Comment on lines +5502 to +5504

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Pass e as the cause in OMException(String, Throwable, ResultCodes), this way OM logs would still show the original VOLUME_NOT_FOUND or BUCKET_NOT_FOUND cause.

Suggested change
throw new OMException(
"Cannot follow bucket link: linked source bucket does not exist",
BUCKET_NOT_FOUND);
throw new OMException(
"Cannot follow bucket link: linked source bucket does not exist", e, BUCKET_NOT_FOUND);

}
throw e;
}
if (!info.isLink()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
Expand All @@ -44,6 +45,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.crypto.key.KeyProvider;
import org.apache.hadoop.crypto.key.KeyProviderCryptoExtension;
import org.apache.hadoop.hdds.client.DefaultReplicationConfig;
Expand Down Expand Up @@ -660,6 +662,84 @@ private static void denySourceRead(OmMetadataReader metadataReader, String sourc
}).when(metadataReader).checkAcls(any(), any(), any(), any(), any(), any());
}

@Test
void testResolveBucketLinkMissingSourceVolume() throws Exception {
String targetVolume = volumeName();
String missingSourceVolume = volumeName();
OmBucketInfo danglingLink = OmBucketInfo.newBuilder()
.setVolumeName(targetVolume)
.setBucketName("dangling-link")
.setSourceVolume(missingSourceVolume)
.setSourceBucket("any-bucket")
.build();
BucketManager bucketManager = mock(BucketManager.class);
when(bucketManager.getBucketInfo(targetVolume, "dangling-link")).thenReturn(danglingLink);
when(bucketManager.getBucketInfo(missingSourceVolume, "any-bucket"))
.thenThrow(new OMException("Volume doesn't exist", ResultCodes.VOLUME_NOT_FOUND));
OzoneManager omSpy = spy(omTestManagers.getOzoneManager());
HddsWhiteboxTestUtils.setInternalState(omSpy, "bucketManager", bucketManager);
when(omSpy.getAclsEnabled()).thenReturn(false);

OMException omEx = assertThrows(OMException.class,
() -> omSpy.resolveBucketLink(Pair.of(targetVolume, "dangling-link")));
assertEquals(ResultCodes.BUCKET_NOT_FOUND, omEx.getResult());
assertThat(omEx.getMessage()).contains("Cannot follow bucket link");
}

@Test
void testResolveBucketLinkMissingSourceBucket() throws Exception {
String targetVolume = volumeName();
String sourceVolume = volumeName();
OmBucketInfo danglingLink = OmBucketInfo.newBuilder()
.setVolumeName(targetVolume)
.setBucketName("dangling-link-bucket")
.setSourceVolume(sourceVolume)
.setSourceBucket("no-such-bucket")
.build();
BucketManager bucketManager = mock(BucketManager.class);
when(bucketManager.getBucketInfo(targetVolume, "dangling-link-bucket")).thenReturn(danglingLink);
when(bucketManager.getBucketInfo(sourceVolume, "no-such-bucket"))
.thenThrow(new OMException("Bucket not found", ResultCodes.BUCKET_NOT_FOUND));
OzoneManager omSpy = spy(omTestManagers.getOzoneManager());
HddsWhiteboxTestUtils.setInternalState(omSpy, "bucketManager", bucketManager);
when(omSpy.getAclsEnabled()).thenReturn(false);

OMException omEx = assertThrows(OMException.class,
() -> omSpy.resolveBucketLink(Pair.of(targetVolume, "dangling-link-bucket")));
assertEquals(ResultCodes.BUCKET_NOT_FOUND, omEx.getResult());
assertThat(omEx.getMessage()).contains("Cannot follow bucket link");
}

@Test
void testListKeysOnLinkWithMissingSourceVolume() throws Exception {
String targetVolume = volumeName();
String missingSourceVolume = volumeName();
OmBucketInfo danglingLink = OmBucketInfo.newBuilder()
.setVolumeName(targetVolume)
.setBucketName("dangling-link-list")
.setSourceVolume(missingSourceVolume)
.setSourceBucket("any-bucket")
.build();
BucketManager bucketManager = mock(BucketManager.class);
when(bucketManager.getBucketInfo(targetVolume, "dangling-link-list")).thenReturn(danglingLink);
when(bucketManager.getBucketInfo(missingSourceVolume, "any-bucket"))
.thenThrow(new OMException("Volume doesn't exist", ResultCodes.VOLUME_NOT_FOUND));
OzoneManager om = omTestManagers.getOzoneManager();
OzoneManager omSpy = spy(om);
HddsWhiteboxTestUtils.setInternalState(omSpy, "bucketManager", bucketManager);
when(omSpy.getAclsEnabled()).thenReturn(false);
OmMetadataReader metadataReader = (OmMetadataReader) HddsWhiteboxTestUtils.getInternalState(om,
"omMetadataReader");
HddsWhiteboxTestUtils.setInternalState(metadataReader, "ozoneManager", omSpy);

OMException omEx = assertThrows(OMException.class,
() -> omSpy.listKeys(targetVolume, "dangling-link-list", null, null, 100));
assertEquals(ResultCodes.BUCKET_NOT_FOUND, omEx.getResult());
assertThat(omEx.getMessage()).contains("Cannot follow bucket link");
verify(bucketManager).getBucketInfo(eq(targetVolume), eq("dangling-link-list"));
verify(bucketManager).getBucketInfo(eq(missingSourceVolume), eq("any-bucket"));
}

Comment thread
sarvekshayr marked this conversation as resolved.
private OzoneManager createAclEnabledOmSpy(BucketManager bucketManager, OmMetadataReader metadataReader) {
OzoneManager omSpy = spy(omTestManagers.getOzoneManager());
HddsWhiteboxTestUtils.setInternalState(omSpy, "bucketManager", bucketManager);
Expand Down