Skip to content

Commit

Permalink
Add read-only mode
Browse files Browse the repository at this point in the history
  • Loading branch information
kuenishi committed Aug 14, 2023
1 parent 93b5538 commit 9dd3b64
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 7 deletions.
8 changes: 8 additions & 0 deletions hadoop-hdds/common/src/main/resources/ozone-default.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1757,6 +1757,14 @@
service principal. </description>
</property>

<property>
<name>ozone.s3g.readonly</name>
<value>false</value>
<tag>OZONE, S3GATEWAY/tag>
<description>Whether the S3Gateway blocks PUT/POST/DELETE methods or not.
Mostly used for system maintenance.</description>
</property>

<property>
<name>ozone.om.save.metrics.interval</name>
<value>5m</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ public final class S3GatewayConfigKeys {
public static final String OZONE_S3G_KERBEROS_PRINCIPAL_KEY =
"ozone.s3g.kerberos.principal";


public static final String OZONE_S3G_READONLY = "ozone.s3g.readonly";
public static final boolean OZONE_S3G_READONLY_DEFAULT = false;
/**
* Never constructed.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.apache.hadoop.ozone.s3.util.ContinueToken;
import org.apache.hadoop.ozone.s3.util.S3StorageType;
import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer;

import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -64,6 +65,7 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import static org.apache.hadoop.ozone.OzoneAcl.AclScope.ACCESS;
Expand Down Expand Up @@ -243,6 +245,12 @@ public Response put(@PathParam("bucket") String bucketName,
InputStream body) throws IOException, OS3Exception {
S3GAction s3GAction = S3GAction.CREATE_BUCKET;

// Check if the S3Gateway status is readonly
Optional<Response> checkResult = checkIfReadonly();
if (checkResult.isPresent()) {
return checkResult.get();
}

try {
if (aclMarker != null) {
s3GAction = S3GAction.PUT_ACL;
Expand Down Expand Up @@ -347,6 +355,12 @@ public Response delete(@PathParam("bucket") String bucketName)
throws IOException, OS3Exception {
S3GAction s3GAction = S3GAction.DELETE_BUCKET;

// Check if the S3Gateway status is readonly
Optional<Response> checkResult = checkIfReadonly();
if (checkResult.isPresent()) {
return checkResult.get();
}

try {
deleteS3Bucket(bucketName);
} catch (OMException ex) {
Expand Down Expand Up @@ -390,9 +404,18 @@ public MultiDeleteResponse multiDelete(@PathParam("bucket") String bucketName,
MultiDeleteRequest request)
throws OS3Exception, IOException {
S3GAction s3GAction = S3GAction.MULTI_DELETE;
MultiDeleteResponse result = new MultiDeleteResponse();

// Check if the S3Gateway status is readonly
Optional<Response> checkResult = checkIfReadonly();
if (checkResult.isPresent()) {
Response res = checkResult.get();
result.addError(new Error("", res.getStatusInfo().getReasonPhrase(),
"The S3Gateway is in read-only mode."));
}

OzoneBucket bucket = getBucket(bucketName);
MultiDeleteResponse result = new MultiDeleteResponse();

if (request.getObjects() != null) {
for (DeleteObject keyToDelete : request.getObjects()) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Context;
import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
import java.util.Arrays;
import java.util.Map;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand All @@ -51,13 +52,15 @@
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes;
import org.apache.hadoop.ozone.om.protocol.S3Auth;
import org.apache.hadoop.ozone.s3.S3GatewayConfigKeys;
import org.apache.hadoop.ozone.s3.exception.OS3Exception;
import org.apache.hadoop.ozone.s3.exception.S3ErrorTable;

import com.google.common.annotations.VisibleForTesting;

import org.apache.hadoop.ozone.s3.metrics.S3GatewayMetrics;
import org.apache.hadoop.ozone.s3.util.AuditUtils;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -380,4 +383,13 @@ protected boolean isAccessDenied(OMException ex) {
|| result == ResultCodes.INVALID_TOKEN;
}

protected Optional<Response> checkIfReadonly() {
// Check if the S3Gateway is in read-only mode or not.
if (getClient().getConfiguration().getBoolean(S3GatewayConfigKeys.OZONE_S3G_READONLY,
S3GatewayConfigKeys.OZONE_S3G_READONLY_DEFAULT)) {
return Optional.of(Response.status(HttpStatus.SC_METHOD_NOT_ALLOWED).
header("Allow", "GET,HEAD").build());
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalLong;

import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -175,6 +176,12 @@ public Response put(
@QueryParam("uploadId") @DefaultValue("") String uploadID,
InputStream body) throws IOException, OS3Exception {

// Check if the S3Gateway status is readonly
Optional<Response> checkResult = checkIfReadonly();
if (checkResult.isPresent()) {
return checkResult.get();
}

S3GAction s3GAction = S3GAction.CREATE_KEY;
boolean auditSuccess = true;

Expand Down Expand Up @@ -527,6 +534,12 @@ public Response delete(
@QueryParam("uploadId") @DefaultValue("") String uploadId) throws
IOException, OS3Exception {

// Check if the S3Gateway status is readonly
Optional<Response> checkResult = checkIfReadonly();
if (checkResult.isPresent()) {
return checkResult.get();
}

S3GAction s3GAction = S3GAction.DELETE_KEY;

try {
Expand Down Expand Up @@ -591,6 +604,13 @@ public Response initializeMultipartUpload(
@PathParam("path") String key
)
throws IOException, OS3Exception {

// Check if the S3Gateway status is readonly
Optional<Response> checkResult = checkIfReadonly();
if (checkResult.isPresent()) {
return checkResult.get();
}

S3GAction s3GAction = S3GAction.INIT_MULTIPART_UPLOAD;

try {
Expand Down Expand Up @@ -658,6 +678,13 @@ public Response completeMultipartUpload(@PathParam("bucket") String bucket,
@QueryParam("uploadId") @DefaultValue("") String uploadID,
CompleteMultipartUploadRequest multipartUploadRequest)
throws IOException, OS3Exception {

// Check if the S3Gateway status is readonly
Optional<Response> checkResult = checkIfReadonly();
if (checkResult.isPresent()) {
return checkResult.get();
}

S3GAction s3GAction = S3GAction.COMPLETE_MULTIPART_UPLOAD;
OzoneVolume volume = getVolume();
// Using LinkedHashMap to preserve ordering of parts list.
Expand Down

0 comments on commit 9dd3b64

Please sign in to comment.