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]

Reply via email to