This is an automated email from the ASF dual-hosted git repository.
adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new b94fcbcc739 HDDS-15190. Add ScmInvoker subclasses for CertificateStore
and RootCARotationHandler (#10226)
b94fcbcc739 is described below
commit b94fcbcc739084382617beaccd4d627de144a82f
Author: Bolin Lin <[email protected]>
AuthorDate: Wed May 13 07:05:52 2026 -0400
HDDS-15190. Add ScmInvoker subclasses for CertificateStore and
RootCARotationHandler (#10226)
---
.../scm/ha/invoker/CertificateStoreInvoker.java | 162 +++++++++++++++++++++
.../ha/invoker/RootCARotationHandlerInvoker.java | 161 ++++++++++++++++++++
.../hadoop/hdds/scm/ha/invoker/ScmInvoker.java | 19 +++
.../hdds/scm/security/RootCARotationHandler.java | 5 +
.../scm/security/RootCARotationHandlerImpl.java | 3 +-
.../hadoop/hdds/scm/server/SCMCertStore.java | 3 +-
.../hadoop/hdds/scm/server/TestSCMCertStore.java | 11 +-
7 files changed, 357 insertions(+), 7 deletions(-)
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/CertificateStoreInvoker.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/CertificateStoreInvoker.java
new file mode 100644
index 00000000000..2305dc542e2
--- /dev/null
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/CertificateStoreInvoker.java
@@ -0,0 +1,162 @@
+/*
+ * 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.hdds.scm.ha.invoker;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType;
+import org.apache.hadoop.hdds.scm.ha.SCMRatisResponse;
+import org.apache.hadoop.hdds.scm.ha.SCMRatisServer;
+import org.apache.hadoop.hdds.scm.metadata.SCMMetadataStore;
+import
org.apache.hadoop.hdds.security.x509.certificate.authority.CertificateStore;
+import org.apache.ratis.protocol.Message;
+
+/** Code generated for {@link CertificateStore}. Do not modify. */
+public class CertificateStoreInvoker extends ScmInvoker<CertificateStore> {
+ enum ReplicateMethod implements NameAndParameterTypes {
+ removeAllExpiredCertificates(new Class<?>[][] {
+ new Class<?>[] {}
+ }),
+ storeValidCertificate(new Class<?>[][] {
+ null,
+ null,
+ null,
+ new Class<?>[] {BigInteger.class, X509Certificate.class,
NodeType.class}
+ });
+
+ private final Class<?>[][] parameterTypes;
+
+ ReplicateMethod(Class<?>[][] parameterTypes) {
+ this.parameterTypes = parameterTypes;
+ }
+
+ @Override
+ public Class<?>[] getParameterTypes(int numArgs) {
+ return parameterTypes[numArgs];
+ }
+ }
+
+ public CertificateStoreInvoker(CertificateStore impl, SCMRatisServer ratis) {
+ super(impl, CertificateStoreInvoker::newProxy, ratis);
+ }
+
+ @Override
+ public Class<CertificateStore> getApi() {
+ return CertificateStore.class;
+ }
+
+ static CertificateStore newProxy(ScmInvoker<CertificateStore> invoker) {
+ return new CertificateStore() {
+
+ @Override
+ public void checkValidCertID(BigInteger arg0) throws IOException {
+ invoker.getImpl().checkValidCertID(arg0);
+ }
+
+ @Override
+ public X509Certificate getCertificateByID(BigInteger arg0) throws
IOException {
+ return invoker.getImpl().getCertificateByID(arg0);
+ }
+
+ @Override
+ public List<X509Certificate> listCertificate(NodeType arg0, BigInteger
arg1, int arg2) throws IOException {
+ return invoker.getImpl().listCertificate(arg0, arg1, arg2);
+ }
+
+ @Override
+ public void reinitialize(SCMMetadataStore arg0) {
+ invoker.getImpl().reinitialize(arg0);
+ }
+
+ @Override
+ public List<X509Certificate> removeAllExpiredCertificates() throws
IOException {
+ final Object[] args = {};
+ return (List<X509Certificate>)
invoker.invokeReplicateDirect(ReplicateMethod.removeAllExpiredCertificates,
+ args);
+ }
+
+ @Override
+ public void storeValidCertificate(BigInteger arg0, X509Certificate arg1,
NodeType arg2) throws IOException {
+ final Object[] args = {arg0, arg1, arg2};
+ invoker.invokeReplicateClient(ReplicateMethod.storeValidCertificate,
args);
+ }
+
+ @Override
+ public void storeValidScmCertificate(BigInteger arg0, X509Certificate
arg1) throws IOException {
+ invoker.getImpl().storeValidScmCertificate(arg0, arg1);
+ }
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Message invokeLocal(String methodName, Object[] p) throws Exception {
+ final Class<?> returnType;
+ final Object returnValue;
+ switch (methodName) {
+ case "checkValidCertID":
+ final BigInteger arg0 = p.length > 0 ? (BigInteger) p[0] : null;
+ getImpl().checkValidCertID(arg0);
+ return Message.EMPTY;
+
+ case "getCertificateByID":
+ final BigInteger arg1 = p.length > 0 ? (BigInteger) p[0] : null;
+ returnType = X509Certificate.class;
+ returnValue = getImpl().getCertificateByID(arg1);
+ break;
+
+ case "listCertificate":
+ final NodeType arg2 = p.length > 0 ? (NodeType) p[0] : null;
+ final BigInteger arg3 = p.length > 1 ? (BigInteger) p[1] : null;
+ final int arg4 = p.length > 2 ? (int) p[2] : 0;
+ returnType = List.class;
+ returnValue = getImpl().listCertificate(arg2, arg3, arg4);
+ break;
+
+ case "reinitialize":
+ final SCMMetadataStore arg5 = p.length > 0 ? (SCMMetadataStore) p[0] :
null;
+ getImpl().reinitialize(arg5);
+ return Message.EMPTY;
+
+ case "removeAllExpiredCertificates":
+ returnType = List.class;
+ returnValue = getImpl().removeAllExpiredCertificates();
+ break;
+
+ case "storeValidCertificate":
+ final BigInteger arg6 = p.length > 0 ? (BigInteger) p[0] : null;
+ final X509Certificate arg7 = p.length > 1 ? (X509Certificate) p[1] :
null;
+ final NodeType arg8 = p.length > 2 ? (NodeType) p[2] : null;
+ getImpl().storeValidCertificate(arg6, arg7, arg8);
+ return Message.EMPTY;
+
+ case "storeValidScmCertificate":
+ final BigInteger arg9 = p.length > 0 ? (BigInteger) p[0] : null;
+ final X509Certificate arg10 = p.length > 1 ? (X509Certificate) p[1] :
null;
+ getImpl().storeValidScmCertificate(arg9, arg10);
+ return Message.EMPTY;
+
+ default:
+ throw new IllegalArgumentException("Method not found: " + methodName + "
in CertificateStore");
+ }
+
+ return SCMRatisResponse.encode(returnValue, returnType);
+ }
+}
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/RootCARotationHandlerInvoker.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/RootCARotationHandlerInvoker.java
new file mode 100644
index 00000000000..15e1d92a313
--- /dev/null
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/RootCARotationHandlerInvoker.java
@@ -0,0 +1,161 @@
+/*
+ * 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.hdds.scm.ha.invoker;
+
+import java.io.IOException;
+import org.apache.hadoop.hdds.scm.ha.SCMRatisResponse;
+import org.apache.hadoop.hdds.scm.ha.SCMRatisServer;
+import org.apache.hadoop.hdds.scm.security.RootCARotationHandler;
+import org.apache.ratis.protocol.Message;
+
+/** Code generated for {@link RootCARotationHandler}. Do not modify. */
+public class RootCARotationHandlerInvoker extends
ScmInvoker<RootCARotationHandler> {
+ enum ReplicateMethod implements NameAndParameterTypes {
+ rotationCommit(new Class<?>[][] {
+ null,
+ new Class<?>[] {String.class}
+ }),
+ rotationCommitted(new Class<?>[][] {
+ null,
+ new Class<?>[] {String.class}
+ }),
+ rotationPrepare(new Class<?>[][] {
+ null,
+ new Class<?>[] {String.class}
+ }),
+ rotationPrepareAck(new Class<?>[][] {
+ null,
+ null,
+ null,
+ new Class<?>[] {String.class, String.class, String.class}
+ });
+
+ private final Class<?>[][] parameterTypes;
+
+ ReplicateMethod(Class<?>[][] parameterTypes) {
+ this.parameterTypes = parameterTypes;
+ }
+
+ @Override
+ public Class<?>[] getParameterTypes(int numArgs) {
+ return parameterTypes[numArgs];
+ }
+ }
+
+ public RootCARotationHandlerInvoker(RootCARotationHandler impl,
SCMRatisServer ratis) {
+ super(impl, RootCARotationHandlerInvoker::newProxy, ratis);
+ }
+
+ @Override
+ public Class<RootCARotationHandler> getApi() {
+ return RootCARotationHandler.class;
+ }
+
+ static RootCARotationHandler newProxy(ScmInvoker<RootCARotationHandler>
invoker) {
+ return new RootCARotationHandler() {
+
+ @Override
+ public void resetRotationPrepareAcks() {
+ invoker.getImpl().resetRotationPrepareAcks();
+ }
+
+ @Override
+ public void rotationCommit(String arg0) throws IOException {
+ final Object[] args = {arg0};
+ invoker.invokeReplicateDirect(ReplicateMethod.rotationCommit, args);
+ }
+
+ @Override
+ public void rotationCommitted(String arg0) throws IOException {
+ final Object[] args = {arg0};
+ invoker.invokeReplicateDirect(ReplicateMethod.rotationCommitted, args);
+ }
+
+ @Override
+ public void rotationPrepare(String arg0) throws IOException {
+ final Object[] args = {arg0};
+ invoker.invokeReplicateDirect(ReplicateMethod.rotationPrepare, args);
+ }
+
+ @Override
+ public void rotationPrepareAck(String arg0, String arg1, String arg2)
throws IOException {
+ final Object[] args = {arg0, arg1, arg2};
+ invoker.invokeReplicateClient(ReplicateMethod.rotationPrepareAck,
args);
+ }
+
+ @Override
+ public int rotationPrepareAcks() {
+ return invoker.getImpl().rotationPrepareAcks();
+ }
+
+ @Override
+ public void setSubCACertId(String arg0) {
+ invoker.getImpl().setSubCACertId(arg0);
+ }
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Message invokeLocal(String methodName, Object[] p) throws Exception {
+ final Class<?> returnType;
+ final Object returnValue;
+ switch (methodName) {
+ case "resetRotationPrepareAcks":
+ getImpl().resetRotationPrepareAcks();
+ return Message.EMPTY;
+
+ case "rotationCommit":
+ final String arg0 = p.length > 0 ? (String) p[0] : null;
+ getImpl().rotationCommit(arg0);
+ return Message.EMPTY;
+
+ case "rotationCommitted":
+ final String arg1 = p.length > 0 ? (String) p[0] : null;
+ getImpl().rotationCommitted(arg1);
+ return Message.EMPTY;
+
+ case "rotationPrepare":
+ final String arg2 = p.length > 0 ? (String) p[0] : null;
+ getImpl().rotationPrepare(arg2);
+ return Message.EMPTY;
+
+ case "rotationPrepareAck":
+ final String arg3 = p.length > 0 ? (String) p[0] : null;
+ final String arg4 = p.length > 1 ? (String) p[1] : null;
+ final String arg5 = p.length > 2 ? (String) p[2] : null;
+ getImpl().rotationPrepareAck(arg3, arg4, arg5);
+ return Message.EMPTY;
+
+ case "rotationPrepareAcks":
+ returnType = int.class;
+ returnValue = getImpl().rotationPrepareAcks();
+ break;
+
+ case "setSubCACertId":
+ final String arg6 = p.length > 0 ? (String) p[0] : null;
+ getImpl().setSubCACertId(arg6);
+ return Message.EMPTY;
+
+ default:
+ throw new IllegalArgumentException("Method not found: " + methodName + "
in RootCARotationHandler");
+ }
+
+ return SCMRatisResponse.encode(returnValue, returnType);
+ }
+}
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/ScmInvoker.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/ScmInvoker.java
index 223ece177d7..cfd19aeb159 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/ScmInvoker.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/invoker/ScmInvoker.java
@@ -22,6 +22,7 @@
import java.util.function.Function;
import org.apache.hadoop.hdds.protocol.proto.SCMRatisProtocol.RequestType;
import org.apache.hadoop.hdds.scm.exceptions.SCMException;
+import org.apache.hadoop.hdds.scm.ha.HASecurityUtils;
import org.apache.hadoop.hdds.scm.ha.SCMHandler;
import org.apache.hadoop.hdds.scm.ha.SCMRatisRequest;
import org.apache.hadoop.hdds.scm.ha.SCMRatisResponse;
@@ -74,6 +75,24 @@ final Object invokeReplicateDirect(NameAndParameterTypes
method, Object[] args)
}
}
+ /** For @Replicate CLIENT methods. */
+ final Object invokeReplicateClient(NameAndParameterTypes method, Object[]
args) throws SCMException {
+ try {
+ final SCMRatisRequest request = SCMRatisRequest.of(
+ getType(), method.name(), method.getParameterTypes(args.length),
args);
+ final SCMRatisResponse response =
HASecurityUtils.submitScmRequestToRatis(
+ ratisHandler.getDivision().getGroup(),
+ ratisHandler.getGrpcTlsConfig(),
+ request.encode());
+ if (response.isSuccess()) {
+ return response.getResult();
+ }
+ throw response.getException();
+ } catch (Exception e) {
+ throw translateException(e);
+ }
+ }
+
interface NameAndParameterTypes {
String name();
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/security/RootCARotationHandler.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/security/RootCARotationHandler.java
index 507aebb653e..adf6027f54a 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/security/RootCARotationHandler.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/security/RootCARotationHandler.java
@@ -20,6 +20,7 @@
import java.io.IOException;
import org.apache.hadoop.hdds.protocol.proto.SCMRatisProtocol.RequestType;
import org.apache.hadoop.hdds.scm.ha.SCMHandler;
+import org.apache.hadoop.hdds.scm.ha.invoker.ScmInvokerCodeGenerator;
import org.apache.hadoop.hdds.scm.metadata.Replicate;
/**
@@ -59,4 +60,8 @@ void rotationCommitted(String rootCertId)
default RequestType getType() {
return RequestType.CERT_ROTATE;
}
+
+ static void main(String[] args) {
+ ScmInvokerCodeGenerator.generate(RootCARotationHandler.class, true);
+ }
}
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/security/RootCARotationHandlerImpl.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/security/RootCARotationHandlerImpl.java
index df9e3248495..812ca1f1106 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/security/RootCARotationHandlerImpl.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/security/RootCARotationHandlerImpl.java
@@ -29,6 +29,7 @@
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.hdds.scm.ha.SCMRatisServer;
+import org.apache.hadoop.hdds.scm.ha.invoker.RootCARotationHandlerInvoker;
import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
import org.apache.hadoop.hdds.security.SecurityConfig;
import
org.apache.hadoop.hdds.security.x509.certificate.client.SCMCertificateClient;
@@ -227,7 +228,7 @@ public RootCARotationHandler build() {
final RootCARotationHandler impl =
new RootCARotationHandlerImpl(scm, rootCARotationManager);
- return ratisServer.getProxyHandler(RootCARotationHandler.class, impl);
+ return ratisServer.getProxyHandler(new
RootCARotationHandlerInvoker(impl, ratisServer));
}
}
}
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMCertStore.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMCertStore.java
index f6fdac43aac..7e470e096f5 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMCertStore.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMCertStore.java
@@ -31,6 +31,7 @@
import java.util.stream.Collectors;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType;
import org.apache.hadoop.hdds.scm.ha.SCMRatisServer;
+import org.apache.hadoop.hdds.scm.ha.invoker.CertificateStoreInvoker;
import org.apache.hadoop.hdds.scm.metadata.SCMMetadataStore;
import org.apache.hadoop.hdds.security.exception.SCMSecurityException;
import
org.apache.hadoop.hdds.security.x509.certificate.authority.CertificateStore;
@@ -214,7 +215,7 @@ public Builder setRatisServer(final SCMRatisServer
ratisServer) {
public CertificateStore build() {
final SCMCertStore scmCertStore = new SCMCertStore(metadataStore);
- return scmRatisServer.getProxyHandler(CertificateStore.class,
scmCertStore);
+ return scmRatisServer.getProxyHandler(new
CertificateStoreInvoker(scmCertStore, scmRatisServer));
}
}
}
diff --git
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMCertStore.java
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMCertStore.java
index 451dcb7eb69..ac375fe43f9 100644
---
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMCertStore.java
+++
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMCertStore.java
@@ -21,9 +21,7 @@
import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType.OM;
import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType.SCM;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.AdditionalAnswers.returnsLastArg;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -38,6 +36,7 @@
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType;
import org.apache.hadoop.hdds.scm.ha.SCMRatisServer;
+import org.apache.hadoop.hdds.scm.ha.invoker.ScmInvoker;
import org.apache.hadoop.hdds.scm.metadata.SCMMetadataStore;
import org.apache.hadoop.hdds.scm.metadata.SCMMetadataStoreImpl;
import org.apache.hadoop.hdds.security.SecurityConfig;
@@ -71,9 +70,11 @@ public void setUp(@TempDir Path tempDir) throws Exception {
keyPair = KeyStoreTestUtil.generateKeyPair("RSA");
final SCMRatisServer ratisServer = mock(SCMRatisServer.class);
- when(ratisServer.getProxyHandler(
- eq(CertificateStore.class), any(CertificateStore.class)))
- .then(returnsLastArg());
+ when(ratisServer.getProxyHandler(any(ScmInvoker.class)))
+ .thenAnswer(invocation -> {
+ ScmInvoker<?> invoker = invocation.getArgument(0);
+ return invoker.getImpl();
+ });
scmMetadataStore = new SCMMetadataStoreImpl(config);
scmCertStore = new SCMCertStore.Builder().setRatisServer(ratisServer)
.setMetadaStore(scmMetadataStore)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]