chihsuan commented on code in PR #10916:
URL: https://github.com/apache/ozone/pull/10916#discussion_r3705462773


##########
hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMSecurityProtocolServer.java:
##########
@@ -326,7 +334,29 @@ public String getSCMCertificate(ScmNodeDetailsProto 
scmNodeDetails,
     LOGGER.info("Processing CSR for scm {}, nodeId: {}",
         scmNodeDetails.getHostName(), scmNodeDetails.getScmNodeId());
 
-    return getEncodedCertToString(certSignReq, NodeType.SCM);
+    boolean leaderless = !storageContainerManager.checkLeader()
+        && isLeaderlessPrimaryScmSigner(storageContainerManager,
+            
storageContainerManager.getScmHAManager().getRatisServer().triggerNotLeaderException(),
+            isRenew);
+
+    return getEncodedCertToString(certSignReq, NodeType.SCM, leaderless, 
scmNodeDetails.getScmNodeId());
+  }
+
+  /**
+   * Single source of truth for whether this SCM should sign its own 
leaderless bootstrap SCM
+   * certificate: no Ratis leader is known cluster-wide (not merely that this 
node isn't leader),
+   * this is not a renewal, and this SCM hosts the primary root CA.
+   *
+   * @param scm     - the serving StorageContainerManager.
+   * @param nle     - the NotLeaderException produced by the local Ratis 
server, or null.
+   * @param isRenew - whether this request is a certificate renewal.
+   * @return true iff the leaderless SCM-certificate signing path should be 
used.
+   */
+  @VisibleForTesting
+  public static boolean isLeaderlessPrimaryScmSigner(StorageContainerManager 
scm, NotLeaderException nle,
+      boolean isRenew) {
+    return !isRenew && nle != null && nle.getSuggestedLeader() == null

Review Comment:
   I was curious about this condition. Could `getSuggestedLeader() == null` 
also occur briefly during an election, or on an isolated SCM while the other 
peers have a leader?



##########
hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SequenceIdGenerator.java:
##########
@@ -180,6 +180,44 @@ public void reinitialize(Table<SequenceIdType, Long> 
sequenceIdTable)
     }
   }
 
+  /**
+   * Allocate the next CertificateId directly against the CertificateId row
+   * of {@link SCMMetadataStore#getSequenceIdTable()}, bypassing Ratis. This
+   * is used for leaderless bootstrap certificate signing, where no Ratis
+   * leader is available yet.
+   *
+   * The live StateManager cache and any un-exhausted batch are refreshed
+   * under the same lock, so that a later Ratis-based allocation of
+   * CertificateId (e.g. after a leader election) cannot CAS a stale cached
+   * lastId and reissue the value handed out here.
+   *
+   * @param scmMetadataStore : the SCMMetadataStore to allocate against.
+   * @return the newly allocated CertificateId.
+   */
+  public long getNextCertificateIdWithoutRatis(SCMMetadataStore 
scmMetadataStore)
+      throws IOException {
+    lock.lock();
+    try {
+      // Re-derive the CertificateId row from existing certificates if missing.
+      upgradeToCertificateSequenceId(scmMetadataStore, false);
+
+      Table<SequenceIdType, Long> sequenceIdTable = 
scmMetadataStore.getSequenceIdTable();
+      Long lastId = sequenceIdTable.get(SequenceIdType.CertificateId);

Review Comment:
    Would we also need to account for an older write already queued in the 
transaction buffer, or is there a guarantee that the buffer is empty on this 
path?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to