Extended Driver api to allow custom config overrides. Added helper methods for creating a distributed notary cluster.

This commit is contained in:
Andrius Dagys 2016-11-21 17:53:44 +00:00
parent 8119a343fe
commit 758ab6d359
2 changed files with 92 additions and 16 deletions

View File

@ -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()
}

View File

@ -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))
}
}
}