HDDS-1379. Convert all OM Volume related operations to HA model. (#689)

This commit is contained in:
Bharat Viswanadham 2019-04-04 21:09:50 -07:00 committed by GitHub
parent 67020f0950
commit 77fe51e136
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 925 additions and 120 deletions

View File

@ -0,0 +1,49 @@
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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 org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.VolumeList;
/**
* OM response for delete volume request for a ozone volume.
*/
public class OmDeleteVolumeResponse {
private String volume;
private String owner;
private VolumeList updatedVolumeList;
public OmDeleteVolumeResponse(String volume, String owner,
VolumeList updatedVolumeList) {
this.volume = volume;
this.owner = owner;
this.updatedVolumeList = updatedVolumeList;
}
public String getVolume() {
return volume;
}
public String getOwner() {
return owner;
}
public VolumeList getUpdatedVolumeList() {
return updatedVolumeList;
}
}

View File

@ -36,10 +36,10 @@
*/
public final class OmVolumeArgs extends WithMetadata implements Auditable {
private final String adminName;
private final String ownerName;
private String ownerName;
private final String volume;
private final long creationTime;
private final long quotaInBytes;
private long creationTime;
private long quotaInBytes;
private final OmOzoneAclMap aclMap;
/**
@ -64,6 +64,19 @@ private OmVolumeArgs(String adminName, String ownerName, String volume,
this.creationTime = creationTime;
}
public void setOwnerName(String newOwner) {
this.ownerName = newOwner;
}
public void setQuotaInBytes(long quotaInBytes) {
this.quotaInBytes = quotaInBytes;
}
public void setCreationTime(long time) {
this.creationTime = time;
}
/**
* Returns the Admin Name.
* @return String.

View File

@ -0,0 +1,56 @@
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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 org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.VolumeList;
/**
* OM response for owner change request for a ozone volume.
*/
public class OmVolumeOwnerChangeResponse {
private VolumeList originalOwnerVolumeList;
private VolumeList newOwnerVolumeList;
private OmVolumeArgs newOwnerVolumeArgs;
private String originalOwner;
public OmVolumeOwnerChangeResponse(VolumeList originalOwnerVolumeList,
VolumeList newOwnerVolumeList, OmVolumeArgs newOwnerVolumeArgs,
String originalOwner) {
this.originalOwnerVolumeList = originalOwnerVolumeList;
this.newOwnerVolumeList = newOwnerVolumeList;
this.newOwnerVolumeArgs = newOwnerVolumeArgs;
this.originalOwner = originalOwner;
}
public String getOriginalOwner() {
return originalOwner;
}
public VolumeList getOriginalOwnerVolumeList() {
return originalOwnerVolumeList;
}
public VolumeList getNewOwnerVolumeList() {
return newOwnerVolumeList;
}
public OmVolumeArgs getNewOwnerVolumeArgs() {
return newOwnerVolumeArgs;
}
}

View File

@ -18,15 +18,20 @@
package org.apache.hadoop.ozone.om.protocol;
import org.apache.hadoop.ozone.om.helpers.OmDeleteVolumeResponse;
import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo;
import org.apache.hadoop.ozone.om.helpers.OmMultipartInfo;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OmVolumeOwnerChangeResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.KeyArgs;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.KeyInfo;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.KeyLocation;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.VolumeList;
import java.io.IOException;
@ -88,4 +93,77 @@ void applyOpenKey(KeyArgs omKeyArgs, KeyInfo keyInfo, long clientID)
*/
OmMultipartInfo applyInitiateMultipartUpload(OmKeyArgs omKeyArgs,
String multipartUploadID) throws IOException;
/**
* Start Create Volume Transaction.
* @param omVolumeArgs
* @return VolumeList
* @throws IOException
*/
VolumeList startCreateVolume(OmVolumeArgs omVolumeArgs) throws IOException;
/**
* Apply Create Volume changes to OM DB.
* @param omVolumeArgs
* @param volumeList
* @throws IOException
*/
void applyCreateVolume(OmVolumeArgs omVolumeArgs,
VolumeList volumeList) throws IOException;
/**
* Start setOwner Transaction.
* @param volume
* @param owner
* @return OmVolumeOwnerChangeResponse
* @throws IOException
*/
OmVolumeOwnerChangeResponse startSetOwner(String volume,
String owner) throws IOException;
/**
* Apply Set Quota changes to OM DB.
* @param oldOwner
* @param oldOwnerVolumeList
* @param newOwnerVolumeList
* @param newOwnerVolumeArgs
* @throws IOException
*/
void applySetOwner(String oldOwner, VolumeList oldOwnerVolumeList,
VolumeList newOwnerVolumeList, OmVolumeArgs newOwnerVolumeArgs)
throws IOException;
/**
* Start Set Quota Transaction.
* @param volume
* @param quota
* @return OmVolumeArgs
* @throws IOException
*/
OmVolumeArgs startSetQuota(String volume, long quota) throws IOException;
/**
* Apply Set Quota Changes to OM DB.
* @param omVolumeArgs
* @throws IOException
*/
void applySetQuota(OmVolumeArgs omVolumeArgs) throws IOException;
/**
* Start Delete Volume Transaction.
* @param volume
* @return OmDeleteVolumeResponse
* @throws IOException
*/
OmDeleteVolumeResponse startDeleteVolume(String volume) throws IOException;
/**
* Apply Delete Volume changes to OM DB.
* @param volume
* @param owner
* @param newVolumeList
* @throws IOException
*/
void applyDeleteVolume(String volume, String owner,
VolumeList newVolumeList) throws IOException;
}

View File

@ -273,6 +273,7 @@ message VolumeInfo {
*/
message CreateVolumeRequest {
required VolumeInfo volumeInfo = 1;
optional VolumeList volumeList = 2;
}
message CreateVolumeResponse {
@ -290,6 +291,10 @@ message SetVolumePropertyRequest {
required string volumeName = 1;
optional string ownerName = 2;
optional uint64 quotaInBytes = 3;
optional string originalOwner = 4;
optional VolumeList oldOwnerVolumeList = 5;
optional VolumeList newOwnerVolumeList = 6;
optional VolumeInfo volumeInfo = 7;
}
message SetVolumePropertyResponse {
@ -326,6 +331,8 @@ message InfoVolumeResponse {
*/
message DeleteVolumeRequest {
required string volumeName = 1;
optional string owner = 2;
optional VolumeList volumeList = 3;
}
message DeleteVolumeResponse {

View File

@ -87,11 +87,11 @@ public void testVolumeOps() throws IOException {
ozoneManager, "volumeManager");
VolumeManager mockVm = Mockito.spy(volumeManager);
Mockito.doNothing().when(mockVm).createVolume(null);
Mockito.doNothing().when(mockVm).deleteVolume(null);
Mockito.doReturn(null).when(mockVm).createVolume(null);
Mockito.doReturn(null).when(mockVm).deleteVolume(null);
Mockito.doReturn(null).when(mockVm).getVolumeInfo(null);
Mockito.doReturn(true).when(mockVm).checkVolumeAccess(null, null);
Mockito.doNothing().when(mockVm).setOwner(null, null);
Mockito.doReturn(null).when(mockVm).setOwner(null, null);
Mockito.doReturn(null).when(mockVm).listVolumes(null, null, null, 0);
HddsWhiteboxTestUtils.setInternalState(

View File

@ -24,11 +24,13 @@
import org.apache.hadoop.ipc.RemoteException;
import org.apache.hadoop.ozone.MiniOzoneCluster;
import org.apache.hadoop.ozone.MiniOzoneHAClusterImpl;
import org.apache.hadoop.ozone.OzoneTestUtils;
import org.apache.hadoop.ozone.client.ObjectStore;
import org.apache.hadoop.ozone.client.OzoneBucket;
import org.apache.hadoop.ozone.client.OzoneClient;
import org.apache.hadoop.ozone.client.io.OzoneInputStream;
import org.apache.hadoop.ozone.client.io.OzoneOutputStream;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.ha.OMFailoverProxyProvider;
import org.apache.hadoop.ozone.om.helpers.OmMultipartInfo;
import org.apache.hadoop.ozone.om.helpers.OmMultipartUploadCompleteInfo;
@ -123,6 +125,33 @@ public void shutdown() {
}
}
@Test
public void testAllVolumeOperations() throws Exception {
String userName = "user" + RandomStringUtils.randomNumeric(5);
String adminName = "admin" + RandomStringUtils.randomNumeric(5);
String volumeName = "volume" + RandomStringUtils.randomNumeric(5);
VolumeArgs createVolumeArgs = VolumeArgs.newBuilder()
.setOwner(userName)
.setAdmin(adminName)
.build();
objectStore.createVolume(volumeName, createVolumeArgs);
OzoneVolume retVolumeinfo = objectStore.getVolume(volumeName);
Assert.assertTrue(retVolumeinfo.getName().equals(volumeName));
Assert.assertTrue(retVolumeinfo.getOwner().equals(userName));
Assert.assertTrue(retVolumeinfo.getAdmin().equals(adminName));
objectStore.deleteVolume(volumeName);
OzoneTestUtils.expectOmException(OMException.ResultCodes.VOLUME_NOT_FOUND,
() -> objectStore.getVolume(volumeName));
OzoneTestUtils.expectOmException(OMException.ResultCodes.VOLUME_NOT_FOUND,
() -> objectStore.deleteVolume(volumeName));
}
/**
* Test a client request when all OM nodes are running. The request should
* succeed.

View File

@ -71,6 +71,8 @@
import org.apache.hadoop.ozone.OzoneIllegalArgumentException;
import org.apache.hadoop.ozone.OzoneSecurityUtil;
import org.apache.hadoop.ozone.om.ha.OMFailoverProxyProvider;
import org.apache.hadoop.ozone.om.helpers.OmDeleteVolumeResponse;
import org.apache.hadoop.ozone.om.helpers.OmVolumeOwnerChangeResponse;
import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
import org.apache.hadoop.ozone.om.protocol.OzoneManagerServerProtocol;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
@ -79,6 +81,8 @@
.KeyInfo;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.KeyLocation;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.VolumeList;
import org.apache.hadoop.ozone.security.OzoneSecurityException;
import org.apache.hadoop.ozone.security.OzoneTokenIdentifier;
import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
@ -1630,6 +1634,79 @@ public void createVolume(OmVolumeArgs args) throws IOException {
}
}
@Override
public VolumeList startCreateVolume(OmVolumeArgs args) throws IOException {
// TODO: Need to add metrics and Audit log for HA requests
if(isAclEnabled) {
checkAcls(ResourceType.VOLUME, StoreType.OZONE, ACLType.CREATE,
args.getVolume(), null, null);
}
VolumeList volumeList = volumeManager.createVolume(args);
return volumeList;
}
public void applyCreateVolume(OmVolumeArgs omVolumeArgs,
VolumeList volumeList) throws IOException {
// TODO: Need to add metrics and Audit log for HA requests
volumeManager.applyCreateVolume(omVolumeArgs, volumeList);
}
@Override
public OmVolumeOwnerChangeResponse startSetOwner(String volume,
String owner) throws IOException {
// TODO: Need to add metrics and Audit log for HA requests
if (isAclEnabled) {
checkAcls(ResourceType.VOLUME, StoreType.OZONE, ACLType.WRITE_ACL, volume,
null, null);
}
return volumeManager.setOwner(volume, owner);
}
@Override
public void applySetOwner(String oldOwner, VolumeList oldOwnerVolumeList,
VolumeList newOwnerVolumeList, OmVolumeArgs newOwnerVolumeArgs)
throws IOException {
// TODO: Need to add metrics and Audit log for HA requests
volumeManager.applySetOwner(oldOwner, oldOwnerVolumeList,
newOwnerVolumeList, newOwnerVolumeArgs);
}
@Override
public OmVolumeArgs startSetQuota(String volume, long quota)
throws IOException {
// TODO: Need to add metrics and Audit log for HA requests
if (isAclEnabled) {
checkAcls(ResourceType.VOLUME, StoreType.OZONE, ACLType.WRITE_ACL, volume,
null, null);
}
return volumeManager.setQuota(volume, quota);
}
@Override
public void applySetQuota(OmVolumeArgs omVolumeArgs) throws IOException {
// TODO: Need to add metrics and Audit log for HA requests
volumeManager.applySetQuota(omVolumeArgs);
}
@Override
public OmDeleteVolumeResponse startDeleteVolume(String volume)
throws IOException {
if(isAclEnabled) {
checkAcls(ResourceType.VOLUME, StoreType.OZONE, ACLType.DELETE, volume,
null, null);
}
// TODO: Need to add metrics and Audit log for HA requests
return volumeManager.deleteVolume(volume);
}
@Override
public void applyDeleteVolume(String volume, String owner,
VolumeList newVolumeList) throws IOException {
// TODO: Need to add metrics and Audit log for HA requests
volumeManager.applyDeleteVolume(volume, owner, newVolumeList);
}
/**
* Checks if current caller has acl permissions.
*

View File

@ -50,6 +50,7 @@ public class S3BucketManagerImpl implements S3BucketManager {
private final OMMetadataManager omMetadataManager;
private final VolumeManager volumeManager;
private final BucketManager bucketManager;
private final boolean isRatisEnabled;
/**
* Construct an S3 Bucket Manager Object.
@ -66,6 +67,9 @@ public S3BucketManagerImpl(
this.omMetadataManager = omMetadataManager;
this.volumeManager = volumeManager;
this.bucketManager = bucketManager;
isRatisEnabled = configuration.getBoolean(
OMConfigKeys.OZONE_OM_RATIS_ENABLE_KEY,
OMConfigKeys.OZONE_OM_RATIS_ENABLE_DEFAULT);
}
@Override
@ -166,7 +170,12 @@ public boolean createOzoneVolumeIfNeeded(String userName)
.setVolume(ozoneVolumeName)
.setQuotaInBytes(OzoneConsts.MAX_QUOTA_IN_BYTES)
.build();
volumeManager.createVolume(args);
if (isRatisEnabled) {
// When ratis is enabled we need to call apply also.
volumeManager.applyCreateVolume(args, volumeManager.createVolume(args));
} else {
volumeManager.createVolume(args);
}
} catch (OMException exp) {
newVolumeCreate = false;
if (exp.getResult().compareTo(VOLUME_ALREADY_EXISTS) == 0) {

View File

@ -16,9 +16,13 @@
*/
package org.apache.hadoop.ozone.om;
import org.apache.hadoop.ozone.om.helpers.OmDeleteVolumeResponse;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OmVolumeOwnerChangeResponse;
import org.apache.hadoop.ozone.protocol.proto
.OzoneManagerProtocolProtos.OzoneAclInfo;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.VolumeList;
import java.io.IOException;
import java.util.List;
@ -32,7 +36,17 @@ public interface VolumeManager {
* Create a new volume.
* @param args - Volume args to create a volume
*/
void createVolume(OmVolumeArgs args) throws IOException;
VolumeList createVolume(OmVolumeArgs args)
throws IOException;
/**
* Apply Create Volume changes to OM DB.
* @param omVolumeArgs
* @param volumeList
* @throws IOException
*/
void applyCreateVolume(OmVolumeArgs omVolumeArgs,
VolumeList volumeList) throws IOException;
/**
* Changes the owner of a volume.
@ -41,7 +55,20 @@ public interface VolumeManager {
* @param owner - Name of the owner.
* @throws IOException
*/
void setOwner(String volume, String owner) throws IOException;
OmVolumeOwnerChangeResponse setOwner(String volume, String owner)
throws IOException;
/**
* Apply Set Owner changes to OM DB.
* @param oldOwner
* @param oldOwnerVolumeList
* @param newOwnerVolumeList
* @param newOwnerVolumeArgs
* @throws IOException
*/
void applySetOwner(String oldOwner, VolumeList oldOwnerVolumeList,
VolumeList newOwnerVolumeList, OmVolumeArgs newOwnerVolumeArgs)
throws IOException;
/**
* Changes the Quota on a volume.
@ -50,7 +77,14 @@ public interface VolumeManager {
* @param quota - Quota in bytes.
* @throws IOException
*/
void setQuota(String volume, long quota) throws IOException;
OmVolumeArgs setQuota(String volume, long quota) throws IOException;
/**
* Apply Set Quota changes to OM DB.
* @param omVolumeArgs
* @throws IOException
*/
void applySetQuota(OmVolumeArgs omVolumeArgs) throws IOException;
/**
* Gets the volume information.
@ -66,7 +100,17 @@ public interface VolumeManager {
* @param volume - Name of the volume.
* @throws IOException
*/
void deleteVolume(String volume) throws IOException;
OmDeleteVolumeResponse deleteVolume(String volume) throws IOException;
/**
* Apply Delete Volume changes to OM DB.
* @param volume
* @param owner
* @param newVolumeList
* @throws IOException
*/
void applyDeleteVolume(String volume, String owner,
VolumeList newVolumeList) throws IOException;
/**
* Checks if the specified user with a role can access this volume.

View File

@ -22,17 +22,18 @@
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.OmDeleteVolumeResponse;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OmVolumeOwnerChangeResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneAclInfo;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.VolumeList;
import org.apache.hadoop.utils.RocksDBStore;
import org.apache.hadoop.utils.db.BatchOperation;
import com.google.common.base.Preconditions;
import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_USER_MAX_VOLUME;
import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_USER_MAX_VOLUME_DEFAULT;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes;
import org.rocksdb.RocksDBException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -45,6 +46,7 @@ public class VolumeManagerImpl implements VolumeManager {
private final OMMetadataManager metadataManager;
private final int maxUserVolumeCount;
private final boolean isRatisEnabled;
/**
* Constructor.
@ -52,15 +54,18 @@ public class VolumeManagerImpl implements VolumeManager {
* @throws IOException
*/
public VolumeManagerImpl(OMMetadataManager metadataManager,
OzoneConfiguration conf) throws IOException {
OzoneConfiguration conf) {
this.metadataManager = metadataManager;
this.maxUserVolumeCount = conf.getInt(OZONE_OM_USER_MAX_VOLUME,
OZONE_OM_USER_MAX_VOLUME_DEFAULT);
isRatisEnabled = conf.getBoolean(
OMConfigKeys.OZONE_OM_RATIS_ENABLE_KEY,
OMConfigKeys.OZONE_OM_RATIS_ENABLE_DEFAULT);
}
// Helpers to add and delete volume from user list
private void addVolumeToOwnerList(String volume, String owner,
BatchOperation batchOperation) throws IOException {
private VolumeList addVolumeToOwnerList(String volume, String owner)
throws IOException {
// Get the volume list
String dbUserKey = metadataManager.getUserKey(owner);
VolumeList volumeList = metadataManager.getUserTable().get(dbUserKey);
@ -72,22 +77,22 @@ private void addVolumeToOwnerList(String volume, String owner,
// Check the volume count
if (prevVolList.size() >= maxUserVolumeCount) {
LOG.debug("Too many volumes for user:{}", owner);
throw new OMException(ResultCodes.USER_TOO_MANY_VOLUMES);
throw new OMException("Too many volumes for user:" + owner,
ResultCodes.USER_TOO_MANY_VOLUMES);
}
// Add the new volume to the list
prevVolList.add(volume);
VolumeList newVolList = VolumeList.newBuilder()
.addAllVolumeNames(prevVolList).build();
metadataManager.getUserTable().putWithBatch(batchOperation,
dbUserKey, newVolList);
return newVolList;
}
private void delVolumeFromOwnerList(String volume, String owner,
BatchOperation batch) throws RocksDBException, IOException {
private VolumeList delVolumeFromOwnerList(String volume, String owner)
throws IOException {
// Get the volume list
String dbUserKey = metadataManager.getUserKey(owner);
VolumeList volumeList = metadataManager.getUserTable().get(dbUserKey);
VolumeList volumeList = metadataManager.getUserTable().get(owner);
List<String> prevVolList = new ArrayList<>();
if (volumeList != null) {
prevVolList.addAll(volumeList.getVolumeNamesList());
@ -98,58 +103,90 @@ private void delVolumeFromOwnerList(String volume, String owner,
// Remove the volume from the list
prevVolList.remove(volume);
if (prevVolList.size() == 0) {
metadataManager.getUserTable().deleteWithBatch(batch, dbUserKey);
} else {
VolumeList newVolList = VolumeList.newBuilder()
.addAllVolumeNames(prevVolList).build();
metadataManager.getUserTable().putWithBatch(batch,
dbUserKey, newVolList);
}
VolumeList newVolList = VolumeList.newBuilder()
.addAllVolumeNames(prevVolList).build();
return newVolList;
}
/**
* Creates a volume.
* @param args - OmVolumeArgs.
* @param omVolumeArgs - OmVolumeArgs.
* @return VolumeList
*/
@Override
public void createVolume(OmVolumeArgs args) throws IOException {
Preconditions.checkNotNull(args);
metadataManager.getLock().acquireUserLock(args.getOwnerName());
metadataManager.getLock().acquireVolumeLock(args.getVolume());
public VolumeList createVolume(OmVolumeArgs omVolumeArgs) throws IOException {
Preconditions.checkNotNull(omVolumeArgs);
metadataManager.getLock().acquireUserLock(omVolumeArgs.getOwnerName());
metadataManager.getLock().acquireVolumeLock(omVolumeArgs.getVolume());
try {
String dbVolumeKey = metadataManager.getVolumeKey(args.getVolume());
String dbVolumeKey = metadataManager.getVolumeKey(
omVolumeArgs.getVolume());
String dbUserKey = metadataManager.getUserKey(
omVolumeArgs.getOwnerName());
OmVolumeArgs volumeInfo =
metadataManager.getVolumeTable().get(dbVolumeKey);
// Check of the volume already exists
if (volumeInfo != null) {
LOG.debug("volume:{} already exists", args.getVolume());
LOG.debug("volume:{} already exists", omVolumeArgs.getVolume());
throw new OMException(ResultCodes.VOLUME_ALREADY_EXISTS);
}
try (BatchOperation batch = metadataManager.getStore()
.initBatchOperation()) {
// Write the vol info
metadataManager.getVolumeTable().putWithBatch(batch,
dbVolumeKey, args);
VolumeList volumeList = addVolumeToOwnerList(omVolumeArgs.getVolume(),
omVolumeArgs.getOwnerName());
// Add volume to user list
addVolumeToOwnerList(args.getVolume(), args.getOwnerName(), batch);
metadataManager.getStore().commitBatchOperation(batch);
// Set creation time
omVolumeArgs.setCreationTime(System.currentTimeMillis());
if (!isRatisEnabled) {
createVolumeCommitToDB(omVolumeArgs, volumeList, dbVolumeKey,
dbUserKey);
}
LOG.debug("created volume:{} user:{}", args.getVolume(),
args.getOwnerName());
LOG.debug("created volume:{} user:{}", omVolumeArgs.getVolume(),
omVolumeArgs.getOwnerName());
return volumeList;
} catch (IOException ex) {
if (!(ex instanceof OMException)) {
LOG.error("Volume creation failed for user:{} volume:{}",
args.getOwnerName(), args.getVolume(), ex);
} else {
throw (IOException) ex;
omVolumeArgs.getOwnerName(), omVolumeArgs.getVolume(), ex);
}
throw ex;
} finally {
metadataManager.getLock().releaseVolumeLock(args.getVolume());
metadataManager.getLock().releaseUserLock(args.getOwnerName());
metadataManager.getLock().releaseVolumeLock(omVolumeArgs.getVolume());
metadataManager.getLock().releaseUserLock(omVolumeArgs.getOwnerName());
}
}
@Override
public void applyCreateVolume(OmVolumeArgs omVolumeArgs,
VolumeList volumeList) throws IOException {
// Do we need to hold lock in apply Transactions requests?
String dbVolumeKey = metadataManager.getVolumeKey(omVolumeArgs.getVolume());
String dbUserKey = metadataManager.getUserKey(omVolumeArgs.getOwnerName());
try {
createVolumeCommitToDB(omVolumeArgs, volumeList, dbVolumeKey, dbUserKey);
} catch (IOException ex) {
LOG.error("Volume creation failed for user:{} volume:{}",
omVolumeArgs.getOwnerName(), omVolumeArgs.getVolume(), ex);
throw ex;
}
}
private void createVolumeCommitToDB(OmVolumeArgs omVolumeArgs,
VolumeList volumeList, String dbVolumeKey, String dbUserKey)
throws IOException {
try (BatchOperation batch = metadataManager.getStore()
.initBatchOperation()) {
// Write the vol info
metadataManager.getVolumeTable().putWithBatch(batch, dbVolumeKey,
omVolumeArgs);
metadataManager.getUserTable().putWithBatch(batch, dbUserKey,
volumeList);
// Add volume to user list
metadataManager.getStore().commitBatchOperation(batch);
} catch (IOException ex) {
throw ex;
}
}
@ -161,7 +198,8 @@ public void createVolume(OmVolumeArgs args) throws IOException {
* @throws IOException
*/
@Override
public void setOwner(String volume, String owner) throws IOException {
public OmVolumeOwnerChangeResponse setOwner(String volume, String owner)
throws IOException {
Preconditions.checkNotNull(volume);
Preconditions.checkNotNull(owner);
metadataManager.getLock().acquireUserLock(owner);
@ -179,49 +217,84 @@ public void setOwner(String volume, String owner) throws IOException {
Preconditions.checkState(volume.equals(volumeArgs.getVolume()));
try (BatchOperation batch = metadataManager.getStore()
.initBatchOperation()) {
delVolumeFromOwnerList(volume, volumeArgs.getOwnerName(), batch);
addVolumeToOwnerList(volume, owner, batch);
String originalOwner =
metadataManager.getUserKey(volumeArgs.getOwnerName());
VolumeList oldOwnerVolumeList = delVolumeFromOwnerList(volume,
originalOwner);
OmVolumeArgs newVolumeArgs =
OmVolumeArgs.newBuilder().setVolume(volumeArgs.getVolume())
.setAdminName(volumeArgs.getAdminName())
.setOwnerName(owner)
.setQuotaInBytes(volumeArgs.getQuotaInBytes())
.setCreationTime(volumeArgs.getCreationTime())
.build();
String newOwner = metadataManager.getUserKey(owner);
VolumeList newOwnerVolumeList = addVolumeToOwnerList(volume, newOwner);
metadataManager.getVolumeTable().putWithBatch(batch,
dbVolumeKey, newVolumeArgs);
metadataManager.getStore().commitBatchOperation(batch);
volumeArgs.setOwnerName(owner);
if (!isRatisEnabled) {
setOwnerCommitToDB(oldOwnerVolumeList, newOwnerVolumeList,
volumeArgs, owner);
}
} catch (RocksDBException | IOException ex) {
return new OmVolumeOwnerChangeResponse(oldOwnerVolumeList,
newOwnerVolumeList, volumeArgs, originalOwner);
} catch (IOException ex) {
if (!(ex instanceof OMException)) {
LOG.error("Changing volume ownership failed for user:{} volume:{}",
owner, volume, ex);
}
if(ex instanceof RocksDBException) {
throw RocksDBStore.toIOException("Volume creation failed.",
(RocksDBException) ex);
} else {
throw (IOException) ex;
}
throw ex;
} finally {
metadataManager.getLock().releaseVolumeLock(volume);
metadataManager.getLock().releaseUserLock(owner);
}
}
@Override
public void applySetOwner(String oldOwner, VolumeList oldOwnerVolumeList,
VolumeList newOwnerVolumeList, OmVolumeArgs newOwnerVolumeArgs)
throws IOException {
try {
setOwnerCommitToDB(oldOwnerVolumeList, newOwnerVolumeList,
newOwnerVolumeArgs, oldOwner);
} catch (IOException ex) {
LOG.error("Changing volume ownership failed for user:{} volume:{}",
newOwnerVolumeArgs.getOwnerName(), newOwnerVolumeArgs.getVolume(),
ex);
throw ex;
}
}
private void setOwnerCommitToDB(VolumeList oldOwnerVolumeList,
VolumeList newOwnerVolumeList, OmVolumeArgs newOwnerVolumeArgs,
String oldOwner) throws IOException {
try (BatchOperation batch = metadataManager.getStore()
.initBatchOperation()) {
if (oldOwnerVolumeList.getVolumeNamesList().size() == 0) {
metadataManager.getUserTable().deleteWithBatch(batch, oldOwner);
} else {
metadataManager.getUserTable().putWithBatch(batch, oldOwner,
oldOwnerVolumeList);
}
metadataManager.getUserTable().putWithBatch(batch,
newOwnerVolumeArgs.getOwnerName(),
newOwnerVolumeList);
String dbVolumeKey =
metadataManager.getVolumeKey(newOwnerVolumeArgs.getVolume());
metadataManager.getVolumeTable().putWithBatch(batch,
dbVolumeKey, newOwnerVolumeArgs);
metadataManager.getStore().commitBatchOperation(batch);
}
}
/**
* Changes the Quota on a volume.
*
* @param volume - Name of the volume.
* @param quota - Quota in bytes.
*
* @return OmVolumeArgs
* @throws IOException
*/
@Override
public void setQuota(String volume, long quota) throws IOException {
public OmVolumeArgs setQuota(String volume, long quota) throws IOException {
Preconditions.checkNotNull(volume);
metadataManager.getLock().acquireVolumeLock(volume);
try {
@ -235,15 +308,13 @@ public void setQuota(String volume, long quota) throws IOException {
Preconditions.checkState(volume.equals(volumeArgs.getVolume()));
OmVolumeArgs newVolumeArgs =
OmVolumeArgs.newBuilder()
.setVolume(volumeArgs.getVolume())
.setAdminName(volumeArgs.getAdminName())
.setOwnerName(volumeArgs.getOwnerName())
.setQuotaInBytes(quota)
.setCreationTime(volumeArgs.getCreationTime()).build();
metadataManager.getVolumeTable().put(dbVolumeKey, newVolumeArgs);
volumeArgs.setQuotaInBytes(quota);
if (!isRatisEnabled) {
metadataManager.getVolumeTable().put(dbVolumeKey, volumeArgs);
}
return volumeArgs;
} catch (IOException ex) {
if (!(ex instanceof OMException)) {
LOG.error("Changing volume quota failed for volume:{} quota:{}", volume,
@ -255,6 +326,19 @@ public void setQuota(String volume, long quota) throws IOException {
}
}
@Override
public void applySetQuota(OmVolumeArgs omVolumeArgs) throws IOException {
try {
String dbVolumeKey = metadataManager.getVolumeKey(
omVolumeArgs.getVolume());
metadataManager.getVolumeTable().put(dbVolumeKey, omVolumeArgs);
} catch (IOException ex) {
LOG.error("Changing volume quota failed for volume:{} quota:{}",
omVolumeArgs.getVolume(), omVolumeArgs.getQuotaInBytes(), ex);
throw ex;
}
}
/**
* Gets the volume information.
* @param volume - Volume name.
@ -290,10 +374,12 @@ public OmVolumeArgs getVolumeInfo(String volume) throws IOException {
* Deletes an existing empty volume.
*
* @param volume - Name of the volume.
*
* @return OmDeleteVolumeResponse
* @throws IOException
*/
@Override
public void deleteVolume(String volume) throws IOException {
public OmDeleteVolumeResponse deleteVolume(String volume) throws IOException {
Preconditions.checkNotNull(volume);
String owner;
metadataManager.getLock().acquireVolumeLock(volume);
@ -305,7 +391,6 @@ public void deleteVolume(String volume) throws IOException {
metadataManager.getLock().acquireUserLock(owner);
metadataManager.getLock().acquireVolumeLock(volume);
try {
String dbVolumeKey = metadataManager.getVolumeKey(volume);
OmVolumeArgs volumeArgs =
metadataManager.getVolumeTable().get(dbVolumeKey);
@ -322,28 +407,54 @@ public void deleteVolume(String volume) throws IOException {
Preconditions.checkState(volume.equals(volumeArgs.getVolume()));
// delete the volume from the owner list
// as well as delete the volume entry
try (BatchOperation batch = metadataManager.getStore()
.initBatchOperation()) {
delVolumeFromOwnerList(volume, volumeArgs.getOwnerName(), batch);
metadataManager.getVolumeTable().deleteWithBatch(batch, dbVolumeKey);
metadataManager.getStore().commitBatchOperation(batch);
VolumeList newVolumeList = delVolumeFromOwnerList(volume,
volumeArgs.getOwnerName());
if (!isRatisEnabled) {
deleteVolumeCommitToDB(newVolumeList,
volume, owner);
}
} catch (RocksDBException| IOException ex) {
return new OmDeleteVolumeResponse(volume, owner, newVolumeList);
} catch (IOException ex) {
if (!(ex instanceof OMException)) {
LOG.error("Delete volume failed for volume:{}", volume, ex);
}
if(ex instanceof RocksDBException) {
throw RocksDBStore.toIOException("Volume creation failed.",
(RocksDBException) ex);
} else {
throw (IOException) ex;
}
throw ex;
} finally {
metadataManager.getLock().releaseVolumeLock(volume);
metadataManager.getLock().releaseUserLock(owner);
}
}
@Override
public void applyDeleteVolume(String volume, String owner,
VolumeList newVolumeList) throws IOException {
try {
deleteVolumeCommitToDB(newVolumeList, volume, owner);
} catch (IOException ex) {
LOG.error("Delete volume failed for volume:{}", volume,
ex);
throw ex;
}
}
private void deleteVolumeCommitToDB(VolumeList newVolumeList,
String volume, String owner) throws IOException {
try (BatchOperation batch = metadataManager.getStore()
.initBatchOperation()) {
String dbUserKey = metadataManager.getUserKey(owner);
if (newVolumeList.getVolumeNamesList().size() == 0) {
metadataManager.getUserTable().deleteWithBatch(batch, dbUserKey);
} else {
metadataManager.getUserTable().putWithBatch(batch, dbUserKey,
newVolumeList);
}
metadataManager.getVolumeTable().deleteWithBatch(batch,
metadataManager.getVolumeKey(volume));
metadataManager.getStore().commitBatchOperation(batch);
}
}
/**
* Checks if the specified user with a role can access this volume.
*

View File

@ -27,6 +27,7 @@
import org.apache.hadoop.ozone.container.common.transport.server.ratis
.ContainerStateMachine;
import org.apache.hadoop.ozone.om.OzoneManager;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.OMRatisHelper;
import org.apache.hadoop.ozone.om.protocol.OzoneManagerServerProtocol;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
@ -36,8 +37,8 @@
.OMRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.OMResponse;
import org.apache.hadoop.ozone.protocolPB.OzoneManagerRequestHandler;
import org.apache.hadoop.ozone.protocolPB.RequestHandler;
import org.apache.hadoop.ozone.protocolPB.OzoneManagerHARequestHandler;
import org.apache.hadoop.ozone.protocolPB.OzoneManagerHARequestHandlerImpl;
import org.apache.hadoop.util.Time;
import org.apache.ratis.proto.RaftProtos;
import org.apache.ratis.protocol.Message;
@ -67,14 +68,14 @@ public class OzoneManagerStateMachine extends BaseStateMachine {
new SimpleStateMachineStorage();
private final OzoneManagerRatisServer omRatisServer;
private final OzoneManagerServerProtocol ozoneManager;
private RequestHandler handler;
private OzoneManagerHARequestHandler handler;
private RaftGroupId raftGroupId;
private long lastAppliedIndex = 0;
public OzoneManagerStateMachine(OzoneManagerRatisServer ratisServer) {
this.omRatisServer = ratisServer;
this.ozoneManager = omRatisServer.getOzoneManager();
this.handler = new OzoneManagerRequestHandler(ozoneManager);
this.handler = new OzoneManagerHARequestHandlerImpl(ozoneManager);
}
/**
@ -185,21 +186,53 @@ public void notifyNotLeader(Collection<TransactionContext> pendingEntries)
private TransactionContext handleStartTransactionRequests(
RaftClientRequest raftClientRequest, OMRequest omRequest) {
switch (omRequest.getCmdType()) {
case AllocateBlock:
return handleAllocateBlock(raftClientRequest, omRequest);
case CreateKey:
return handleCreateKeyRequest(raftClientRequest, omRequest);
case InitiateMultiPartUpload:
return handleInitiateMultipartUpload(raftClientRequest, omRequest);
default:
return TransactionContext.newBuilder()
OMRequest newOmRequest = null;
try {
switch (omRequest.getCmdType()) {
case CreateVolume:
case SetVolumeProperty:
case DeleteVolume:
newOmRequest = handler.handleStartTransaction(omRequest);
break;
case AllocateBlock:
return handleAllocateBlock(raftClientRequest, omRequest);
case CreateKey:
return handleCreateKeyRequest(raftClientRequest, omRequest);
case InitiateMultiPartUpload:
return handleInitiateMultipartUpload(raftClientRequest, omRequest);
default:
return TransactionContext.newBuilder()
.setClientRequest(raftClientRequest)
.setStateMachine(this)
.setServerRole(RaftProtos.RaftPeerRole.LEADER)
.setLogData(raftClientRequest.getMessage().getContent())
.build();
}
} catch (IOException ex) {
TransactionContext transactionContext = TransactionContext.newBuilder()
.setClientRequest(raftClientRequest)
.setStateMachine(this)
.setServerRole(RaftProtos.RaftPeerRole.LEADER)
.setLogData(raftClientRequest.getMessage().getContent())
.build();
if (ex instanceof OMException) {
IOException ioException =
new IOException(ex.getMessage() + STATUS_CODE +
((OMException) ex).getResult());
transactionContext.setException(ioException);
} else {
transactionContext.setException(ex);
}
LOG.error("Exception in startTransaction for cmdType " +
omRequest.getCmdType(), ex);
return transactionContext;
}
TransactionContext transactionContext = TransactionContext.newBuilder()
.setClientRequest(raftClientRequest)
.setStateMachine(this)
.setServerRole(RaftProtos.RaftPeerRole.LEADER)
.setLogData(OMRatisHelper.convertRequestToByteString(newOmRequest))
.build();
return transactionContext;
}
private TransactionContext handleInitiateMultipartUpload(
@ -367,7 +400,7 @@ private IOException constructExceptionForFailedRequest(
* @throws ServiceException
*/
private Message runCommand(OMRequest request, long trxLogIndex) {
OMResponse response = handler.handle(request);
OMResponse response = handler.handleApplyTransaction(request);
lastAppliedIndex = trxLogIndex;
return OMRatisHelper.convertResponseToMessage(response);
}
@ -394,7 +427,7 @@ private static <T> CompletableFuture<T> completeExceptionally(Exception e) {
}
@VisibleForTesting
public void setHandler(RequestHandler handler) {
public void setHandler(OzoneManagerHARequestHandler handler) {
this.handler = handler;
}

View File

@ -0,0 +1,48 @@
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.protocolPB;
import java.io.IOException;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.OMRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.OMResponse;
/**
* Handler to handle OM requests in OM HA.
*/
public interface OzoneManagerHARequestHandler extends RequestHandler {
/**
* Handle start Transaction Requests from OzoneManager StateMachine.
* @param omRequest
* @return OMRequest - New OM Request which will be applied during apply
* Transaction
* @throws IOException
*/
OMRequest handleStartTransaction(OMRequest omRequest) throws IOException;
/**
* Handle Apply Transaction Requests from OzoneManager StateMachine.
* @param omRequest
* @return OMResponse
*/
OMResponse handleApplyTransaction(OMRequest omRequest);
}

View File

@ -0,0 +1,247 @@
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.protocolPB;
import java.io.IOException;
import org.apache.hadoop.ozone.om.helpers.OmDeleteVolumeResponse;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OmVolumeOwnerChangeResponse;
import org.apache.hadoop.ozone.om.protocol.OzoneManagerServerProtocol;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.CreateVolumeRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.CreateVolumeResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.DeleteVolumeRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.DeleteVolumeResponse;
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
.SetVolumePropertyRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.SetVolumePropertyResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.Status;
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
.VolumeList;
/**
* Command Handler for OM requests. OM State Machine calls this handler for
* deserializing the client request and sending it to OM.
*/
public class OzoneManagerHARequestHandlerImpl
extends OzoneManagerRequestHandler implements OzoneManagerHARequestHandler {
public OzoneManagerHARequestHandlerImpl(OzoneManagerServerProtocol om) {
super(om);
}
@Override
public OMRequest handleStartTransaction(OMRequest omRequest)
throws IOException {
LOG.debug("Received OMRequest: {}, ", omRequest);
Type cmdType = omRequest.getCmdType();
OMRequest newOmRequest = null;
switch (cmdType) {
case CreateVolume:
newOmRequest = handleCreateVolumeStart(omRequest);
break;
case SetVolumeProperty:
newOmRequest = handleSetVolumePropertyStart(omRequest);
break;
case DeleteVolume:
newOmRequest = handleDeleteVolumeStart(omRequest);
break;
default:
throw new IOException("Unrecognized Command Type:" + cmdType);
}
return newOmRequest;
}
@Override
public OMResponse handleApplyTransaction(OMRequest omRequest) {
LOG.debug("Received OMRequest: {}, ", omRequest);
Type cmdType = omRequest.getCmdType();
OMResponse.Builder responseBuilder =
OMResponse.newBuilder().setCmdType(cmdType)
.setStatus(Status.OK);
try {
switch (cmdType) {
case CreateVolume:
responseBuilder.setCreateVolumeResponse(
handleCreateVolumeApply(omRequest));
break;
case SetVolumeProperty:
responseBuilder.setSetVolumePropertyResponse(
handleSetVolumePropertyApply(omRequest));
break;
case DeleteVolume:
responseBuilder.setDeleteVolumeResponse(
handleDeleteVolumeApply(omRequest));
break;
default:
// As all request types are not changed so we need to call handle
// here.
return handle(omRequest);
}
responseBuilder.setSuccess(true);
} catch (IOException ex) {
responseBuilder.setSuccess(false);
responseBuilder.setStatus(exceptionToResponseStatus(ex));
if (ex.getMessage() != null) {
responseBuilder.setMessage(ex.getMessage());
}
}
return responseBuilder.build();
}
private OMRequest handleCreateVolumeStart(OMRequest omRequest)
throws IOException {
VolumeInfo volumeInfo = omRequest.getCreateVolumeRequest().getVolumeInfo();
OzoneManagerProtocolProtos.VolumeList volumeList =
getOzoneManagerServerProtocol().startCreateVolume(
OmVolumeArgs.getFromProtobuf(volumeInfo));
CreateVolumeRequest createVolumeRequest =
CreateVolumeRequest.newBuilder().setVolumeInfo(volumeInfo)
.setVolumeList(volumeList).build();
return omRequest.toBuilder().setCreateVolumeRequest(createVolumeRequest)
.build();
}
private CreateVolumeResponse handleCreateVolumeApply(OMRequest omRequest)
throws IOException {
OzoneManagerProtocolProtos.VolumeInfo volumeInfo =
omRequest.getCreateVolumeRequest().getVolumeInfo();
VolumeList volumeList =
omRequest.getCreateVolumeRequest().getVolumeList();
getOzoneManagerServerProtocol().applyCreateVolume(
OmVolumeArgs.getFromProtobuf(volumeInfo),
volumeList);
return CreateVolumeResponse.newBuilder().build();
}
private OMRequest handleSetVolumePropertyStart(OMRequest omRequest)
throws IOException {
SetVolumePropertyRequest setVolumePropertyRequest =
omRequest.getSetVolumePropertyRequest();
String volume = setVolumePropertyRequest.getVolumeName();
OMRequest newOmRequest = null;
if (setVolumePropertyRequest.hasQuotaInBytes()) {
long quota = setVolumePropertyRequest.getQuotaInBytes();
OmVolumeArgs omVolumeArgs =
getOzoneManagerServerProtocol().startSetQuota(volume, quota);
SetVolumePropertyRequest newSetVolumePropertyRequest =
SetVolumePropertyRequest.newBuilder().setVolumeName(volume)
.setVolumeInfo(omVolumeArgs.getProtobuf()).build();
newOmRequest =
omRequest.toBuilder().setSetVolumePropertyRequest(
newSetVolumePropertyRequest).build();
} else {
String owner = setVolumePropertyRequest.getOwnerName();
OmVolumeOwnerChangeResponse omVolumeOwnerChangeResponse =
getOzoneManagerServerProtocol().startSetOwner(volume, owner);
// If volumeLists become large and as ratis writes the request to disk we
// might take more space if the lists become very big in size. We might
// need to revisit this if it becomes problem
SetVolumePropertyRequest newSetVolumePropertyRequest =
SetVolumePropertyRequest.newBuilder().setVolumeName(volume)
.setOwnerName(owner)
.setOriginalOwner(omVolumeOwnerChangeResponse.getOriginalOwner())
.setNewOwnerVolumeList(
omVolumeOwnerChangeResponse.getNewOwnerVolumeList())
.setOldOwnerVolumeList(
omVolumeOwnerChangeResponse.getOriginalOwnerVolumeList())
.setVolumeInfo(
omVolumeOwnerChangeResponse.getNewOwnerVolumeArgs()
.getProtobuf()).build();
newOmRequest =
omRequest.toBuilder().setSetVolumePropertyRequest(
newSetVolumePropertyRequest).build();
}
return newOmRequest;
}
private SetVolumePropertyResponse handleSetVolumePropertyApply(
OMRequest omRequest) throws IOException {
SetVolumePropertyRequest setVolumePropertyRequest =
omRequest.getSetVolumePropertyRequest();
if (setVolumePropertyRequest.hasQuotaInBytes()) {
getOzoneManagerServerProtocol().applySetQuota(
OmVolumeArgs.getFromProtobuf(
setVolumePropertyRequest.getVolumeInfo()));
} else {
getOzoneManagerServerProtocol().applySetOwner(
setVolumePropertyRequest.getOriginalOwner(),
setVolumePropertyRequest.getOldOwnerVolumeList(),
setVolumePropertyRequest.getNewOwnerVolumeList(),
OmVolumeArgs.getFromProtobuf(
setVolumePropertyRequest.getVolumeInfo()));
}
return SetVolumePropertyResponse.newBuilder().build();
}
private OMRequest handleDeleteVolumeStart(OMRequest omRequest)
throws IOException {
DeleteVolumeRequest deleteVolumeRequest =
omRequest.getDeleteVolumeRequest();
String volume = deleteVolumeRequest.getVolumeName();
OmDeleteVolumeResponse omDeleteVolumeResponse =
getOzoneManagerServerProtocol().startDeleteVolume(volume);
DeleteVolumeRequest newDeleteVolumeRequest =
DeleteVolumeRequest.newBuilder().setVolumeList(
omDeleteVolumeResponse.getUpdatedVolumeList())
.setVolumeName(omDeleteVolumeResponse.getVolume())
.setOwner(omDeleteVolumeResponse.getOwner()).build();
return omRequest.toBuilder().setDeleteVolumeRequest(
newDeleteVolumeRequest).build();
}
private DeleteVolumeResponse handleDeleteVolumeApply(OMRequest omRequest)
throws IOException {
DeleteVolumeRequest deleteVolumeRequest =
omRequest.getDeleteVolumeRequest();
getOzoneManagerServerProtocol().applyDeleteVolume(
deleteVolumeRequest.getVolumeName(), deleteVolumeRequest.getOwner(),
deleteVolumeRequest.getVolumeList());
return DeleteVolumeResponse.newBuilder().build();
}
}

View File

@ -364,7 +364,7 @@ public OMResponse handle(OMRequest request) {
}
// Convert and exception to corresponding status code
private Status exceptionToResponseStatus(IOException ex) {
protected Status exceptionToResponseStatus(IOException ex) {
if (ex instanceof OMException) {
return Status.values()[((OMException) ex).getResult().ordinal()];
} else {
@ -1027,4 +1027,8 @@ private OzoneManagerProtocolProtos.LookupFileResponse lookupFile(
.setKeyInfo(impl.lookupFile(omKeyArgs).getProtobuf())
.build();
}
protected OzoneManagerServerProtocol getOzoneManagerServerProtocol() {
return impl;
}
}

View File

@ -28,7 +28,6 @@
*/
public interface RequestHandler {
/**
* Handle the OmRequest, and returns OmResponse.
* @param request
@ -36,6 +35,7 @@ public interface RequestHandler {
*/
OMResponse handle(OMRequest request);
/**
* Validates that the incoming OM request has required parameters.
* TODO: Add more validation checks before writing the request to Ratis log.

View File

@ -39,8 +39,8 @@
.OMRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.OMResponse;
import org.apache.hadoop.ozone.protocolPB.OzoneManagerRequestHandler;
import org.apache.hadoop.ozone.protocolPB.RequestHandler;
import org.apache.hadoop.ozone.protocolPB.OzoneManagerHARequestHandler;
import org.apache.hadoop.ozone.protocolPB.OzoneManagerHARequestHandlerImpl;
import org.apache.ratis.proto.RaftProtos;
import org.apache.ratis.protocol.ClientId;
import org.apache.ratis.protocol.Message;
@ -72,7 +72,7 @@ public class TestOzoneManagerStateMachine {
private OzoneConfiguration conf;
private OzoneManagerRatisServer omRatisServer;
private String omID;
private RequestHandler requestHandler;
private OzoneManagerHARequestHandler requestHandler;
private RaftGroupId raftGroupId;
private OzoneManagerStateMachine ozoneManagerStateMachine;
@ -105,7 +105,7 @@ public void setup() throws Exception {
ozoneManagerStateMachine =
new OzoneManagerStateMachine(omRatisServer);
requestHandler = Mockito.mock(OzoneManagerRequestHandler.class);
requestHandler = Mockito.mock(OzoneManagerHARequestHandlerImpl.class);
raftGroupId = omRatisServer.getRaftGroup().getGroupId();
ozoneManagerStateMachine.setHandler(requestHandler);