mirror of
https://github.com/corda/corda.git
synced 2025-01-29 15:43:55 +00:00
Extended Driver api to allow custom config overrides. Added helper methods for creating a distributed notary cluster.
This commit is contained in:
parent
8119a343fe
commit
758ab6d359
@ -11,6 +11,7 @@ import net.corda.core.div
|
||||
import net.corda.core.future
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.node.services.ServiceType
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.node.services.User
|
||||
import net.corda.node.services.config.ConfigHelper
|
||||
@ -18,7 +19,9 @@ import net.corda.node.services.config.FullNodeConfiguration
|
||||
import net.corda.node.services.messaging.ArtemisMessagingServer
|
||||
import net.corda.node.services.messaging.NodeMessagingClient
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
||||
import net.corda.node.utilities.JsonSupport
|
||||
import net.corda.node.utilities.ServiceIdentityGenerator
|
||||
import org.slf4j.Logger
|
||||
import java.io.File
|
||||
import java.net.*
|
||||
@ -62,7 +65,17 @@ interface DriverDSLExposedInterface {
|
||||
*/
|
||||
fun startNode(providedName: String? = null,
|
||||
advertisedServices: Set<ServiceInfo> = emptySet(),
|
||||
rpcUsers: List<User> = emptyList()): Future<NodeInfoAndConfig>
|
||||
rpcUsers: List<User> = emptyList(),
|
||||
customOverrides: Map<String, Any?> = emptyMap()): Future<NodeInfoAndConfig>
|
||||
|
||||
/**
|
||||
* Starts a distributed notary cluster.
|
||||
*
|
||||
* @param notaryName The legal name of the advertised distributed notary service.
|
||||
* @param clusterSize Number of nodes to create for the cluster.
|
||||
* @param type The advertised notary service type. Currently the only supported type is [RaftValidatingNotaryService.type].
|
||||
*/
|
||||
fun startNotaryCluster(notaryName: String, clusterSize: Int = 3, type: ServiceType = RaftValidatingNotaryService.type)
|
||||
|
||||
fun waitForAllNodesToFinish()
|
||||
}
|
||||
@ -292,31 +305,35 @@ open class DriverDSL(
|
||||
}
|
||||
}
|
||||
|
||||
override fun startNode(providedName: String?, advertisedServices: Set<ServiceInfo>, rpcUsers: List<User>): Future<NodeInfoAndConfig> {
|
||||
override fun startNode(providedName: String?, advertisedServices: Set<ServiceInfo>,
|
||||
rpcUsers: List<User>, customOverrides: Map<String, Any?>): Future<NodeInfoAndConfig> {
|
||||
val messagingAddress = portAllocation.nextHostAndPort()
|
||||
val apiAddress = portAllocation.nextHostAndPort()
|
||||
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
||||
val name = providedName ?: "${pickA(name)}-${messagingAddress.port}"
|
||||
|
||||
val baseDirectory = driverDirectory / name
|
||||
val configOverrides = mapOf(
|
||||
"myLegalName" to name,
|
||||
"basedir" to baseDirectory.normalize().toString(),
|
||||
"artemisAddress" to messagingAddress.toString(),
|
||||
"webAddress" to apiAddress.toString(),
|
||||
"extraAdvertisedServiceIds" to advertisedServices.joinToString(","),
|
||||
"networkMapAddress" to networkMapAddress.toString(),
|
||||
"useTestClock" to useTestClock,
|
||||
"rpcUsers" to rpcUsers.map {
|
||||
mapOf(
|
||||
"user" to it.username,
|
||||
"password" to it.password,
|
||||
"permissions" to it.permissions
|
||||
)
|
||||
}
|
||||
) + customOverrides
|
||||
|
||||
val config = ConfigHelper.loadConfig(
|
||||
baseDirectoryPath = baseDirectory,
|
||||
allowMissingConfig = true,
|
||||
configOverrides = mapOf(
|
||||
"myLegalName" to name,
|
||||
"basedir" to baseDirectory.normalize().toString(),
|
||||
"artemisAddress" to messagingAddress.toString(),
|
||||
"webAddress" to apiAddress.toString(),
|
||||
"extraAdvertisedServiceIds" to advertisedServices.joinToString(","),
|
||||
"networkMapAddress" to networkMapAddress.toString(),
|
||||
"useTestClock" to useTestClock,
|
||||
"rpcUsers" to rpcUsers.map { mapOf(
|
||||
"user" to it.username,
|
||||
"password" to it.password,
|
||||
"permissions" to it.permissions)
|
||||
}
|
||||
)
|
||||
configOverrides = configOverrides
|
||||
)
|
||||
|
||||
return future {
|
||||
@ -325,6 +342,25 @@ open class DriverDSL(
|
||||
}
|
||||
}
|
||||
|
||||
override fun startNotaryCluster(notaryName: String, clusterSize: Int, type: ServiceType) {
|
||||
val nodeNames = (1..clusterSize).map { "Notary Node $it" }
|
||||
val paths = nodeNames.map { driverDirectory / it }
|
||||
ServiceIdentityGenerator.generateToDisk(paths, type.id, notaryName)
|
||||
|
||||
val serviceInfo = ServiceInfo(type, notaryName)
|
||||
val advertisedService = setOf(serviceInfo)
|
||||
val notaryClusterAddress = portAllocation.nextHostAndPort()
|
||||
|
||||
// Start the first node that will bootstrap the cluster
|
||||
startNode(nodeNames.first(), advertisedService, emptyList(), mapOf("notaryNodeAddress" to notaryClusterAddress.toString()))
|
||||
// All other nodes will join the cluster
|
||||
nodeNames.drop(1).forEach {
|
||||
val nodeAddress = portAllocation.nextHostAndPort()
|
||||
val configOverride = mapOf("notaryNodeAddress" to nodeAddress.toString(), "notaryClusterAddress" to notaryClusterAddress.toString())
|
||||
startNode(it, advertisedService, emptyList(), configOverride)
|
||||
}
|
||||
}
|
||||
|
||||
override fun start() {
|
||||
startNetworkMapService()
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
package net.corda.node.utilities
|
||||
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.crypto.Party
|
||||
import net.corda.core.crypto.composite
|
||||
import net.corda.core.crypto.generateKeyPair
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
||||
object ServiceIdentityGenerator {
|
||||
private val log = loggerFor<ServiceIdentityGenerator>()
|
||||
|
||||
/**
|
||||
* Generates signing key pairs and a common distributed service identity for a set of nodes.
|
||||
* The key pairs and the group identity get serialized to disk in the corresponding node directories.
|
||||
* This method should be called *before* any of the nodes are started.
|
||||
*
|
||||
* @param dirs List of node directories to place the generated identity and key pairs in.
|
||||
* @param serviceId The service id of the distributed service.
|
||||
* @param serviceName The legal name of the distributed service.
|
||||
* @param threshold The threshold for the generated group [CompositeKey.Node].
|
||||
*/
|
||||
fun generateToDisk(dirs: List<Path>, serviceId: String, serviceName: String, threshold: Int = 1) {
|
||||
log.trace("Generating a group identity \"serviceName\" for nodes: ${dirs.joinToString()}")
|
||||
|
||||
val keyPairs = (1..dirs.size).map { generateKeyPair() }
|
||||
val notaryKey = CompositeKey.Builder().addKeys(keyPairs.map { it.public.composite }).build(threshold)
|
||||
val notaryParty = Party(serviceName, notaryKey).serialize()
|
||||
|
||||
keyPairs.zip(dirs) { keyPair, dir ->
|
||||
Files.createDirectories(dir)
|
||||
val privateKeyFile = serviceId + "-private-key"
|
||||
val publicKeyFile = serviceId + "-public"
|
||||
notaryParty.writeToFile(dir.resolve(publicKeyFile))
|
||||
keyPair.serialize().writeToFile(dir.resolve(privateKeyFile))
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user