From 93d6050fb8cc9a24e65ebcd401c5c46100b09680 Mon Sep 17 00:00:00 2001 From: Sumit Agrawal Date: Wed, 7 Aug 2024 17:42:17 +0530 Subject: [PATCH 1/7] HDDS-11285. cli to trigger quota repair and status --- .../java/org/apache/hadoop/ozone/OmUtils.java | 2 + .../om/protocol/OzoneManagerProtocol.java | 13 ++ ...ManagerProtocolClientSideTranslatorPB.java | 24 ++++ .../src/main/proto/OmClientProtocol.proto | 17 +++ .../apache/hadoop/ozone/om/OzoneManager.java | 11 ++ .../ozone/om/service/QuotaRepairTask.java | 77 +++++++---- .../OzoneManagerRequestHandler.java | 22 ++++ .../ozone/repair/quota/QuotaRepair.java | 121 ++++++++++++++++++ .../ozone/repair/quota/QuotaStatus.java | 81 ++++++++++++ .../ozone/repair/quota/QuotaTrigger.java | 100 +++++++++++++++ .../ozone/repair/quota/package-info.java | 22 ++++ 11 files changed, 466 insertions(+), 24 deletions(-) create mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaRepair.java create mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java create mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaTrigger.java create mode 100644 hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/package-info.java diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java index 27015d34a35a..43471c955f9d 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java @@ -279,6 +279,8 @@ public static boolean isReadOnly( case PrintCompactionLogDag: case GetSnapshotInfo: case GetServerDefaults: + case QuotaRepairStatus: + case QuotaRepairTrigger: return true; case CreateVolume: case SetVolumeProperty: diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java index 0f01761b17b1..5ddb540078f0 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java @@ -1153,4 +1153,17 @@ boolean setSafeMode(SafeModeAction action, boolean isChecked) * @throws IOException */ OzoneFsServerDefaults getServerDefaults() throws IOException; + + /** + * Get status of last triggered quota repair in OM. + * @return String + * @throws IOException + */ + String getQuotaRepairStatus() throws IOException; + + /** + * trigger quota repair in OM. + * @throws IOException + */ + void triggerQuotaRepair(List buckets) throws IOException; } diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java index d3e39550dfbc..96d7031474fe 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java @@ -2579,6 +2579,30 @@ public OzoneFsServerDefaults getServerDefaults() serverDefaultsResponse.getServerDefaults()); } + @Override + public String getQuotaRepairStatus() throws IOException { + OzoneManagerProtocolProtos.QuotaRepairStatusRequest quotaRepairStatusRequest = + OzoneManagerProtocolProtos.QuotaRepairStatusRequest.newBuilder() + .build(); + + OMRequest omRequest = createOMRequest(Type.QuotaRepairStatus) + .setQuotaRepairStatusRequest(quotaRepairStatusRequest).build(); + + OzoneManagerProtocolProtos.QuotaRepairStatusResponse quotaRepairStatusResponse + = handleError(submitRequest(omRequest)).getQuotaRepairStatusResponse(); + return quotaRepairStatusResponse.getStatus(); + } + + @Override + public void triggerQuotaRepair(List buckets) throws IOException { + OzoneManagerProtocolProtos.QuotaRepairTriggerRequest quotaRepairTriggerRequest = + OzoneManagerProtocolProtos.QuotaRepairTriggerRequest.newBuilder() + .build(); + OMRequest omRequest = createOMRequest(Type.QuotaRepairTrigger) + .setQuotaRepairTriggerRequest(quotaRepairTriggerRequest).build(); + handleError(submitRequest(omRequest)).getQuotaRepairTriggerResponse(); + } + private SafeMode toProtoBuf(SafeModeAction action) { switch (action) { case ENTER: diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto index eeddc5500527..2d64f9c05486 100644 --- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto +++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto @@ -151,6 +151,8 @@ enum Type { ListOpenFiles = 132; QuotaRepair = 133; GetServerDefaults = 134; + QuotaRepairStatus = 135; + QuotaRepairTrigger = 136; } enum SafeMode { @@ -291,6 +293,8 @@ message OMRequest { optional ListOpenFilesRequest ListOpenFilesRequest = 130; optional QuotaRepairRequest QuotaRepairRequest = 131; optional ServerDefaultsRequest ServerDefaultsRequest = 132; + optional QuotaRepairStatusRequest QuotaRepairStatusRequest = 133; + optional QuotaRepairTriggerRequest QuotaRepairTriggerRequest = 134; } message OMResponse { @@ -419,6 +423,8 @@ message OMResponse { optional ListOpenFilesResponse ListOpenFilesResponse = 133; optional QuotaRepairResponse QuotaRepairResponse = 134; optional ServerDefaultsResponse ServerDefaultsResponse = 135; + optional QuotaRepairStatusResponse QuotaRepairStatusResponse = 136; + optional QuotaRepairTriggerResponse QuotaRepairTriggerResponse = 137; } enum Status { @@ -2226,6 +2232,17 @@ message ServerDefaultsResponse { required FsServerDefaultsProto serverDefaults = 1; } +message QuotaRepairStatusRequest { +} +message QuotaRepairStatusResponse { + optional string status = 1; +} +message QuotaRepairTriggerRequest { + repeated string buckets = 1; +} +message QuotaRepairTriggerResponse { +} + message OMLockDetailsProto { optional bool isLockAcquired = 1; optional uint64 waitLockNanos = 2; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java index 602158bb5c33..19af2c8611f4 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java @@ -106,6 +106,7 @@ import org.apache.hadoop.ozone.om.s3.S3SecretCacheProvider; import org.apache.hadoop.ozone.om.s3.S3SecretStoreProvider; import org.apache.hadoop.ozone.om.service.OMRangerBGSyncService; +import org.apache.hadoop.ozone.om.service.QuotaRepairTask; import org.apache.hadoop.ozone.om.snapshot.OmSnapshotUtils; import org.apache.hadoop.ozone.om.snapshot.ReferenceCounted; import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; @@ -4751,6 +4752,16 @@ public OzoneFsServerDefaults getServerDefaults() { return serverDefaults; } + @Override + public String getQuotaRepairStatus() throws IOException { + return QuotaRepairTask.getStatus(); + } + + @Override + public void triggerQuotaRepair(List buckets) throws IOException { + new QuotaRepairTask(this).repair(buckets); + } + /** * Write down Layout version of a finalized feature to DB on finalization. * @param lvm OMLayoutVersionManager diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java index b3e64c98c5dd..b5be58d21f15 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java @@ -26,6 +26,7 @@ import java.io.UncheckedIOException; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -48,6 +49,7 @@ import org.apache.hadoop.ozone.om.OMMetadataManager; import org.apache.hadoop.ozone.om.OmMetadataManagerImpl; import org.apache.hadoop.ozone.om.OzoneManager; +import org.apache.hadoop.ozone.om.exceptions.OMException; import org.apache.hadoop.ozone.om.helpers.BucketLayout; import org.apache.hadoop.ozone.om.helpers.OMRatisHelper; import org.apache.hadoop.ozone.om.helpers.OmBucketInfo; @@ -74,27 +76,31 @@ public class QuotaRepairTask { private static final int TASK_THREAD_CNT = 3; private static final AtomicBoolean IN_PROGRESS = new AtomicBoolean(false); private static final RepairStatus REPAIR_STATUS = new RepairStatus(); + private static final AtomicLong RUN_CNT = new AtomicLong(0); private final OzoneManager om; - private final AtomicLong runCount = new AtomicLong(0); private ExecutorService executor; public QuotaRepairTask(OzoneManager ozoneManager) { this.om = ozoneManager; } - public CompletableFuture repair() throws Exception { + public CompletableFuture repair() throws IOException { + return repair(Collections.emptyList()); + } + + public CompletableFuture repair(List buckets) throws IOException { // lock in progress operation and reject any other if (!IN_PROGRESS.compareAndSet(false, true)) { LOG.info("quota repair task already running"); - return CompletableFuture.supplyAsync(() -> false); + throw new OMException("Operation in progress", OMException.ResultCodes.QUOTA_ERROR); } - REPAIR_STATUS.reset(runCount.get() + 1); - return CompletableFuture.supplyAsync(() -> repairTask()); + REPAIR_STATUS.reset(RUN_CNT.get() + 1); + return CompletableFuture.supplyAsync(() -> repairTask(buckets)); } public static String getStatus() { return REPAIR_STATUS.toString(); } - private boolean repairTask() { + private boolean repairTask(List buckets) { LOG.info("Starting quota repair task {}", REPAIR_STATUS); OMMetadataManager activeMetaManager = null; try { @@ -104,7 +110,7 @@ private boolean repairTask() { = OzoneManagerProtocolProtos.QuotaRepairRequest.newBuilder(); // repair active db activeMetaManager = createActiveDBCheckpoint(om.getMetadataManager(), om.getConfiguration()); - repairActiveDb(activeMetaManager, builder); + repairActiveDb(activeMetaManager, builder, buckets); // TODO: repair snapshots for quota @@ -116,12 +122,12 @@ private boolean repairTask() { .setClientId(clientId.toString()) .build(); OzoneManagerProtocolProtos.OMResponse response = submitRequest(omRequest, clientId); - if (response != null && !response.getSuccess()) { + if (response != null && response.getSuccess()) { + REPAIR_STATUS.updateStatus(builder, om.getMetadataManager()); + } else { LOG.error("update quota repair count response failed"); REPAIR_STATUS.updateStatus("Response for update DB is failed"); return false; - } else { - REPAIR_STATUS.updateStatus(builder, om.getMetadataManager()); } } catch (Exception exp) { LOG.error("quota repair count failed", exp); @@ -145,11 +151,15 @@ private boolean repairTask() { private void repairActiveDb( OMMetadataManager metadataManager, - OzoneManagerProtocolProtos.QuotaRepairRequest.Builder builder) throws Exception { + OzoneManagerProtocolProtos.QuotaRepairRequest.Builder builder, + List buckets) throws Exception { Map nameBucketInfoMap = new HashMap<>(); Map idBucketInfoMap = new HashMap<>(); Map oriBucketInfoMap = new HashMap<>(); - prepareAllBucketInfo(nameBucketInfoMap, idBucketInfoMap, oriBucketInfoMap, metadataManager); + prepareAllBucketInfo(nameBucketInfoMap, idBucketInfoMap, oriBucketInfoMap, metadataManager, buckets); + if (nameBucketInfoMap.isEmpty()) { + throw new OMException("no matching buckets", OMException.ResultCodes.BUCKET_NOT_FOUND); + } repairCount(nameBucketInfoMap, idBucketInfoMap, metadataManager); @@ -178,7 +188,7 @@ private void repairActiveDb( } private OzoneManagerProtocolProtos.OMResponse submitRequest( - OzoneManagerProtocolProtos.OMRequest omRequest, ClientId clientId) { + OzoneManagerProtocolProtos.OMRequest omRequest, ClientId clientId) throws Exception { try { if (om.isRatisEnabled()) { OzoneManagerRatisServer server = om.getOmRatisServer(); @@ -186,19 +196,20 @@ private OzoneManagerProtocolProtos.OMResponse submitRequest( .setClientId(clientId) .setServerId(om.getOmRatisServer().getRaftPeerId()) .setGroupId(om.getOmRatisServer().getRaftGroupId()) - .setCallId(runCount.getAndIncrement()) + .setCallId(RUN_CNT.getAndIncrement()) .setMessage(Message.valueOf(OMRatisHelper.convertRequestToByteString(omRequest))) .setType(RaftClientRequest.writeRequestType()) .build(); return server.submitRequest(omRequest, raftClientRequest); } else { + RUN_CNT.getAndIncrement(); return om.getOmServerProtocol().submitRequest( null, omRequest); } } catch (ServiceException e) { LOG.error("repair quota count " + omRequest.getCmdType() + " request failed.", e); + throw e; } - return null; } private OMMetadataManager createActiveDBCheckpoint( @@ -228,24 +239,42 @@ private static String cleanTempCheckPointPath(OMMetadataManager omMetaManager) t private void prepareAllBucketInfo( Map nameBucketInfoMap, Map idBucketInfoMap, - Map oriBucketInfoMap, OMMetadataManager metadataManager) throws IOException { + Map oriBucketInfoMap, OMMetadataManager metadataManager, + List buckets) throws IOException { + if (!buckets.isEmpty()) { + for (String bucketkey : buckets) { + OmBucketInfo bucketInfo = metadataManager.getBucketTable().get(bucketkey); + if (null == bucketInfo) { + continue; + } + populateBucket(nameBucketInfoMap, idBucketInfoMap, oriBucketInfoMap, metadataManager, bucketInfo); + } + return; + } try (TableIterator> iterator = metadataManager.getBucketTable().iterator()) { while (iterator.hasNext()) { Table.KeyValue entry = iterator.next(); OmBucketInfo bucketInfo = entry.getValue(); - String bucketNameKey = buildNamePath(bucketInfo.getVolumeName(), - bucketInfo.getBucketName()); - oriBucketInfoMap.put(bucketNameKey, bucketInfo.copyObject()); - bucketInfo.incrUsedNamespace(-bucketInfo.getUsedNamespace()); - bucketInfo.incrUsedBytes(-bucketInfo.getUsedBytes()); - nameBucketInfoMap.put(bucketNameKey, bucketInfo); - idBucketInfoMap.put(buildIdPath(metadataManager.getVolumeId(bucketInfo.getVolumeName()), - bucketInfo.getObjectID()), bucketInfo); + populateBucket(nameBucketInfoMap, idBucketInfoMap, oriBucketInfoMap, metadataManager, bucketInfo); } } } + private static void populateBucket( + Map nameBucketInfoMap, Map idBucketInfoMap, + Map oriBucketInfoMap, OMMetadataManager metadataManager, + OmBucketInfo bucketInfo) throws IOException { + String bucketNameKey = buildNamePath(bucketInfo.getVolumeName(), + bucketInfo.getBucketName()); + oriBucketInfoMap.put(bucketNameKey, bucketInfo.copyObject()); + bucketInfo.incrUsedNamespace(-bucketInfo.getUsedNamespace()); + bucketInfo.incrUsedBytes(-bucketInfo.getUsedBytes()); + nameBucketInfoMap.put(bucketNameKey, bucketInfo); + idBucketInfoMap.put(buildIdPath(metadataManager.getVolumeId(bucketInfo.getVolumeName()), + bucketInfo.getObjectID()), bucketInfo); + } + private boolean isChange(OmBucketInfo lBucketInfo, OmBucketInfo rBucketInfo) { if (lBucketInfo.getUsedNamespace() != rBucketInfo.getUsedNamespace() || lBucketInfo.getUsedBytes() != rBucketInfo.getUsedBytes()) { diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java index f6bd7cca139b..e08522cca377 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java @@ -382,6 +382,16 @@ public OMResponse handleReadRequest(OMRequest request) { .setServerDefaults(impl.getServerDefaults().getProtobuf()) .build()); break; + case QuotaRepairStatus: + OzoneManagerProtocolProtos.QuotaRepairStatusResponse quotaRepairStatusRsp = + getQuotaRepairStatus(request.getQuotaRepairStatusRequest()); + responseBuilder.setQuotaRepairStatusResponse(quotaRepairStatusRsp); + break; + case QuotaRepairTrigger: + OzoneManagerProtocolProtos.QuotaRepairTriggerResponse quotaRepairTriggerRsp = + triggerQuotaRepair(request.getQuotaRepairTriggerRequest()); + responseBuilder.setQuotaRepairTriggerResponse(quotaRepairTriggerRsp); + break; default: responseBuilder.setSuccess(false); responseBuilder.setMessage("Unrecognized Command Type: " + cmdType); @@ -1521,4 +1531,16 @@ private SafeModeAction toSafeModeAction( safeMode); } } + + private OzoneManagerProtocolProtos.QuotaRepairStatusResponse getQuotaRepairStatus( + OzoneManagerProtocolProtos.QuotaRepairStatusRequest req) throws IOException { + return OzoneManagerProtocolProtos.QuotaRepairStatusResponse.newBuilder() + .setStatus(impl.getQuotaRepairStatus()) + .build(); + } + private OzoneManagerProtocolProtos.QuotaRepairTriggerResponse triggerQuotaRepair( + OzoneManagerProtocolProtos.QuotaRepairTriggerRequest req) throws IOException { + impl.triggerQuotaRepair(req.getBucketsList()); + return OzoneManagerProtocolProtos.QuotaRepairTriggerResponse.newBuilder().build(); + } } diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaRepair.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaRepair.java new file mode 100644 index 000000000000..5f21b739c818 --- /dev/null +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaRepair.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.ozone.repair.quota; + +import java.io.IOException; +import java.util.Collection; +import java.util.concurrent.Callable; +import org.apache.hadoop.hdds.cli.GenericCli; +import org.apache.hadoop.hdds.cli.SubcommandWithParent; +import org.apache.hadoop.hdds.conf.OzoneConfiguration; +import org.apache.hadoop.ipc.ProtobufRpcEngine; +import org.apache.hadoop.ipc.RPC; +import org.apache.hadoop.ozone.OmUtils; +import org.apache.hadoop.ozone.client.OzoneClientException; +import org.apache.hadoop.ozone.om.protocolPB.Hadoop3OmTransportFactory; +import org.apache.hadoop.ozone.om.protocolPB.OmTransport; +import org.apache.hadoop.ozone.om.protocolPB.OzoneManagerProtocolClientSideTranslatorPB; +import org.apache.hadoop.ozone.om.protocolPB.OzoneManagerProtocolPB; +import org.apache.hadoop.ozone.repair.OzoneRepair; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.ratis.protocol.ClientId; +import org.kohsuke.MetaInfServices; +import picocli.CommandLine; + +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ADDRESS_KEY; +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_SERVICE_IDS_KEY; + +/** + * Ozone Repair CLI for quota. + */ +@CommandLine.Command(name = "quota", + description = "Operational tool to repair quota in OM DB.") +@MetaInfServices(SubcommandWithParent.class) +public class QuotaRepair implements Callable, SubcommandWithParent { + + @CommandLine.Spec + private CommandLine.Model.CommandSpec spec; + + @CommandLine.ParentCommand + private OzoneRepair parent; + + @Override + public Void call() { + GenericCli.missingSubcommand(spec); + return null; + } + + public OzoneManagerProtocolClientSideTranslatorPB createOmClient( + String omServiceID, + String omHost, + boolean forceHA + ) throws Exception { + OzoneConfiguration conf = parent.getOzoneConf(); + if (omHost != null && !omHost.isEmpty()) { + omServiceID = null; + conf.set(OZONE_OM_ADDRESS_KEY, omHost); + } else if (omServiceID == null || omServiceID.isEmpty()) { + omServiceID = getTheOnlyConfiguredOmServiceIdOrThrow(); + } + RPC.setProtocolEngine(conf, OzoneManagerProtocolPB.class, + ProtobufRpcEngine.class); + String clientId = ClientId.randomId().toString(); + if (!forceHA || (forceHA && OmUtils.isOmHAServiceId(conf, omServiceID))) { + OmTransport omTransport = new Hadoop3OmTransportFactory() + .createOmTransport(conf, getUser(), omServiceID); + return new OzoneManagerProtocolClientSideTranslatorPB(omTransport, + clientId); + } else { + throw new OzoneClientException("This command works only on OzoneManager" + + " HA cluster. Service ID specified does not match" + + " with " + OZONE_OM_SERVICE_IDS_KEY + " defined in the " + + "configuration. Configured " + OZONE_OM_SERVICE_IDS_KEY + " are " + + conf.getTrimmedStringCollection(OZONE_OM_SERVICE_IDS_KEY) + "\n"); + } + } + + private String getTheOnlyConfiguredOmServiceIdOrThrow() { + if (getConfiguredServiceIds().size() != 1) { + throw new IllegalArgumentException("There is no Ozone Manager service ID " + + "specified, but there are either zero, or more than one service ID" + + "configured."); + } + return getConfiguredServiceIds().iterator().next(); + } + + private Collection getConfiguredServiceIds() { + OzoneConfiguration conf = parent.getOzoneConf(); + Collection omServiceIds = + conf.getTrimmedStringCollection(OZONE_OM_SERVICE_IDS_KEY); + return omServiceIds; + } + + public UserGroupInformation getUser() throws IOException { + return UserGroupInformation.getCurrentUser(); + } + + protected OzoneRepair getParent() { + return parent; + } + + @Override + public Class getParentType() { + return OzoneRepair.class; + } +} diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java new file mode 100644 index 000000000000..cf5019ade9d0 --- /dev/null +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java @@ -0,0 +1,81 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license + * agreements. See the NOTICE file distributed with this work for additional + * information regarding + * copyright ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a + * copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software + * distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and + * limitations under the License. + */ +package org.apache.hadoop.ozone.repair.quota; + +import java.util.concurrent.Callable; +import org.apache.commons.lang3.StringUtils; +import org.apache.hadoop.hdds.cli.HddsVersionProvider; +import org.apache.hadoop.hdds.cli.SubcommandWithParent; +import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol; +import org.kohsuke.MetaInfServices; +import picocli.CommandLine; + + +/** + * Tool to get status of last triggered quota repair. + */ +@CommandLine.Command( + name = "status", + description = "CLI to get the status of last trigger quota repair if available.", + mixinStandardHelpOptions = true, + versionProvider = HddsVersionProvider.class +) +@MetaInfServices(SubcommandWithParent.class) +public class QuotaStatus implements Callable, SubcommandWithParent { + @CommandLine.Spec + private static CommandLine.Model.CommandSpec spec; + + @CommandLine.Option( + names = {"--service-id", "--om-service-id"}, + description = "Ozone Manager Service ID", + required = false + ) + private String omServiceId; + + @CommandLine.Option( + names = {"--service-host"}, + description = "Ozone Manager Host. If OM HA is enabled, use --service-id instead. " + + "If you must use --service-host with OM HA, this must point directly to the leader OM. " + + "This option is required when --service-id is not provided or when HA is not enabled." + ) + private String omHost; + + @CommandLine.ParentCommand + private QuotaRepair parent; + + @Override + public Void call() throws Exception { + OzoneManagerProtocol ozoneManagerClient = + parent.createOmClient(omServiceId, omHost, false); + System.out.println(ozoneManagerClient.getQuotaRepairStatus()); + return null; + } + + protected QuotaRepair getParent() { + return parent; + } + + @Override + public Class getParentType() { + return QuotaRepair.class; + } +} diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaTrigger.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaTrigger.java new file mode 100644 index 000000000000..1cafabba709e --- /dev/null +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaTrigger.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license + * agreements. See the NOTICE file distributed with this work for additional + * information regarding + * copyright ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a + * copy of the License at + * + *

http://www.apache.org/licenses/LICENSE-2.0 + * + *

Unless required by applicable law or agreed to in writing, software + * distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and + * limitations under the License. + */ +package org.apache.hadoop.ozone.repair.quota; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Callable; +import org.apache.commons.lang3.StringUtils; +import org.apache.hadoop.hdds.cli.HddsVersionProvider; +import org.apache.hadoop.hdds.cli.SubcommandWithParent; +import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol; +import org.kohsuke.MetaInfServices; +import picocli.CommandLine; + +/** + * Tool to trigger quota repair. + */ +@CommandLine.Command( + name = "trigger", + description = "CLI to trigger quota repair.", + mixinStandardHelpOptions = true, + versionProvider = HddsVersionProvider.class +) +@MetaInfServices(SubcommandWithParent.class) +public class QuotaTrigger implements Callable, SubcommandWithParent { + @CommandLine.Spec + private static CommandLine.Model.CommandSpec spec; + + @CommandLine.ParentCommand + private QuotaRepair parent; + + @CommandLine.Option( + names = {"--service-id", "--om-service-id"}, + description = "Ozone Manager Service ID", + required = false + ) + private String omServiceId; + + @CommandLine.Option( + names = {"--service-host"}, + description = "Ozone Manager Host. If OM HA is enabled, use --service-id instead. " + + "If you must use --service-host with OM HA, this must point directly to the leader OM. " + + "This option is required when --service-id is not provided or when HA is not enabled." + ) + private String omHost; + + @CommandLine.Option(names = {"--buckets"}, + required = false, + description = "trigger quota repair for specific buckets. Input will be list of uri separated by comma as" + + " //[,...]") + private String buckets; + + @Override + public Void call() throws Exception { + List bucketList = Collections.emptyList(); + if (StringUtils.isNotEmpty(buckets)) { + bucketList = Arrays.asList(buckets.split(",")); + } + + OzoneManagerProtocol ozoneManagerClient = + parent.createOmClient(omServiceId, omHost, false); + try { + ozoneManagerClient.triggerQuotaRepair(bucketList); + System.out.println(ozoneManagerClient.getQuotaRepairStatus()); + } catch (Exception ex) { + System.out.println(ex.getMessage()); + } + return null; + } + + protected QuotaRepair getParent() { + return parent; + } + + @Override + public Class getParentType() { + return QuotaRepair.class; + } + +} diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/package-info.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/package-info.java new file mode 100644 index 000000000000..9a433b24397a --- /dev/null +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Ozone Repair tools. + */ +package org.apache.hadoop.ozone.repair.quota; From a5b5421715791f4bb8b1c0b2dc465839f74e4d46 Mon Sep 17 00:00:00 2001 From: Sumit Agrawal Date: Wed, 7 Aug 2024 22:41:12 +0530 Subject: [PATCH 2/7] test case --- .../ozone/shell/TestOzoneRepairShell.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java index 328fc1ddd8c2..f4400454fc2f 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java @@ -22,8 +22,13 @@ import org.apache.hadoop.ozone.debug.DBScanner; import org.apache.hadoop.ozone.debug.RDBParser; import org.apache.hadoop.ozone.om.OMStorage; +import org.apache.hadoop.ozone.repair.OzoneRepair; import org.apache.hadoop.ozone.repair.RDBRepair; import org.apache.hadoop.ozone.repair.TransactionInfoRepair; +import org.apache.hadoop.ozone.repair.quota.QuotaRepair; +import org.apache.hadoop.ozone.repair.quota.QuotaStatus; +import org.apache.hadoop.ozone.repair.quota.QuotaTrigger; +import org.apache.ozone.test.GenericTestUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -38,6 +43,7 @@ import java.util.regex.Pattern; import static org.apache.hadoop.ozone.OzoneConsts.OM_DB_NAME; +import static org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_ADDRESS_KEY; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static java.nio.charset.StandardCharsets.UTF_8; @@ -130,4 +136,28 @@ private String[] parseScanOutput(String output) throws IOException { throw new IllegalStateException("Failed to scan and find raft's highest term and index from TransactionInfo table"); } + @Test + public void testQuotaRepair() throws Exception { + CommandLine cmd = new CommandLine(new OzoneRepair()).addSubcommand(new CommandLine(new QuotaRepair()) + .addSubcommand(new QuotaStatus()).addSubcommand(new QuotaTrigger())); + + String[] args = new String[] {"quota", "status", "--service-host", conf.get(OZONE_OM_ADDRESS_KEY)}; + int exitCode = cmd.execute(args); + assertEquals(0, exitCode); + args = new String[] {"quota", "trigger", "--service-host", conf.get(OZONE_OM_ADDRESS_KEY)}; + exitCode = cmd.execute(args); + assertEquals(0, exitCode); + GenericTestUtils.waitFor(() -> { + out.reset(); + // verify quota trigger is completed having non-zero lastRunFinishedTime + String[] targs = new String[]{"quota", "status", "--service-host", conf.get(OZONE_OM_ADDRESS_KEY)}; + cmd.execute(targs); + try { + return !out.toString(DEFAULT_ENCODING).contains("\"lastRunFinishedTime\":0"); + } catch (Exception ex) { + // do nothing + } + return false; + }, 1000, 10000); + } } From 5b22db89f159141455e24cb8d48b5dc86034f271 Mon Sep 17 00:00:00 2001 From: Sumit Agrawal Date: Wed, 14 Aug 2024 16:59:03 +0530 Subject: [PATCH 3/7] check for admin access --- .../src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java index 19af2c8611f4..d4063d9a2016 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java @@ -4754,11 +4754,13 @@ public OzoneFsServerDefaults getServerDefaults() { @Override public String getQuotaRepairStatus() throws IOException { + checkAdminUserPrivilege("quota repair status"); return QuotaRepairTask.getStatus(); } @Override public void triggerQuotaRepair(List buckets) throws IOException { + checkAdminUserPrivilege("trigger quota repair"); new QuotaRepairTask(this).repair(buckets); } From b81661635794701efb924483407abc5d495af136 Mon Sep 17 00:00:00 2001 From: Sumit Agrawal Date: Wed, 14 Aug 2024 17:04:12 +0530 Subject: [PATCH 4/7] fix old volume quota update for all --- .../org/apache/hadoop/ozone/om/service/QuotaRepairTask.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java index b5be58d21f15..e72de5ebd49d 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java @@ -184,7 +184,11 @@ private void repairActiveDb( } // update volume to support quota - builder.setSupportVolumeOldQuota(true); + if (buckets.isEmpty()) { + builder.setSupportVolumeOldQuota(true); + } else { + builder.setSupportVolumeOldQuota(false); + } } private OzoneManagerProtocolProtos.OMResponse submitRequest( From 27e159f6d93ad9906885c3b764a4c5a94aa9df3b Mon Sep 17 00:00:00 2001 From: Sumit Agrawal Date: Wed, 21 Aug 2024 15:09:46 +0530 Subject: [PATCH 5/7] checkstyle and findbug --- .../protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java | 2 +- .../java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java index 96d7031474fe..e0979fcce642 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java @@ -2600,7 +2600,7 @@ public void triggerQuotaRepair(List buckets) throws IOException { .build(); OMRequest omRequest = createOMRequest(Type.QuotaRepairTrigger) .setQuotaRepairTriggerRequest(quotaRepairTriggerRequest).build(); - handleError(submitRequest(omRequest)).getQuotaRepairTriggerResponse(); + handleError(submitRequest(omRequest)); } private SafeMode toProtoBuf(SafeModeAction action) { diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java index cf5019ade9d0..a78d248e055c 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaStatus.java @@ -22,7 +22,6 @@ package org.apache.hadoop.ozone.repair.quota; import java.util.concurrent.Callable; -import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.hdds.cli.HddsVersionProvider; import org.apache.hadoop.hdds.cli.SubcommandWithParent; import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol; From fceb98c369a7d05f39ccef2d9de0403c99f3d273 Mon Sep 17 00:00:00 2001 From: Sumit Agrawal Date: Wed, 4 Sep 2024 15:56:49 +0530 Subject: [PATCH 6/7] review comment fix --- .../java/org/apache/hadoop/ozone/OmUtils.java | 4 +-- .../om/protocol/OzoneManagerProtocol.java | 4 +-- ...ManagerProtocolClientSideTranslatorPB.java | 22 +++++++------- .../ozone/shell/TestOzoneRepairShell.java | 2 +- .../src/main/proto/OmClientProtocol.proto | 20 ++++++------- .../apache/hadoop/ozone/om/OzoneManager.java | 4 +-- .../ozone/om/service/QuotaRepairTask.java | 2 +- .../OzoneManagerRequestHandler.java | 30 +++++++++---------- .../ozone/repair/quota/QuotaTrigger.java | 6 ++-- 9 files changed, 47 insertions(+), 47 deletions(-) diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java index 43471c955f9d..8fa8921cc9a9 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java @@ -279,8 +279,8 @@ public static boolean isReadOnly( case PrintCompactionLogDag: case GetSnapshotInfo: case GetServerDefaults: - case QuotaRepairStatus: - case QuotaRepairTrigger: + case GetQuotaRepairStatus: + case StartQuotaRepair: return true; case CreateVolume: case SetVolumeProperty: diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java index 5ddb540078f0..37481b00ea28 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java @@ -1162,8 +1162,8 @@ boolean setSafeMode(SafeModeAction action, boolean isChecked) String getQuotaRepairStatus() throws IOException; /** - * trigger quota repair in OM. + * start quota repair in OM. * @throws IOException */ - void triggerQuotaRepair(List buckets) throws IOException; + void startQuotaRepair(List buckets) throws IOException; } diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java index e0979fcce642..bdd1428b16dc 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java @@ -2581,25 +2581,25 @@ public OzoneFsServerDefaults getServerDefaults() @Override public String getQuotaRepairStatus() throws IOException { - OzoneManagerProtocolProtos.QuotaRepairStatusRequest quotaRepairStatusRequest = - OzoneManagerProtocolProtos.QuotaRepairStatusRequest.newBuilder() + OzoneManagerProtocolProtos.GetQuotaRepairStatusRequest quotaRepairStatusRequest = + OzoneManagerProtocolProtos.GetQuotaRepairStatusRequest.newBuilder() .build(); - OMRequest omRequest = createOMRequest(Type.QuotaRepairStatus) - .setQuotaRepairStatusRequest(quotaRepairStatusRequest).build(); + OMRequest omRequest = createOMRequest(Type.GetQuotaRepairStatus) + .setGetQuotaRepairStatusRequest(quotaRepairStatusRequest).build(); - OzoneManagerProtocolProtos.QuotaRepairStatusResponse quotaRepairStatusResponse - = handleError(submitRequest(omRequest)).getQuotaRepairStatusResponse(); + OzoneManagerProtocolProtos.GetQuotaRepairStatusResponse quotaRepairStatusResponse + = handleError(submitRequest(omRequest)).getGetQuotaRepairStatusResponse(); return quotaRepairStatusResponse.getStatus(); } @Override - public void triggerQuotaRepair(List buckets) throws IOException { - OzoneManagerProtocolProtos.QuotaRepairTriggerRequest quotaRepairTriggerRequest = - OzoneManagerProtocolProtos.QuotaRepairTriggerRequest.newBuilder() + public void startQuotaRepair(List buckets) throws IOException { + OzoneManagerProtocolProtos.StartQuotaRepairRequest startQuotaRepairRequest = + OzoneManagerProtocolProtos.StartQuotaRepairRequest.newBuilder() .build(); - OMRequest omRequest = createOMRequest(Type.QuotaRepairTrigger) - .setQuotaRepairTriggerRequest(quotaRepairTriggerRequest).build(); + OMRequest omRequest = createOMRequest(Type.StartQuotaRepair) + .setStartQuotaRepairRequest(startQuotaRepairRequest).build(); handleError(submitRequest(omRequest)); } diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java index f4400454fc2f..e38e146c06bb 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java @@ -144,7 +144,7 @@ public void testQuotaRepair() throws Exception { String[] args = new String[] {"quota", "status", "--service-host", conf.get(OZONE_OM_ADDRESS_KEY)}; int exitCode = cmd.execute(args); assertEquals(0, exitCode); - args = new String[] {"quota", "trigger", "--service-host", conf.get(OZONE_OM_ADDRESS_KEY)}; + args = new String[] {"quota", "start", "--service-host", conf.get(OZONE_OM_ADDRESS_KEY)}; exitCode = cmd.execute(args); assertEquals(0, exitCode); GenericTestUtils.waitFor(() -> { diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto index 2d64f9c05486..e79797993c13 100644 --- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto +++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto @@ -151,8 +151,8 @@ enum Type { ListOpenFiles = 132; QuotaRepair = 133; GetServerDefaults = 134; - QuotaRepairStatus = 135; - QuotaRepairTrigger = 136; + GetQuotaRepairStatus = 135; + StartQuotaRepair = 136; } enum SafeMode { @@ -293,8 +293,8 @@ message OMRequest { optional ListOpenFilesRequest ListOpenFilesRequest = 130; optional QuotaRepairRequest QuotaRepairRequest = 131; optional ServerDefaultsRequest ServerDefaultsRequest = 132; - optional QuotaRepairStatusRequest QuotaRepairStatusRequest = 133; - optional QuotaRepairTriggerRequest QuotaRepairTriggerRequest = 134; + optional GetQuotaRepairStatusRequest GetQuotaRepairStatusRequest = 133; + optional StartQuotaRepairRequest StartQuotaRepairRequest = 134; } message OMResponse { @@ -423,8 +423,8 @@ message OMResponse { optional ListOpenFilesResponse ListOpenFilesResponse = 133; optional QuotaRepairResponse QuotaRepairResponse = 134; optional ServerDefaultsResponse ServerDefaultsResponse = 135; - optional QuotaRepairStatusResponse QuotaRepairStatusResponse = 136; - optional QuotaRepairTriggerResponse QuotaRepairTriggerResponse = 137; + optional GetQuotaRepairStatusResponse GetQuotaRepairStatusResponse = 136; + optional StartQuotaRepairResponse StartQuotaRepairResponse = 137; } enum Status { @@ -2232,15 +2232,15 @@ message ServerDefaultsResponse { required FsServerDefaultsProto serverDefaults = 1; } -message QuotaRepairStatusRequest { +message GetQuotaRepairStatusRequest { } -message QuotaRepairStatusResponse { +message GetQuotaRepairStatusResponse { optional string status = 1; } -message QuotaRepairTriggerRequest { +message StartQuotaRepairRequest { repeated string buckets = 1; } -message QuotaRepairTriggerResponse { +message StartQuotaRepairResponse { } message OMLockDetailsProto { diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java index d4063d9a2016..b6903ca9e91f 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java @@ -4759,8 +4759,8 @@ public String getQuotaRepairStatus() throws IOException { } @Override - public void triggerQuotaRepair(List buckets) throws IOException { - checkAdminUserPrivilege("trigger quota repair"); + public void startQuotaRepair(List buckets) throws IOException { + checkAdminUserPrivilege("start quota repair"); new QuotaRepairTask(this).repair(buckets); } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java index e72de5ebd49d..9b3a2ad3db35 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java @@ -91,7 +91,7 @@ public CompletableFuture repair(List buckets) throws IOExceptio // lock in progress operation and reject any other if (!IN_PROGRESS.compareAndSet(false, true)) { LOG.info("quota repair task already running"); - throw new OMException("Operation in progress", OMException.ResultCodes.QUOTA_ERROR); + throw new OMException("Quota repair is already running", OMException.ResultCodes.QUOTA_ERROR); } REPAIR_STATUS.reset(RUN_CNT.get() + 1); return CompletableFuture.supplyAsync(() -> repairTask(buckets)); diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java index e08522cca377..576fac48c736 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java @@ -382,15 +382,15 @@ public OMResponse handleReadRequest(OMRequest request) { .setServerDefaults(impl.getServerDefaults().getProtobuf()) .build()); break; - case QuotaRepairStatus: - OzoneManagerProtocolProtos.QuotaRepairStatusResponse quotaRepairStatusRsp = - getQuotaRepairStatus(request.getQuotaRepairStatusRequest()); - responseBuilder.setQuotaRepairStatusResponse(quotaRepairStatusRsp); + case GetQuotaRepairStatus: + OzoneManagerProtocolProtos.GetQuotaRepairStatusResponse quotaRepairStatusRsp = + getQuotaRepairStatus(request.getGetQuotaRepairStatusRequest()); + responseBuilder.setGetQuotaRepairStatusResponse(quotaRepairStatusRsp); break; - case QuotaRepairTrigger: - OzoneManagerProtocolProtos.QuotaRepairTriggerResponse quotaRepairTriggerRsp = - triggerQuotaRepair(request.getQuotaRepairTriggerRequest()); - responseBuilder.setQuotaRepairTriggerResponse(quotaRepairTriggerRsp); + case StartQuotaRepair: + OzoneManagerProtocolProtos.StartQuotaRepairResponse startQuotaRepairRsp = + startQuotaRepair(request.getStartQuotaRepairRequest()); + responseBuilder.setStartQuotaRepairResponse(startQuotaRepairRsp); break; default: responseBuilder.setSuccess(false); @@ -1532,15 +1532,15 @@ private SafeModeAction toSafeModeAction( } } - private OzoneManagerProtocolProtos.QuotaRepairStatusResponse getQuotaRepairStatus( - OzoneManagerProtocolProtos.QuotaRepairStatusRequest req) throws IOException { - return OzoneManagerProtocolProtos.QuotaRepairStatusResponse.newBuilder() + private OzoneManagerProtocolProtos.GetQuotaRepairStatusResponse getQuotaRepairStatus( + OzoneManagerProtocolProtos.GetQuotaRepairStatusRequest req) throws IOException { + return OzoneManagerProtocolProtos.GetQuotaRepairStatusResponse.newBuilder() .setStatus(impl.getQuotaRepairStatus()) .build(); } - private OzoneManagerProtocolProtos.QuotaRepairTriggerResponse triggerQuotaRepair( - OzoneManagerProtocolProtos.QuotaRepairTriggerRequest req) throws IOException { - impl.triggerQuotaRepair(req.getBucketsList()); - return OzoneManagerProtocolProtos.QuotaRepairTriggerResponse.newBuilder().build(); + private OzoneManagerProtocolProtos.StartQuotaRepairResponse startQuotaRepair( + OzoneManagerProtocolProtos.StartQuotaRepairRequest req) throws IOException { + impl.startQuotaRepair(req.getBucketsList()); + return OzoneManagerProtocolProtos.StartQuotaRepairResponse.newBuilder().build(); } } diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaTrigger.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaTrigger.java index 1cafabba709e..19ad92340c06 100644 --- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaTrigger.java +++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/repair/quota/QuotaTrigger.java @@ -36,7 +36,7 @@ * Tool to trigger quota repair. */ @CommandLine.Command( - name = "trigger", + name = "start", description = "CLI to trigger quota repair.", mixinStandardHelpOptions = true, versionProvider = HddsVersionProvider.class @@ -66,7 +66,7 @@ public class QuotaTrigger implements Callable, SubcommandWithParent { @CommandLine.Option(names = {"--buckets"}, required = false, - description = "trigger quota repair for specific buckets. Input will be list of uri separated by comma as" + + description = "start quota repair for specific buckets. Input will be list of uri separated by comma as" + " //[,...]") private String buckets; @@ -80,7 +80,7 @@ public Void call() throws Exception { OzoneManagerProtocol ozoneManagerClient = parent.createOmClient(omServiceId, omHost, false); try { - ozoneManagerClient.triggerQuotaRepair(bucketList); + ozoneManagerClient.startQuotaRepair(bucketList); System.out.println(ozoneManagerClient.getQuotaRepairStatus()); } catch (Exception ex) { System.out.println(ex.getMessage()); From 5382f79a52b7a50b988c9211e7dd930aff11a0f0 Mon Sep 17 00:00:00 2001 From: Sumit Agrawal Date: Thu, 5 Sep 2024 10:30:41 +0530 Subject: [PATCH 7/7] comment fix date format --- .../org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java | 2 +- .../org/apache/hadoop/ozone/om/service/QuotaRepairTask.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java index e38e146c06bb..9216c909ee4b 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneRepairShell.java @@ -153,7 +153,7 @@ public void testQuotaRepair() throws Exception { String[] targs = new String[]{"quota", "status", "--service-host", conf.get(OZONE_OM_ADDRESS_KEY)}; cmd.execute(targs); try { - return !out.toString(DEFAULT_ENCODING).contains("\"lastRunFinishedTime\":0"); + return !out.toString(DEFAULT_ENCODING).contains("\"lastRunFinishedTime\":\"\""); } catch (Exception ex) { // do nothing } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java index 9b3a2ad3db35..c043a6a72f24 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/service/QuotaRepairTask.java @@ -501,8 +501,9 @@ public String toString() { } Map status = new HashMap<>(); status.put("taskId", taskId); - status.put("lastRunStartTime", lastRunStartTime); - status.put("lastRunFinishedTime", lastRunFinishedTime); + status.put("lastRunStartTime", lastRunStartTime > 0 ? new java.util.Date(lastRunStartTime).toString() : ""); + status.put("lastRunFinishedTime", lastRunFinishedTime > 0 ? new java.util.Date(lastRunFinishedTime).toString() + : ""); status.put("errorMsg", errorMsg); status.put("bucketCountDiffMap", bucketCountDiffMap); try {