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]