This is an automated email from the ASF dual-hosted git repository. xyao pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/hadoop.git
The following commit(s) were added to refs/heads/trunk by this push: new 3ac0f3a HDDS-1619. Support volume acl operations for OM HA. Contributed by… (#1147) 3ac0f3a is described below commit 3ac0f3a0c1d982bfab13de0112b7bae778d19a74 Author: Xiaoyu Yao <x...@apache.org> AuthorDate: Thu Aug 8 09:55:46 2019 -0700 HDDS-1619. Support volume acl operations for OM HA. Contributed by… (#1147) --- .../om/ratis/utils/OzoneManagerRatisUtils.java | 33 ++++- .../om/request/volume/acl/OMVolumeAclRequest.java | 157 +++++++++++++++++++++ .../request/volume/acl/OMVolumeAddAclRequest.java | 110 +++++++++++++++ .../volume/acl/OMVolumeRemoveAclRequest.java | 109 ++++++++++++++ .../request/volume/acl/OMVolumeSetAclRequest.java | 106 ++++++++++++++ .../ozone/om/request/volume/acl/package-info.java | 22 +++ .../om/response/volume/OMVolumeAclOpResponse.java | 68 +++++++++ .../OzoneManagerHARequestHandlerImpl.java | 17 ++- .../ozone/om/request/TestOMRequestUtils.java | 65 ++++++++- .../volume/acl/TestOMVolumeAddAclRequest.java | 123 ++++++++++++++++ .../volume/acl/TestOMVolumeRemoveAclRequest.java | 133 +++++++++++++++++ .../volume/acl/TestOMVolumeSetAclRequest.java | 136 ++++++++++++++++++ .../ozone/om/request/volume/acl/package-info.java | 21 +++ 13 files changed, 1093 insertions(+), 7 deletions(-) diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java index aef189c..460daaa 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/utils/OzoneManagerRatisUtils.java @@ -41,9 +41,12 @@ import org.apache.hadoop.ozone.om.request.volume.OMVolumeCreateRequest; import org.apache.hadoop.ozone.om.request.volume.OMVolumeDeleteRequest; import org.apache.hadoop.ozone.om.request.volume.OMVolumeSetOwnerRequest; import org.apache.hadoop.ozone.om.request.volume.OMVolumeSetQuotaRequest; +import org.apache.hadoop.ozone.om.request.volume.acl.OMVolumeAddAclRequest; +import org.apache.hadoop.ozone.om.request.volume.acl.OMVolumeRemoveAclRequest; +import org.apache.hadoop.ozone.om.request.volume.acl.OMVolumeSetAclRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos - .OMRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneObj.ObjectType; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Status; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type; @@ -117,12 +120,38 @@ public final class OzoneManagerRatisUtils { return new S3MultipartUploadAbortRequest(omRequest); case CompleteMultiPartUpload: return new S3MultipartUploadCompleteRequest(omRequest); + case AddAcl: + case RemoveAcl: + case SetAcl: + return getOMAclRequest(omRequest); default: // TODO: will update once all request types are implemented. return null; } } + private static OMClientRequest getOMAclRequest(OMRequest omRequest) { + Type cmdType = omRequest.getCmdType(); + if (Type.AddAcl == cmdType) { + ObjectType type = omRequest.getAddAclRequest().getObj().getResType(); + if (ObjectType.VOLUME == type) { + return new OMVolumeAddAclRequest(omRequest); + } + } else if (Type.RemoveAcl == cmdType) { + ObjectType type = omRequest.getAddAclRequest().getObj().getResType(); + if (ObjectType.VOLUME == type) { + return new OMVolumeRemoveAclRequest(omRequest); + } + } else if (Type.SetAcl == cmdType) { + ObjectType type = omRequest.getAddAclRequest().getObj().getResType(); + if (ObjectType.VOLUME == type) { + return new OMVolumeSetAclRequest(omRequest); + } + } + //TODO: handle bucket, key and prefix AddAcl + return null; + } + /** * Convert exception result to {@link OzoneManagerProtocolProtos.Status}. * @param exception diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/OMVolumeAclRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/OMVolumeAclRequest.java new file mode 100644 index 0000000..4d2a851 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/OMVolumeAclRequest.java @@ -0,0 +1,157 @@ +package org.apache.hadoop.ozone.om.request.volume.acl; + +import com.google.common.base.Optional; +import org.apache.hadoop.hdds.scm.storage.CheckedBiFunction; +import org.apache.hadoop.ozone.OzoneAcl; +import org.apache.hadoop.ozone.om.OMMetadataManager; +import org.apache.hadoop.ozone.om.OMMetrics; +import org.apache.hadoop.ozone.om.OzoneManager; +import org.apache.hadoop.ozone.om.exceptions.OMException; +import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; +import org.apache.hadoop.ozone.om.ratis.utils.OzoneManagerDoubleBufferHelper; +import org.apache.hadoop.ozone.om.request.OMClientRequest; +import org.apache.hadoop.ozone.om.response.OMClientResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse; +import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer; +import org.apache.hadoop.ozone.security.acl.OzoneObj; +import org.apache.hadoop.utils.db.cache.CacheKey; +import org.apache.hadoop.utils.db.cache.CacheValue; + +import java.io.IOException; +import java.util.List; + +import static org.apache.hadoop.ozone.om.lock.OzoneManagerLock.Resource.VOLUME_LOCK; + +/** + * Base class for OMVolumeAcl Request. + */ +public abstract class OMVolumeAclRequest extends OMClientRequest { + + private CheckedBiFunction<List<OzoneAcl>, OmVolumeArgs, IOException> + omVolumeAclOp; + + public OMVolumeAclRequest(OzoneManagerProtocolProtos.OMRequest omRequest, + CheckedBiFunction<List<OzoneAcl>, OmVolumeArgs, IOException> aclOp) { + super(omRequest); + omVolumeAclOp = aclOp; + } + + @Override + public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, + long transactionLogIndex, + OzoneManagerDoubleBufferHelper ozoneManagerDoubleBufferHelper) { + // protobuf guarantees volume and acls are non-null. + String volume = getVolumeName(); + List<OzoneAcl> ozoneAcls = getAcls(); + + OMMetrics omMetrics = ozoneManager.getMetrics(); + omMetrics.incNumVolumeUpdates(); + OmVolumeArgs omVolumeArgs = null; + + OMResponse.Builder omResponse = onInit(); + OMClientResponse omClientResponse = null; + IOException exception = null; + + OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager(); + boolean lockAcquired = false; + try { + // check Acl + if (ozoneManager.getAclsEnabled()) { + checkAcls(ozoneManager, OzoneObj.ResourceType.VOLUME, + OzoneObj.StoreType.OZONE, IAccessAuthorizer.ACLType.WRITE_ACL, + volume, null, null); + } + lockAcquired = + omMetadataManager.getLock().acquireLock(VOLUME_LOCK, volume); + String dbVolumeKey = omMetadataManager.getVolumeKey(volume); + omVolumeArgs = omMetadataManager.getVolumeTable().get(dbVolumeKey); + if (omVolumeArgs == null) { + throw new OMException(OMException.ResultCodes.VOLUME_NOT_FOUND); + } + + // result is false upon add existing acl or remove non-existing acl + boolean result = true; + try { + omVolumeAclOp.apply(ozoneAcls, omVolumeArgs); + } catch (OMException ex) { + result = false; + } + + if (result) { + // update cache. + omMetadataManager.getVolumeTable().addCacheEntry( + new CacheKey<>(dbVolumeKey), + new CacheValue<>(Optional.of(omVolumeArgs), transactionLogIndex)); + } + + omClientResponse = onSuccess(omResponse, omVolumeArgs, result); + } catch (IOException ex) { + exception = ex; + omMetrics.incNumVolumeUpdateFails(); + omClientResponse = onFailure(omResponse, ex); + } finally { + if (omClientResponse != null) { + omClientResponse.setFlushFuture( + ozoneManagerDoubleBufferHelper.add(omClientResponse, + transactionLogIndex)); + } + if (lockAcquired) { + omMetadataManager.getLock().releaseLock(VOLUME_LOCK, volume); + } + } + + onComplete(exception); + + return omClientResponse; + } + + /** + * Get the Acls from the request. + * @return List of OzoneAcls, for add/remove it is a single element list + * for set it can be non-single element list. + */ + abstract List<OzoneAcl> getAcls(); + + /** + * Get the volume name from the request. + * @return volume name + * This is needed for case where volume does not exist and the omVolumeArgs is + * null. + */ + abstract String getVolumeName(); + + // TODO: Finer grain metrics can be moved to these callbacks. They can also + // be abstracted into separate interfaces in future. + /** + * Get the initial om response builder with lock. + * @return om response builder. + */ + abstract OMResponse.Builder onInit(); + + /** + * Get the om client response on success case with lock. + * @param omResponse + * @param omVolumeArgs + * @param result + * @return OMClientResponse + */ + abstract OMClientResponse onSuccess( + OMResponse.Builder omResponse, OmVolumeArgs omVolumeArgs, boolean result); + + /** + * Get the om client response on failure case with lock. + * @param omResponse + * @param ex + * @return OMClientResponse + */ + abstract OMClientResponse onFailure(OMResponse.Builder omResponse, + IOException ex); + + /** + * Completion hook for final processing before return without lock. + * Usually used for logging without lock. + * @param ex + */ + abstract void onComplete(IOException ex); +} diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/OMVolumeAddAclRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/OMVolumeAddAclRequest.java new file mode 100644 index 0000000..6bb8564 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/OMVolumeAddAclRequest.java @@ -0,0 +1,110 @@ +/** + * 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.request.volume.acl; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import org.apache.hadoop.hdds.scm.storage.CheckedBiFunction; +import org.apache.hadoop.ozone.OzoneAcl; +import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; +import org.apache.hadoop.ozone.om.response.OMClientResponse; +import org.apache.hadoop.ozone.om.response.volume.OMVolumeAclOpResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.List; + +/** + * Handles volume add acl request. + */ +public class OMVolumeAddAclRequest extends OMVolumeAclRequest { + private static final Logger LOG = + LoggerFactory.getLogger(OMVolumeAddAclRequest.class); + + private static CheckedBiFunction<List<OzoneAcl>, + OmVolumeArgs, IOException> volumeAddAclOp; + + static { + volumeAddAclOp = (acls, volArgs) -> volArgs.addAcl(acls.get(0)); + } + + private List<OzoneAcl> ozoneAcls; + private String volumeName; + + public OMVolumeAddAclRequest(OMRequest omRequest) { + super(omRequest, volumeAddAclOp); + OzoneManagerProtocolProtos.AddAclRequest addAclRequest = + getOmRequest().getAddAclRequest(); + Preconditions.checkNotNull(addAclRequest); + ozoneAcls = Lists.newArrayList( + OzoneAcl.fromProtobuf(addAclRequest.getAcl())); + volumeName = addAclRequest.getObj().getPath().substring(1); + } + + @Override + public List<OzoneAcl> getAcls() { + return ozoneAcls; + } + + @Override + public String getVolumeName() { + return volumeName; + } + + private OzoneAcl getAcl() { + return ozoneAcls.get(0); + } + + + @Override + OMResponse.Builder onInit() { + return OMResponse.newBuilder().setCmdType( + OzoneManagerProtocolProtos.Type.AddAcl) + .setStatus(OzoneManagerProtocolProtos.Status.OK).setSuccess(true); + } + + @Override + OMClientResponse onSuccess(OMResponse.Builder omResponse, + OmVolumeArgs omVolumeArgs, boolean result){ + omResponse.setAddAclResponse(OzoneManagerProtocolProtos.AddAclResponse + .newBuilder().setResponse(result).build()); + return new OMVolumeAclOpResponse(omVolumeArgs, omResponse.build()); + } + + @Override + OMClientResponse onFailure(OMResponse.Builder omResponse, + IOException ex) { + return new OMVolumeAclOpResponse(null, + createErrorOMResponse(omResponse, ex)); + } + + @Override + void onComplete(IOException ex) { + if (ex == null) { + LOG.debug("Add acl: {} to volume: {} success!", + getAcl(), getVolumeName()); + } else { + LOG.error("Add acl {} to volume {} failed!", + getAcl(), getVolumeName(), ex); + } + } +} diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/OMVolumeRemoveAclRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/OMVolumeRemoveAclRequest.java new file mode 100644 index 0000000..188e205 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/OMVolumeRemoveAclRequest.java @@ -0,0 +1,109 @@ +/** + * 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.request.volume.acl; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import org.apache.hadoop.hdds.scm.storage.CheckedBiFunction; +import org.apache.hadoop.ozone.OzoneAcl; +import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; +import org.apache.hadoop.ozone.om.response.OMClientResponse; +import org.apache.hadoop.ozone.om.response.volume.OMVolumeAclOpResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.List; + +/** + * Handles volume remove acl request. + */ +public class OMVolumeRemoveAclRequest extends OMVolumeAclRequest { + private static final Logger LOG = + LoggerFactory.getLogger(OMVolumeRemoveAclRequest.class); + + private static CheckedBiFunction<List<OzoneAcl>, + OmVolumeArgs, IOException> volumeRemoveAclOp; + + static { + volumeRemoveAclOp = (acls, volArgs) -> volArgs.removeAcl(acls.get(0)); + } + + private List<OzoneAcl> ozoneAcls; + private String volumeName; + + public OMVolumeRemoveAclRequest(OMRequest omRequest) { + super(omRequest, volumeRemoveAclOp); + OzoneManagerProtocolProtos.RemoveAclRequest removeAclRequest = + getOmRequest().getRemoveAclRequest(); + Preconditions.checkNotNull(removeAclRequest); + ozoneAcls = Lists.newArrayList( + OzoneAcl.fromProtobuf(removeAclRequest.getAcl())); + volumeName = removeAclRequest.getObj().getPath().substring(1); + } + + @Override + public List<OzoneAcl> getAcls() { + return ozoneAcls; + } + + @Override + public String getVolumeName() { + return volumeName; + } + + private OzoneAcl getAcl() { + return ozoneAcls.get(0); + } + + @Override + OMResponse.Builder onInit() { + return OMResponse.newBuilder().setCmdType( + OzoneManagerProtocolProtos.Type.RemoveAcl) + .setStatus(OzoneManagerProtocolProtos.Status.OK).setSuccess(true); + } + + @Override + OMClientResponse onSuccess(OMResponse.Builder omResponse, + OmVolumeArgs omVolumeArgs, boolean result){ + omResponse.setRemoveAclResponse(OzoneManagerProtocolProtos.RemoveAclResponse + .newBuilder().setResponse(result).build()); + return new OMVolumeAclOpResponse(omVolumeArgs, omResponse.build()); + } + + @Override + OMClientResponse onFailure(OMResponse.Builder omResponse, + IOException ex) { + return new OMVolumeAclOpResponse(null, + createErrorOMResponse(omResponse, ex)); + } + + @Override + void onComplete(IOException ex) { + if (ex == null) { + LOG.debug("Remove acl: {} from volume: {} success!", + getAcl(), getVolumeName()); + } else { + LOG.error("Remove acl {} from volume {} failed!", + getAcl(), getVolumeName(), ex); + } + } +} diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/OMVolumeSetAclRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/OMVolumeSetAclRequest.java new file mode 100644 index 0000000..01b5edc --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/OMVolumeSetAclRequest.java @@ -0,0 +1,106 @@ +/** + * 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.request.volume.acl; + +import com.google.common.base.Preconditions; +import org.apache.hadoop.hdds.scm.storage.CheckedBiFunction; +import org.apache.hadoop.ozone.OzoneAcl; +import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; +import org.apache.hadoop.ozone.om.response.OMClientResponse; +import org.apache.hadoop.ozone.om.response.volume.OMVolumeAclOpResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Handles volume set acl request. + */ +public class OMVolumeSetAclRequest extends OMVolumeAclRequest { + private static final Logger LOG = + LoggerFactory.getLogger(OMVolumeSetAclRequest.class); + + private static CheckedBiFunction<List<OzoneAcl>, + OmVolumeArgs, IOException> volumeSetAclOp; + + static { + volumeSetAclOp = (acls, volArgs) -> volArgs.setAcls(acls); + } + + private List<OzoneAcl> ozoneAcls; + private String volumeName; + + public OMVolumeSetAclRequest(OMRequest omRequest) { + super(omRequest, volumeSetAclOp); + OzoneManagerProtocolProtos.SetAclRequest setAclRequest = + getOmRequest().getSetAclRequest(); + Preconditions.checkNotNull(setAclRequest); + ozoneAcls = new ArrayList<>(); + setAclRequest.getAclList().forEach(oai -> + ozoneAcls.add(OzoneAcl.fromProtobuf(oai))); + volumeName = setAclRequest.getObj().getPath().substring(1); + } + + @Override + public List<OzoneAcl> getAcls() { + return ozoneAcls; + } + + @Override + public String getVolumeName() { + return volumeName; + } + + @Override + OMResponse.Builder onInit() { + return OMResponse.newBuilder().setCmdType( + OzoneManagerProtocolProtos.Type.RemoveAcl) + .setStatus(OzoneManagerProtocolProtos.Status.OK).setSuccess(true); + } + + @Override + OMClientResponse onSuccess(OMResponse.Builder omResponse, + OmVolumeArgs omVolumeArgs, boolean result){ + omResponse.setSetAclResponse(OzoneManagerProtocolProtos.SetAclResponse + .newBuilder().setResponse(result).build()); + return new OMVolumeAclOpResponse(omVolumeArgs, omResponse.build()); + } + + @Override + OMClientResponse onFailure(OMResponse.Builder omResponse, + IOException ex) { + return new OMVolumeAclOpResponse(null, + createErrorOMResponse(omResponse, ex)); + } + + @Override + void onComplete(IOException ex) { + if (ex == null) { + LOG.debug("Set acls: {} to volume: {} success!", + getAcls(), getVolumeName()); + } else { + LOG.error("Set acls {} to volume {} failed!", + getAcls(), getVolumeName(), ex); + } + } +} diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/package-info.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/package-info.java new file mode 100644 index 0000000..79c4afd --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/volume/acl/package-info.java @@ -0,0 +1,22 @@ +/** + * 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 contains classes related to volume acl requests and responses. + */ +package org.apache.hadoop.ozone.om.request.volume.acl; \ No newline at end of file diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/volume/OMVolumeAclOpResponse.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/volume/OMVolumeAclOpResponse.java new file mode 100644 index 0000000..3706129 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/response/volume/OMVolumeAclOpResponse.java @@ -0,0 +1,68 @@ +/** + * 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.response.volume; + +import com.google.common.annotations.VisibleForTesting; +import org.apache.hadoop.ozone.om.OMMetadataManager; +import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; +import org.apache.hadoop.ozone.om.response.OMClientResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse; +import org.apache.hadoop.utils.db.BatchOperation; + +import java.io.IOException; + +/** + * Response for om volume acl operation request. + */ +public class OMVolumeAclOpResponse extends OMClientResponse { + + private OmVolumeArgs omVolumeArgs; + + public OMVolumeAclOpResponse(OmVolumeArgs omVolumeArgs, + OMResponse omResponse) { + super(omResponse); + this.omVolumeArgs = omVolumeArgs; + } + + @Override + public void addToDBBatch(OMMetadataManager omMetadataManager, + BatchOperation batchOperation) throws IOException { + + // For OmResponse with failure, this should do nothing. This method is + // not called in failure scenario in OM code. + if (getOMResponse().getSuccess()) { + if ((getOMResponse().hasAddAclResponse() && + getOMResponse().getAddAclResponse().getResponse()) || + (getOMResponse().hasRemoveAclResponse() && + getOMResponse().getRemoveAclResponse().getResponse()) || + (getOMResponse().hasSetAclResponse() && + getOMResponse().getSetAclResponse().getResponse())) { + omMetadataManager.getVolumeTable().putWithBatch(batchOperation, + omMetadataManager.getVolumeKey(omVolumeArgs.getVolume()), + omVolumeArgs); + } + } + } + + @VisibleForTesting + public OmVolumeArgs getOmVolumeArgs() { + return omVolumeArgs; + } +} + diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerHARequestHandlerImpl.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerHARequestHandlerImpl.java index f3f27a6..4b77813 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerHARequestHandlerImpl.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerHARequestHandlerImpl.java @@ -71,6 +71,9 @@ public class OzoneManagerHARequestHandlerImpl case CommitMultiPartUpload: case AbortMultiPartUpload: case CompleteMultiPartUpload: + case AddAcl: + case RemoveAcl: + case SetAcl: //TODO: We don't need to pass transactionID, this will be removed when // complete write requests is changed to new model. And also we can // return OMClientResponse, then adding to doubleBuffer can be taken @@ -78,10 +81,16 @@ public class OzoneManagerHARequestHandlerImpl // paths. OMClientRequest omClientRequest = OzoneManagerRatisUtils.createClientRequest(omRequest); - OMClientResponse omClientResponse = - omClientRequest.validateAndUpdateCache(getOzoneManager(), - transactionLogIndex, ozoneManagerDoubleBuffer::add); - return omClientResponse.getOMResponse(); + if (omClientRequest != null) { + OMClientResponse omClientResponse = + omClientRequest.validateAndUpdateCache(getOzoneManager(), + transactionLogIndex, ozoneManagerDoubleBuffer::add); + return omClientResponse.getOMResponse(); + } else { + //TODO: remove this once we have all HA support for all write request. + return handle(omRequest); + } + default: // As all request types are not changed so we need to call handle // here. diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMRequestUtils.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMRequestUtils.java index 581c083..24667eb 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMRequestUtils.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/TestOMRequestUtils.java @@ -28,6 +28,7 @@ import java.util.UUID; import org.apache.hadoop.hdds.protocol.proto.HddsProtos; import org.apache.hadoop.ozone.OmUtils; +import org.apache.hadoop.ozone.OzoneAcl; import org.apache.hadoop.ozone.om.OMMetadataManager; import org.apache.hadoop.ozone.om.helpers.OmBucketInfo; import org.apache.hadoop.ozone.om.helpers.OmKeyInfo; @@ -49,6 +50,17 @@ import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos .OMRequest; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos .SetVolumePropertyRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos + .AddAclRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos + .RemoveAclRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos + .SetAclRequest; +import org.apache.hadoop.ozone.security.acl.OzoneObj; +import org.apache.hadoop.ozone.security.acl.OzoneObj.ResourceType; +import org.apache.hadoop.ozone.security.acl.OzoneObj.StoreType; + +import org.apache.hadoop.ozone.security.acl.OzoneObjInfo; import org.apache.hadoop.util.Time; /** @@ -285,6 +297,58 @@ public final class TestOMRequestUtils { .setSetVolumePropertyRequest(setVolumePropertyRequest).build(); } + public static OMRequest createVolumeAddAclRequest(String volumeName, + OzoneAcl acl) { + AddAclRequest.Builder addAclRequestBuilder = AddAclRequest.newBuilder(); + addAclRequestBuilder.setObj(OzoneObj.toProtobuf(new OzoneObjInfo.Builder() + .setVolumeName(volumeName) + .setResType(ResourceType.VOLUME) + .setStoreType(StoreType.OZONE) + .build())); + if (acl != null) { + addAclRequestBuilder.setAcl(OzoneAcl.toProtobuf(acl)); + } + return OMRequest.newBuilder().setClientId(UUID.randomUUID().toString()) + .setCmdType(OzoneManagerProtocolProtos.Type.AddAcl) + .setAddAclRequest(addAclRequestBuilder.build()).build(); + } + + public static OMRequest createVolumeRemoveAclRequest(String volumeName, + OzoneAcl acl) { + RemoveAclRequest.Builder removeAclRequestBuilder = + RemoveAclRequest.newBuilder(); + removeAclRequestBuilder.setObj(OzoneObj.toProtobuf( + new OzoneObjInfo.Builder() + .setVolumeName(volumeName) + .setResType(ResourceType.VOLUME) + .setStoreType(StoreType.OZONE) + .build())); + if (acl != null) { + removeAclRequestBuilder.setAcl(OzoneAcl.toProtobuf(acl)); + } + return OMRequest.newBuilder().setClientId(UUID.randomUUID().toString()) + .setCmdType(OzoneManagerProtocolProtos.Type.RemoveAcl) + .setRemoveAclRequest(removeAclRequestBuilder.build()).build(); + } + + public static OMRequest createVolumeSetAclRequest(String volumeName, + List<OzoneAcl> acls) { + SetAclRequest.Builder setAclRequestBuilder = SetAclRequest.newBuilder(); + setAclRequestBuilder.setObj(OzoneObj.toProtobuf(new OzoneObjInfo.Builder() + .setVolumeName(volumeName) + .setResType(ResourceType.VOLUME) + .setStoreType(StoreType.OZONE) + .build())); + if (acls != null) { + acls.forEach( + acl -> setAclRequestBuilder.addAcl(OzoneAcl.toProtobuf(acl))); + } + + return OMRequest.newBuilder().setClientId(UUID.randomUUID().toString()) + .setCmdType(OzoneManagerProtocolProtos.Type.SetAcl) + .setSetAclRequest(setAclRequestBuilder.build()).build(); + } + /** * Deletes key from Key table and adds it to DeletedKeys table. * @return the deletedKey name @@ -387,5 +451,4 @@ public final class TestOMRequestUtils { .build(); } - } diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/acl/TestOMVolumeAddAclRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/acl/TestOMVolumeAddAclRequest.java new file mode 100644 index 0000000..eae8c51 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/acl/TestOMVolumeAddAclRequest.java @@ -0,0 +1,123 @@ +/** + * 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.request.volume.acl; + +import org.apache.hadoop.ozone.OzoneAcl; +import org.apache.hadoop.ozone.om.helpers.OmOzoneAclMap; +import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; +import org.apache.hadoop.ozone.om.request.TestOMRequestUtils; +import org.apache.hadoop.ozone.om.request.volume.TestOMVolumeRequest; +import org.apache.hadoop.ozone.om.response.OMClientResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.UUID; + +/** + * Tests volume addAcl request. + */ +public class TestOMVolumeAddAclRequest extends TestOMVolumeRequest { + + @Test + public void testPreExecute() throws Exception { + String volumeName = UUID.randomUUID().toString(); + OzoneAcl acl = OzoneAcl.parseAcl("user:bilbo:rw"); + OMRequest originalRequest = + TestOMRequestUtils.createVolumeAddAclRequest(volumeName, acl); + + OMVolumeAddAclRequest omVolumeAddAclRequest = + new OMVolumeAddAclRequest(originalRequest); + + OMRequest modifiedRequest = omVolumeAddAclRequest.preExecute( + ozoneManager); + Assert.assertNotEquals(modifiedRequest, originalRequest); + } + + @Test + public void testValidateAndUpdateCacheSuccess() throws Exception { + String volumeName = UUID.randomUUID().toString(); + String ownerName = "user1"; + + TestOMRequestUtils.addUserToDB(volumeName, ownerName, omMetadataManager); + TestOMRequestUtils.addVolumeToDB(volumeName, ownerName, omMetadataManager); + + OzoneAcl acl = OzoneAcl.parseAcl("user:bilbo:rwdlncxy[ACCESS]"); + + OMRequest originalRequest = + TestOMRequestUtils.createVolumeAddAclRequest(volumeName, acl); + + OMVolumeAddAclRequest omVolumeAddAclRequest = + new OMVolumeAddAclRequest(originalRequest); + + omVolumeAddAclRequest.preExecute(ozoneManager); + + String volumeKey = omMetadataManager.getVolumeKey(volumeName); + + // Get Acl before validateAndUpdateCache. + OmVolumeArgs omVolumeArgs = + omMetadataManager.getVolumeTable().get(volumeKey); + // As request is valid volume table should have entry. + Assert.assertNotNull(omVolumeArgs); + OmOzoneAclMap aclMapBeforeSet = omVolumeArgs.getAclMap(); + + OMClientResponse omClientResponse = + omVolumeAddAclRequest.validateAndUpdateCache(ozoneManager, 1, + ozoneManagerDoubleBufferHelper); + + OMResponse omResponse = omClientResponse.getOMResponse(); + Assert.assertNotNull(omResponse.getAddAclResponse()); + Assert.assertEquals(OzoneManagerProtocolProtos.Status.OK, + omResponse.getStatus()); + + OmOzoneAclMap aclMapAfterSet = omMetadataManager + .getVolumeTable().get(volumeKey).getAclMap(); + Assert.assertNotEquals(aclMapBeforeSet, aclMapAfterSet); + + // acl is added to aclMapAfterSet + Assert.assertEquals(1, aclMapAfterSet.getAcl().size()); + Assert.assertEquals(acl, aclMapAfterSet.getAcl().get(0)); + } + + @Test + public void testValidateAndUpdateCacheWithVolumeNotFound() + throws Exception { + String volumeName = UUID.randomUUID().toString(); + OzoneAcl acl = OzoneAcl.parseAcl("user:bilbo:rw"); + OMRequest originalRequest = + TestOMRequestUtils.createVolumeAddAclRequest(volumeName, acl); + + OMVolumeAddAclRequest omVolumeAddAclRequest = + new OMVolumeAddAclRequest(originalRequest); + + omVolumeAddAclRequest.preExecute(ozoneManager); + + OMClientResponse omClientResponse = + omVolumeAddAclRequest.validateAndUpdateCache(ozoneManager, 1, + ozoneManagerDoubleBufferHelper); + + OMResponse omResponse = omClientResponse.getOMResponse(); + Assert.assertNotNull(omResponse.getAddAclResponse()); + Assert.assertEquals(OzoneManagerProtocolProtos.Status.VOLUME_NOT_FOUND, + omResponse.getStatus()); + } +} diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/acl/TestOMVolumeRemoveAclRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/acl/TestOMVolumeRemoveAclRequest.java new file mode 100644 index 0000000..dfd0a23 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/acl/TestOMVolumeRemoveAclRequest.java @@ -0,0 +1,133 @@ +/** + * 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.request.volume.acl; + +import org.apache.hadoop.ozone.OzoneAcl; +import org.apache.hadoop.ozone.om.helpers.OmOzoneAclMap; +import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; +import org.apache.hadoop.ozone.om.request.TestOMRequestUtils; +import org.apache.hadoop.ozone.om.request.volume.TestOMVolumeRequest; +import org.apache.hadoop.ozone.om.response.OMClientResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse; +import org.junit.Assert; +import org.junit.Test; + +import java.util.UUID; + +/** + * Tests volume removeAcl request. + */ +public class TestOMVolumeRemoveAclRequest extends TestOMVolumeRequest { + + @Test + public void testPreExecute() throws Exception { + String volumeName = UUID.randomUUID().toString(); + OzoneAcl acl = OzoneAcl.parseAcl("user:bilbo:rw"); + OMRequest originalRequest = + TestOMRequestUtils.createVolumeRemoveAclRequest(volumeName, acl); + + OMVolumeRemoveAclRequest omVolumeRemoveAclRequest = + new OMVolumeRemoveAclRequest(originalRequest); + + OMRequest modifiedRequest = omVolumeRemoveAclRequest.preExecute( + ozoneManager); + Assert.assertNotEquals(modifiedRequest, originalRequest); + } + + @Test + public void testValidateAndUpdateCacheSuccess() throws Exception { + String volumeName = UUID.randomUUID().toString(); + String ownerName = "user1"; + + TestOMRequestUtils.addUserToDB(volumeName, ownerName, omMetadataManager); + TestOMRequestUtils.addVolumeToDB(volumeName, ownerName, omMetadataManager); + + OzoneAcl acl = OzoneAcl.parseAcl("user:bilbo:rwdlncxy[ACCESS]"); + // add acl first + OMRequest addAclRequest = + TestOMRequestUtils.createVolumeAddAclRequest(volumeName, acl); + OMVolumeAddAclRequest omVolumeAddAclRequest = + new OMVolumeAddAclRequest(addAclRequest); + omVolumeAddAclRequest.preExecute(ozoneManager); + OMClientResponse omClientAddResponse = + omVolumeAddAclRequest.validateAndUpdateCache(ozoneManager, 1, + ozoneManagerDoubleBufferHelper); + OMResponse omAddAclResponse = omClientAddResponse.getOMResponse(); + Assert.assertNotNull(omAddAclResponse.getAddAclResponse()); + Assert.assertEquals(OzoneManagerProtocolProtos.Status.OK, + omAddAclResponse.getStatus()); + + + // remove acl + OMRequest removeAclRequest = + TestOMRequestUtils.createVolumeRemoveAclRequest(volumeName, acl); + OMVolumeRemoveAclRequest omVolumeRemoveAclRequest = + new OMVolumeRemoveAclRequest(removeAclRequest); + omVolumeRemoveAclRequest.preExecute(ozoneManager); + + String volumeKey = omMetadataManager.getVolumeKey(volumeName); + + // Get Acl before Remove. + OmVolumeArgs omVolumeArgs = + omMetadataManager.getVolumeTable().get(volumeKey); + // As request is valid volume table should have entry. + Assert.assertNotNull(omVolumeArgs); + OmOzoneAclMap aclMapBeforeRemove = omVolumeArgs.getAclMap(); + Assert.assertEquals(acl, aclMapBeforeRemove.getAcl().get(0)); + + OMClientResponse omClientRemoveResponse = + omVolumeRemoveAclRequest.validateAndUpdateCache(ozoneManager, 1, + ozoneManagerDoubleBufferHelper); + + OMResponse omRemoveAclResponse = omClientRemoveResponse.getOMResponse(); + Assert.assertNotNull(omRemoveAclResponse.getRemoveAclResponse()); + Assert.assertEquals(OzoneManagerProtocolProtos.Status.OK, + omRemoveAclResponse.getStatus()); + + // acl is removed from aclMapAfterSet + OmOzoneAclMap aclMapAfterRemove = omMetadataManager + .getVolumeTable().get(volumeKey).getAclMap(); + Assert.assertEquals(0, aclMapAfterRemove.getAcl().size()); + } + + @Test + public void testValidateAndUpdateCacheWithVolumeNotFound() + throws Exception { + String volumeName = UUID.randomUUID().toString(); + OzoneAcl acl = OzoneAcl.parseAcl("user:bilbo:rw"); + OMRequest originalRequest = + TestOMRequestUtils.createVolumeRemoveAclRequest(volumeName, acl); + + OMVolumeRemoveAclRequest omVolumeRemoveAclRequest = + new OMVolumeRemoveAclRequest(originalRequest); + + omVolumeRemoveAclRequest.preExecute(ozoneManager); + + OMClientResponse omClientResponse = + omVolumeRemoveAclRequest.validateAndUpdateCache(ozoneManager, 1, + ozoneManagerDoubleBufferHelper); + + OMResponse omResponse = omClientResponse.getOMResponse(); + Assert.assertNotNull(omResponse.getRemoveAclResponse()); + Assert.assertEquals(OzoneManagerProtocolProtos.Status.VOLUME_NOT_FOUND, + omResponse.getStatus()); + } +} diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/acl/TestOMVolumeSetAclRequest.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/acl/TestOMVolumeSetAclRequest.java new file mode 100644 index 0000000..c0c48ec --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/acl/TestOMVolumeSetAclRequest.java @@ -0,0 +1,136 @@ +/** + * 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.request.volume.acl; + +import com.google.common.collect.Lists; +import org.apache.hadoop.ozone.OzoneAcl; +import org.apache.hadoop.ozone.om.helpers.OmOzoneAclMap; +import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; +import org.apache.hadoop.ozone.om.request.TestOMRequestUtils; +import org.apache.hadoop.ozone.om.request.volume.TestOMVolumeRequest; +import org.apache.hadoop.ozone.om.response.OMClientResponse; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; +import java.util.UUID; + +import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneAclInfo.OzoneAclScope.ACCESS; +import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneAclInfo.OzoneAclScope.DEFAULT; + +/** + * Tests volume setAcl request. + */ +public class TestOMVolumeSetAclRequest extends TestOMVolumeRequest { + + @Test + public void testPreExecute() throws Exception { + String volumeName = UUID.randomUUID().toString(); + OzoneAcl acl = OzoneAcl.parseAcl("user:bilbo:rw"); + OMRequest originalRequest = + TestOMRequestUtils.createVolumeSetAclRequest(volumeName, + Lists.newArrayList(acl)); + + OMVolumeSetAclRequest omVolumeSetAclRequest = + new OMVolumeSetAclRequest(originalRequest); + + OMRequest modifiedRequest = omVolumeSetAclRequest.preExecute( + ozoneManager); + Assert.assertNotEquals(modifiedRequest, originalRequest); + } + + @Test + public void testValidateAndUpdateCacheSuccess() throws Exception { + String volumeName = UUID.randomUUID().toString(); + String ownerName = "user1"; + + TestOMRequestUtils.addUserToDB(volumeName, ownerName, omMetadataManager); + TestOMRequestUtils.addVolumeToDB(volumeName, ownerName, omMetadataManager); + + OzoneAcl userAccessAcl = OzoneAcl.parseAcl("user:bilbo:rw[ACCESS]"); + OzoneAcl groupDefaultAcl = + OzoneAcl.parseAcl("group:admin:rwdlncxy[DEFAULT]"); + + List<OzoneAcl> acls = Lists.newArrayList(userAccessAcl, groupDefaultAcl); + + OMRequest originalRequest = + TestOMRequestUtils.createVolumeSetAclRequest(volumeName, acls); + + OMVolumeSetAclRequest omVolumeSetAclRequest = + new OMVolumeSetAclRequest(originalRequest); + + omVolumeSetAclRequest.preExecute(ozoneManager); + + String volumeKey = omMetadataManager.getVolumeKey(volumeName); + + // Get Acl before validateAndUpdateCache. + OmVolumeArgs omVolumeArgs = + omMetadataManager.getVolumeTable().get(volumeKey); + // As request is valid volume table should have entry. + Assert.assertNotNull(omVolumeArgs); + OmOzoneAclMap aclMapBeforeSet = omVolumeArgs.getAclMap(); + + OMClientResponse omClientResponse = + omVolumeSetAclRequest.validateAndUpdateCache(ozoneManager, 1, + ozoneManagerDoubleBufferHelper); + + OMResponse omResponse = omClientResponse.getOMResponse(); + Assert.assertNotNull(omResponse.getSetAclResponse()); + Assert.assertEquals(OzoneManagerProtocolProtos.Status.OK, + omResponse.getStatus()); + + OmOzoneAclMap aclMapAfterSet = omMetadataManager + .getVolumeTable().get(volumeKey).getAclMap(); + Assert.assertNotEquals(aclMapBeforeSet, aclMapAfterSet); + + // Acl is added to aclMapAfterSet + Assert.assertEquals(2, aclMapAfterSet.getAcl().size()); + Assert.assertTrue("Default Acl should be set.", + aclMapAfterSet.getAclsByScope(ACCESS).contains(userAccessAcl)); + Assert.assertTrue("Default Acl should be set.", + aclMapAfterSet.getAclsByScope(DEFAULT).contains(groupDefaultAcl)); + } + + @Test + public void testValidateAndUpdateCacheWithVolumeNotFound() + throws Exception { + String volumeName = UUID.randomUUID().toString(); + OzoneAcl acl = OzoneAcl.parseAcl("user:bilbo:rw"); + OMRequest originalRequest = + TestOMRequestUtils.createVolumeSetAclRequest(volumeName, + Lists.newArrayList(acl)); + + OMVolumeSetAclRequest omVolumeSetAclRequest = + new OMVolumeSetAclRequest(originalRequest); + + omVolumeSetAclRequest.preExecute(ozoneManager); + + OMClientResponse omClientResponse = + omVolumeSetAclRequest.validateAndUpdateCache(ozoneManager, 1, + ozoneManagerDoubleBufferHelper); + + OMResponse omResponse = omClientResponse.getOMResponse(); + Assert.assertNotNull(omResponse.getSetAclResponse()); + Assert.assertEquals(OzoneManagerProtocolProtos.Status.VOLUME_NOT_FOUND, + omResponse.getStatus()); + } +} diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/acl/package-info.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/acl/package-info.java new file mode 100644 index 0000000..1552af7 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/volume/acl/package-info.java @@ -0,0 +1,21 @@ +/** + * 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 contains test classes for volume acl requests. + */ +package org.apache.hadoop.ozone.om.request.volume.acl; \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org For additional commands, e-mail: common-commits-h...@hadoop.apache.org