mirror of
https://github.com/corda/corda.git
synced 2025-01-18 18:56:28 +00:00
Merged in mnesbit-cleanup-driver-use-standalone-node (pull request #340)
Use standalone Corda main class and configuration in the Driver, rather than a separate class.
This commit is contained in:
commit
4fb0148f96
@ -7,6 +7,7 @@ import com.r3corda.core.crypto.generateKeyPair
|
||||
import com.r3corda.core.node.NodeInfo
|
||||
import com.r3corda.core.node.services.NetworkMapCache
|
||||
import com.r3corda.core.node.services.ServiceType
|
||||
import com.r3corda.node.services.config.FullNodeConfiguration
|
||||
import com.r3corda.node.services.config.NodeConfiguration
|
||||
import com.r3corda.node.services.config.NodeConfigurationFromConfig
|
||||
import com.r3corda.node.services.messaging.ArtemisMessagingClient
|
||||
@ -14,6 +15,7 @@ import com.r3corda.node.services.messaging.ArtemisMessagingComponent
|
||||
import com.r3corda.node.services.messaging.ArtemisMessagingServer
|
||||
import com.r3corda.node.services.network.InMemoryNetworkMapCache
|
||||
import com.r3corda.node.services.network.NetworkMapService
|
||||
import com.r3corda.node.services.transactions.NotaryService
|
||||
import com.r3corda.node.utilities.AffinityExecutor
|
||||
import com.typesafe.config.Config
|
||||
import com.typesafe.config.ConfigRenderOptions
|
||||
@ -21,6 +23,7 @@ import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
import java.net.*
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
@ -289,25 +292,24 @@ class DriverDSL(
|
||||
val name = providedName ?: "${pickA(name)}-${messagingAddress.port}"
|
||||
|
||||
val nodeDirectory = "$baseDirectory/$name"
|
||||
val useNotary = advertisedServices.any { it.isSubTypeOf(NotaryService.Type) }
|
||||
|
||||
val config = NodeConfiguration.loadConfig(
|
||||
baseDirectoryPath = Paths.get(nodeDirectory),
|
||||
allowMissingConfig = true,
|
||||
configOverrides = mapOf(
|
||||
"myLegalName" to name
|
||||
"myLegalName" to name,
|
||||
"basedir" to Paths.get(nodeDirectory).normalize().toString(),
|
||||
"artemisAddress" to messagingAddress.toString(),
|
||||
"webAddress" to apiAddress.toString(),
|
||||
"hostNotaryServiceLocally" to useNotary.toString(),
|
||||
"extraAdvertisedServiceIds" to advertisedServices.map { x -> x.id }.joinToString(","),
|
||||
"networkMapAddress" to networkMapAddress.toString()
|
||||
)
|
||||
)
|
||||
|
||||
val driverCliParams = NodeRunner.CliParams(
|
||||
services = advertisedServices,
|
||||
networkMapAddress = networkMapAddress,
|
||||
messagingAddress = messagingAddress,
|
||||
apiAddress = apiAddress,
|
||||
baseDirectory = nodeDirectory
|
||||
)
|
||||
|
||||
return Executors.newSingleThreadExecutor().submit(Callable<NodeInfo> {
|
||||
registerProcess(DriverDSL.startNode(config, driverCliParams, name, quasarJarPath, debugPort))
|
||||
registerProcess(DriverDSL.startNode(config, quasarJarPath, debugPort))
|
||||
poll("network map cache for $name") {
|
||||
networkMapCache.partyNodes.forEach {
|
||||
if (it.identity.name == name) {
|
||||
@ -406,19 +408,17 @@ class DriverDSL(
|
||||
baseDirectoryPath = Paths.get(nodeDirectory),
|
||||
allowMissingConfig = true,
|
||||
configOverrides = mapOf(
|
||||
"myLegalName" to networkMapName
|
||||
"myLegalName" to networkMapName,
|
||||
"basedir" to Paths.get(nodeDirectory).normalize().toString(),
|
||||
"artemisAddress" to networkMapAddress.toString(),
|
||||
"webAddress" to apiAddress.toString(),
|
||||
"hostNotaryServiceLocally" to "false",
|
||||
"extraAdvertisedServiceIds" to ""
|
||||
)
|
||||
)
|
||||
|
||||
val driverCliParams = NodeRunner.CliParams(
|
||||
services = setOf(NetworkMapService.Type),
|
||||
networkMapAddress = null,
|
||||
messagingAddress = networkMapAddress,
|
||||
apiAddress = apiAddress,
|
||||
baseDirectory = nodeDirectory
|
||||
)
|
||||
log.info("Starting network-map-service")
|
||||
registerProcess(startNode(config, driverCliParams, networkMapName, quasarJarPath, debugPort))
|
||||
registerProcess(startNode(config, quasarJarPath, debugPort))
|
||||
}
|
||||
|
||||
companion object {
|
||||
@ -433,16 +433,14 @@ class DriverDSL(
|
||||
|
||||
private fun startNode(
|
||||
config: Config,
|
||||
cliParams: NodeRunner.CliParams,
|
||||
legalName: String,
|
||||
quasarJarPath: String,
|
||||
debugPort: Int?
|
||||
): Process {
|
||||
|
||||
val nodeConf = FullNodeConfiguration(config)
|
||||
// Write node.conf
|
||||
writeConfig(cliParams.baseDirectory, "node.conf", config)
|
||||
writeConfig(nodeConf.basedir, "node.conf", config)
|
||||
|
||||
val className = NodeRunner::class.java.canonicalName
|
||||
val className = "com.r3corda.node.MainKt" // cannot directly get class for this, so just use string
|
||||
val separator = System.getProperty("file.separator")
|
||||
val classpath = System.getProperty("java.class.path")
|
||||
val path = System.getProperty("java.home") + separator + "bin" + separator + "java"
|
||||
@ -453,26 +451,27 @@ class DriverDSL(
|
||||
emptyList()
|
||||
|
||||
val javaArgs = listOf(path) +
|
||||
listOf("-Dname=$legalName", "-javaagent:$quasarJarPath") + debugPortArg +
|
||||
listOf("-Dname=${nodeConf.myLegalName}", "-javaagent:$quasarJarPath") + debugPortArg +
|
||||
listOf("-cp", classpath, className) +
|
||||
cliParams.toCliArguments()
|
||||
"--base-directory=${nodeConf.basedir}"
|
||||
val builder = ProcessBuilder(javaArgs)
|
||||
builder.redirectError(Paths.get("error.$className.log").toFile())
|
||||
builder.inheritIO()
|
||||
builder.directory(nodeConf.basedir.toFile())
|
||||
val process = builder.start()
|
||||
addressMustBeBound(cliParams.messagingAddress)
|
||||
addressMustBeBound(nodeConf.artemisAddress)
|
||||
// TODO There is a race condition here. Even though the messaging address is bound it may be the case that
|
||||
// the handlers for the advertised services are not yet registered. A hacky workaround is that we wait for
|
||||
// the web api address to be bound as well, as that starts after the services. Needs rethinking.
|
||||
addressMustBeBound(cliParams.apiAddress)
|
||||
addressMustBeBound(nodeConf.webAddress)
|
||||
|
||||
return process
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun writeConfig(path: String, filename: String, config: Config) {
|
||||
File(path).mkdirs()
|
||||
fun writeConfig(path: Path, filename: String, config: Config) {
|
||||
path.toFile().mkdirs()
|
||||
File("$path/$filename").writeText(config.root().render(ConfigRenderOptions.concise()))
|
||||
}
|
||||
|
||||
|
@ -1,121 +0,0 @@
|
||||
package com.r3corda.node.driver
|
||||
|
||||
import com.google.common.net.HostAndPort
|
||||
import com.r3corda.core.node.services.ServiceType
|
||||
import com.r3corda.node.internal.Node
|
||||
import com.r3corda.node.services.config.NodeConfiguration
|
||||
import com.r3corda.node.services.config.NodeConfigurationFromConfig
|
||||
import com.r3corda.node.services.messaging.ArtemisMessagingClient
|
||||
import joptsimple.ArgumentAcceptingOptionSpec
|
||||
import joptsimple.OptionParser
|
||||
import joptsimple.OptionSet
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
|
||||
private val log: Logger = LoggerFactory.getLogger(NodeRunner::class.java)
|
||||
|
||||
class NodeRunner {
|
||||
companion object {
|
||||
@JvmStatic fun main(arguments: Array<String>) {
|
||||
val cliParams = CliParams.parse(CliParams.parser.parse(*arguments))
|
||||
val nodeDirectory = Paths.get(cliParams.baseDirectory)
|
||||
createNodeRunDirectory(nodeDirectory)
|
||||
|
||||
with(cliParams) {
|
||||
|
||||
val networkMapNodeInfo =
|
||||
if (networkMapAddress != null) {
|
||||
ArtemisMessagingClient.makeNetworkMapAddress(networkMapAddress)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val nodeConfiguration = NodeConfigurationFromConfig(
|
||||
NodeConfiguration.loadConfig(
|
||||
baseDirectoryPath = nodeDirectory,
|
||||
allowMissingConfig = false
|
||||
)
|
||||
)
|
||||
|
||||
val node = Node(
|
||||
dir = nodeDirectory,
|
||||
p2pAddr = messagingAddress,
|
||||
webServerAddr = apiAddress,
|
||||
configuration = nodeConfiguration,
|
||||
networkMapAddress = networkMapNodeInfo,
|
||||
advertisedServices = services.toSet()
|
||||
)
|
||||
|
||||
log.info("Starting ${nodeConfiguration.myLegalName} with services $services on addresses $messagingAddress and $apiAddress")
|
||||
node.start()
|
||||
node.run()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CliParams (
|
||||
val services: Set<ServiceType>,
|
||||
val networkMapAddress: HostAndPort?,
|
||||
val messagingAddress: HostAndPort,
|
||||
val apiAddress: HostAndPort,
|
||||
val baseDirectory: String
|
||||
) {
|
||||
|
||||
companion object {
|
||||
val parser = OptionParser()
|
||||
val services =
|
||||
parser.accepts("services").withRequiredArg().ofType(String::class.java)
|
||||
val networkMapAddress =
|
||||
parser.accepts("network-map-address").withOptionalArg().ofType(String::class.java)
|
||||
val messagingAddress =
|
||||
parser.accepts("messaging-address").withRequiredArg().ofType(String::class.java)
|
||||
val apiAddress =
|
||||
parser.accepts("api-address").withRequiredArg().ofType(String::class.java)
|
||||
val baseDirectory =
|
||||
parser.accepts("base-directory").withRequiredArg().ofType(String::class.java)
|
||||
|
||||
private fun <T> requiredArgument(optionSet: OptionSet, spec: ArgumentAcceptingOptionSpec<T>) =
|
||||
optionSet.valueOf(spec) ?: throw IllegalArgumentException("Must provide $spec")
|
||||
|
||||
fun parse(optionSet: OptionSet): CliParams {
|
||||
val services = optionSet.valuesOf(services)
|
||||
val networkMapAddress = optionSet.valueOf(networkMapAddress)
|
||||
val messagingAddress = requiredArgument(optionSet, messagingAddress)
|
||||
val apiAddress = requiredArgument(optionSet, apiAddress)
|
||||
val baseDirectory = requiredArgument(optionSet, baseDirectory)
|
||||
|
||||
return CliParams(
|
||||
services = services.map { object : ServiceType(it) {} }.toSet(),
|
||||
messagingAddress = HostAndPort.fromString(messagingAddress),
|
||||
apiAddress = HostAndPort.fromString(apiAddress),
|
||||
baseDirectory = baseDirectory,
|
||||
networkMapAddress = networkMapAddress?.let { HostAndPort.fromString(it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun toCliArguments(): List<String> {
|
||||
val cliArguments = LinkedList<String>()
|
||||
if (services.isNotEmpty()) {
|
||||
cliArguments.add("--services")
|
||||
cliArguments.addAll(services.map { it.toString() })
|
||||
}
|
||||
if (networkMapAddress != null) {
|
||||
cliArguments.add("--network-map-address")
|
||||
cliArguments.add(networkMapAddress.toString())
|
||||
}
|
||||
cliArguments.add("--messaging-address")
|
||||
cliArguments.add(messagingAddress.toString())
|
||||
cliArguments.add("--api-address")
|
||||
cliArguments.add(apiAddress.toString())
|
||||
cliArguments.add("--base-directory")
|
||||
cliArguments.add(baseDirectory.toString())
|
||||
return cliArguments
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createNodeRunDirectory(directory: Path) = directory.toFile().mkdirs()
|
||||
|
Loading…
Reference in New Issue
Block a user