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
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ private OzoneConsts() {
public static final String MAX_PARTS = "maxParts";
public static final String S3_BUCKET = "s3Bucket";
public static final String S3_GETSECRET_USER = "S3GetSecretUser";
public static final String RENAMED_KEYS_MAP = "renamedKeysMap";
public static final String UNRENAMED_KEYS_MAP = "unRenamedKeysMap";
public static final String MULTIPART_UPLOAD_PART_NUMBER = "partNumber";
public static final String MULTIPART_UPLOAD_PART_NAME = "partName";
public static final String BUCKET_ENCRYPTION_KEY = "bucketEncryptionKey";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,16 @@ public void renameKey(String fromKeyName, String toKeyName)
proxy.renameKey(volumeName, name, fromKeyName, toKeyName);
}

/**
* Rename the key by keyMap, The key is fromKeyName and value is toKeyName.
* @param keyMap The key is original key name nad value is new key name.
* @throws IOException
*/
public void renameKeys(Map<String, String> keyMap)
throws IOException {
proxy.renameKeys(volumeName, name, keyMap);
}

/**
* Initiate multipart upload for a specified key.
* @param keyName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,17 @@ void deleteKeys(String volumeName, String bucketName,
* @throws IOException
*/
void renameKey(String volumeName, String bucketName, String fromKeyName,
String toKeyName) throws IOException;
String toKeyName) throws IOException;

/**
* Renames existing keys within a bucket.
* @param volumeName Name of the Volume
* @param bucketName Name of the Bucket
* @param keyMap The key is original key name nad value is new key name.
* @throws IOException
*/
void renameKeys(String volumeName, String bucketName,
Map<String, String> keyMap) throws IOException;

/**
* Returns list of Keys in {Volume/Bucket} that matches the keyPrefix,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
import org.apache.hadoop.ozone.om.helpers.OmMultipartUploadList;
import org.apache.hadoop.ozone.om.helpers.OmMultipartUploadListParts;
import org.apache.hadoop.ozone.om.helpers.OmPartInfo;
import org.apache.hadoop.ozone.om.helpers.OmRenameKeys;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OpenKeySession;
import org.apache.hadoop.ozone.om.helpers.OzoneAclUtil;
Expand Down Expand Up @@ -760,6 +761,18 @@ public void renameKey(String volumeName, String bucketName,
ozoneManagerClient.renameKey(keyArgs, toKeyName);
}

@Override
public void renameKeys(String volumeName, String bucketName,
Map<String, String> keyMap) throws IOException {
verifyVolumeName(volumeName);
verifyBucketName(bucketName);
HddsClientUtils.checkNotNull(keyMap);
OmRenameKeys omRenameKeys =
new OmRenameKeys(volumeName, bucketName, keyMap, null);
ozoneManagerClient.renameKeys(omRenameKeys);
}


@Override
public List<OzoneKey> listKeys(String volumeName, String bucketName,
String keyPrefix, String prevKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ public static boolean isReadOnly(
case DeleteBucket:
case CreateKey:
case RenameKey:
case RenameKeys:
case DeleteKey:
case DeleteKeys:
case CommitKey:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public enum OMAction implements AuditAction {
DELETE_BUCKET,
DELETE_KEY,
RENAME_KEY,
RENAME_KEYS,
SET_OWNER,
SET_QUOTA,
UPDATE_VOLUME,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ public enum ResultCodes {

DETECTED_LOOP_IN_BUCKET_LINKS,

NOT_SUPPORTED_OPERATION
NOT_SUPPORTED_OPERATION,

PARTIAL_RENAME

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* 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.helpers;

import java.util.HashMap;
import java.util.Map;

/**
* This class is used for rename keys.
*/
public class OmRenameKeys {

private String volume;
private String bucket;
private Map<String, String> fromAndToKey = new HashMap<>();
private Map<String, OmKeyInfo> fromKeyAndToKeyInfo = new HashMap<>();

public OmRenameKeys(String volume, String bucket,
Map<String, String> fromAndToKey,
Map<String, OmKeyInfo> fromKeyAndToKeyInfo) {
this.volume = volume;
this.bucket = bucket;
this.fromAndToKey = fromAndToKey;
this.fromKeyAndToKeyInfo = fromKeyAndToKeyInfo;
}

public String getVolume() {
return volume;
}

public String getBucket() {
return bucket;
}

public Map<String, String> getFromAndToKey() {
return fromAndToKey;
}

public Map<String, OmKeyInfo> getFromKeyAndToKeyInfo() {
return fromKeyAndToKeyInfo;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.apache.hadoop.ozone.om.helpers.OmMultipartUploadCompleteList;
import org.apache.hadoop.ozone.om.helpers.OmMultipartUploadList;
import org.apache.hadoop.ozone.om.helpers.OmMultipartUploadListParts;
import org.apache.hadoop.ozone.om.helpers.OmRenameKeys;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OpenKeySession;
import org.apache.hadoop.ozone.om.helpers.OzoneFileStatus;
Expand Down Expand Up @@ -217,6 +218,14 @@ OmKeyLocationInfo allocateBlock(OmKeyArgs args, long clientID,
*/
void renameKey(OmKeyArgs args, String toKeyName) throws IOException;

/**
* Rename existing keys within a bucket.
* @param omRenameKeys Includes volume, bucket, and fromKey toKey name map
* and fromKey name toKey info Map.
* @throws IOException
*/
void renameKeys(OmRenameKeys omRenameKeys) throws IOException;

/**
* Deletes an existing key.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.hadoop.hdds.annotation.InterfaceAudience;
Expand All @@ -44,6 +45,7 @@
import org.apache.hadoop.ozone.om.helpers.OmMultipartUploadCompleteList;
import org.apache.hadoop.ozone.om.helpers.OmMultipartUploadList;
import org.apache.hadoop.ozone.om.helpers.OmMultipartUploadListParts;
import org.apache.hadoop.ozone.om.helpers.OmRenameKeys;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OpenKeySession;
import org.apache.hadoop.ozone.om.helpers.OzoneFileStatus;
Expand Down Expand Up @@ -121,7 +123,10 @@
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.RecoverTrashResponse;
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.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.RenewDelegationTokenResponseProto;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServiceListRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.ServiceListResponse;
Expand Down Expand Up @@ -675,6 +680,33 @@ public OmKeyInfo lookupKey(OmKeyArgs args) throws IOException {
return OmKeyInfo.getFromProtobuf(resp.getKeyInfo());
}

@Override
public void renameKeys(OmRenameKeys omRenameKeys) throws IOException {

List<RenameKeysMap> renameKeyList = new ArrayList<>();
for (Map.Entry< String, String> entry :
omRenameKeys.getFromAndToKey().entrySet()) {
RenameKeysMap.Builder renameKey = RenameKeysMap.newBuilder()
.setFromKeyName(entry.getKey())
.setToKeyName(entry.getValue());
renameKeyList.add(renameKey.build());
}

RenameKeysArgs.Builder renameKeyArgs = RenameKeysArgs.newBuilder()
.setVolumeName(omRenameKeys.getVolume())
.setBucketName(omRenameKeys.getBucket())
.addAllRenameKeysMap(renameKeyList);

RenameKeysRequest.Builder reqKeys = RenameKeysRequest.newBuilder()
.setRenameKeysArgs(renameKeyArgs.build());

OMRequest omRequest = createOMRequest(Type.RenameKeys)
.setRenameKeysRequest(reqKeys.build())
.build();

handleError(submitRequest(omRequest));
}

@Override
public void renameKey(OmKeyArgs args, String toKeyName) throws IOException {
RenameKeyRequest.Builder req = RenameKeyRequest.newBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@
import static org.apache.hadoop.ozone.OzoneAcl.AclScope.ACCESS;
import static org.apache.hadoop.ozone.OzoneAcl.AclScope.DEFAULT;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.NO_SUCH_MULTIPART_UPLOAD_ERROR;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.KEY_NOT_FOUND;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.PARTIAL_RENAME;
import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLIdentityType.GROUP;
import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLIdentityType.USER;
import static org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.READ;
Expand All @@ -121,6 +123,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import org.junit.Test;

/**
Expand Down Expand Up @@ -1202,7 +1205,7 @@ public void testDeleteKey()
Assert.assertEquals(keyName, key.getName());
bucket.deleteKey(keyName);

OzoneTestUtils.expectOmException(ResultCodes.KEY_NOT_FOUND,
OzoneTestUtils.expectOmException(KEY_NOT_FOUND,
() -> bucket.getKey(keyName));
}

Expand All @@ -1217,13 +1220,7 @@ public void testRenameKey()
OzoneVolume volume = store.getVolume(volumeName);
volume.createBucket(bucketName);
OzoneBucket bucket = volume.getBucket(bucketName);
OzoneOutputStream out = bucket.createKey(fromKeyName,
value.getBytes().length, STAND_ALONE,
ONE, new HashMap<>());
out.write(value.getBytes());
out.close();
OzoneKey key = bucket.getKey(fromKeyName);
Assert.assertEquals(fromKeyName, key.getName());
createTestKey(bucket, fromKeyName, value);

// Rename to empty string should fail.
OMException oe = null;
Expand All @@ -1244,12 +1241,79 @@ public void testRenameKey()
} catch (OMException e) {
oe = e;
}
Assert.assertEquals(ResultCodes.KEY_NOT_FOUND, oe.getResult());
Assert.assertEquals(KEY_NOT_FOUND, oe.getResult());

key = bucket.getKey(toKeyName);
OzoneKey key = bucket.getKey(toKeyName);
Assert.assertEquals(toKeyName, key.getName());
}

@Test
public void testKeysRename() throws Exception {
String volumeName = UUID.randomUUID().toString();
String bucketName = UUID.randomUUID().toString();
String keyName1 = "dir/file1";
String keyName2 = "dir/file2";

String newKeyName1 = "dir/key1";
String newKeyName2 = "dir/key2";

String value = "sample value";
store.createVolume(volumeName);
OzoneVolume volume = store.getVolume(volumeName);
volume.createBucket(bucketName);
OzoneBucket bucket = volume.getBucket(bucketName);
createTestKey(bucket, keyName1, value);
createTestKey(bucket, keyName2, value);

Map<String, String> keyMap = new HashMap();
keyMap.put(keyName1, newKeyName1);
keyMap.put(keyName2, newKeyName2);
bucket.renameKeys(keyMap);

// new key should exist
Assert.assertEquals(newKeyName1, bucket.getKey(newKeyName1).getName());
Assert.assertEquals(newKeyName2, bucket.getKey(newKeyName2).getName());

// old key should not exist
assertKeyRenamedEx(bucket, keyName1);
assertKeyRenamedEx(bucket, keyName2);
}

@Test
public void testKeysRenameFail() throws Exception {
String volumeName = UUID.randomUUID().toString();
String bucketName = UUID.randomUUID().toString();
String keyName1 = "dir/file1";
String keyName2 = "dir/file2";

String newKeyName1 = "dir/key1";
String newKeyName2 = "dir/key2";

String value = "sample value";
store.createVolume(volumeName);
OzoneVolume volume = store.getVolume(volumeName);
volume.createBucket(bucketName);
OzoneBucket bucket = volume.getBucket(bucketName);

// Create only keyName1 to test the partial failure of renameKeys.
createTestKey(bucket, keyName1, value);

Map<String, String> keyMap = new HashMap();
keyMap.put(keyName1, newKeyName1);
keyMap.put(keyName2, newKeyName2);

try {
bucket.renameKeys(keyMap);
} catch (OMException ex) {
Assert.assertEquals(PARTIAL_RENAME, ex.getResult());
}

// newKeyName1 should exist
Assert.assertEquals(newKeyName1, bucket.getKey(newKeyName1).getName());
// newKeyName2 should not exist
assertKeyRenamedEx(bucket, keyName2);
}

@Test
public void testListVolume() throws IOException {
String volBase = "vol-" + RandomStringUtils.randomNumeric(3);
Expand Down Expand Up @@ -2685,6 +2749,28 @@ private void completeMultipartUpload(OzoneBucket bucket, String keyName,
Assert.assertNotNull(omMultipartUploadCompleteInfo.getHash());
}

private void createTestKey(OzoneBucket bucket, String keyName,
String keyValue) throws IOException {
OzoneOutputStream out = bucket.createKey(keyName,
keyValue.getBytes().length, STAND_ALONE,
ONE, new HashMap<>());
out.write(keyValue.getBytes());
out.close();
OzoneKey key = bucket.getKey(keyName);
Assert.assertEquals(keyName, key.getName());
}

private void assertKeyRenamedEx(OzoneBucket bucket, String keyName)
throws Exception {
OMException oe = null;
try {
bucket.getKey(keyName);
} catch (OMException e) {
oe = e;
}
Assert.assertEquals(KEY_NOT_FOUND, oe.getResult());
}

/**
* Tests GDPR encryption/decryption.
* 1. Create GDPR Enabled bucket.
Expand Down
Loading