mirror of
https://github.com/corda/corda.git
synced 2025-01-31 08:25:50 +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.NodeInfo
|
||||||
import com.r3corda.core.node.services.NetworkMapCache
|
import com.r3corda.core.node.services.NetworkMapCache
|
||||||
import com.r3corda.core.node.services.ServiceType
|
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.NodeConfiguration
|
||||||
import com.r3corda.node.services.config.NodeConfigurationFromConfig
|
import com.r3corda.node.services.config.NodeConfigurationFromConfig
|
||||||
import com.r3corda.node.services.messaging.ArtemisMessagingClient
|
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.messaging.ArtemisMessagingServer
|
||||||
import com.r3corda.node.services.network.InMemoryNetworkMapCache
|
import com.r3corda.node.services.network.InMemoryNetworkMapCache
|
||||||
import com.r3corda.node.services.network.NetworkMapService
|
import com.r3corda.node.services.network.NetworkMapService
|
||||||
|
import com.r3corda.node.services.transactions.NotaryService
|
||||||
import com.r3corda.node.utilities.AffinityExecutor
|
import com.r3corda.node.utilities.AffinityExecutor
|
||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
import com.typesafe.config.ConfigRenderOptions
|
import com.typesafe.config.ConfigRenderOptions
|
||||||
@ -21,6 +23,7 @@ import org.slf4j.Logger
|
|||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.*
|
import java.net.*
|
||||||
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -289,25 +292,24 @@ class DriverDSL(
|
|||||||
val name = providedName ?: "${pickA(name)}-${messagingAddress.port}"
|
val name = providedName ?: "${pickA(name)}-${messagingAddress.port}"
|
||||||
|
|
||||||
val nodeDirectory = "$baseDirectory/$name"
|
val nodeDirectory = "$baseDirectory/$name"
|
||||||
|
val useNotary = advertisedServices.any { it.isSubTypeOf(NotaryService.Type) }
|
||||||
|
|
||||||
val config = NodeConfiguration.loadConfig(
|
val config = NodeConfiguration.loadConfig(
|
||||||
baseDirectoryPath = Paths.get(nodeDirectory),
|
baseDirectoryPath = Paths.get(nodeDirectory),
|
||||||
allowMissingConfig = true,
|
allowMissingConfig = true,
|
||||||
configOverrides = mapOf(
|
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> {
|
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") {
|
poll("network map cache for $name") {
|
||||||
networkMapCache.partyNodes.forEach {
|
networkMapCache.partyNodes.forEach {
|
||||||
if (it.identity.name == name) {
|
if (it.identity.name == name) {
|
||||||
@ -406,19 +408,17 @@ class DriverDSL(
|
|||||||
baseDirectoryPath = Paths.get(nodeDirectory),
|
baseDirectoryPath = Paths.get(nodeDirectory),
|
||||||
allowMissingConfig = true,
|
allowMissingConfig = true,
|
||||||
configOverrides = mapOf(
|
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")
|
log.info("Starting network-map-service")
|
||||||
registerProcess(startNode(config, driverCliParams, networkMapName, quasarJarPath, debugPort))
|
registerProcess(startNode(config, quasarJarPath, debugPort))
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -433,16 +433,14 @@ class DriverDSL(
|
|||||||
|
|
||||||
private fun startNode(
|
private fun startNode(
|
||||||
config: Config,
|
config: Config,
|
||||||
cliParams: NodeRunner.CliParams,
|
|
||||||
legalName: String,
|
|
||||||
quasarJarPath: String,
|
quasarJarPath: String,
|
||||||
debugPort: Int?
|
debugPort: Int?
|
||||||
): Process {
|
): Process {
|
||||||
|
val nodeConf = FullNodeConfiguration(config)
|
||||||
// Write node.conf
|
// 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 separator = System.getProperty("file.separator")
|
||||||
val classpath = System.getProperty("java.class.path")
|
val classpath = System.getProperty("java.class.path")
|
||||||
val path = System.getProperty("java.home") + separator + "bin" + separator + "java"
|
val path = System.getProperty("java.home") + separator + "bin" + separator + "java"
|
||||||
@ -453,26 +451,27 @@ class DriverDSL(
|
|||||||
emptyList()
|
emptyList()
|
||||||
|
|
||||||
val javaArgs = listOf(path) +
|
val javaArgs = listOf(path) +
|
||||||
listOf("-Dname=$legalName", "-javaagent:$quasarJarPath") + debugPortArg +
|
listOf("-Dname=${nodeConf.myLegalName}", "-javaagent:$quasarJarPath") + debugPortArg +
|
||||||
listOf("-cp", classpath, className) +
|
listOf("-cp", classpath, className) +
|
||||||
cliParams.toCliArguments()
|
"--base-directory=${nodeConf.basedir}"
|
||||||
val builder = ProcessBuilder(javaArgs)
|
val builder = ProcessBuilder(javaArgs)
|
||||||
builder.redirectError(Paths.get("error.$className.log").toFile())
|
builder.redirectError(Paths.get("error.$className.log").toFile())
|
||||||
builder.inheritIO()
|
builder.inheritIO()
|
||||||
|
builder.directory(nodeConf.basedir.toFile())
|
||||||
val process = builder.start()
|
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
|
// 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 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.
|
// 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
|
return process
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeConfig(path: String, filename: String, config: Config) {
|
fun writeConfig(path: Path, filename: String, config: Config) {
|
||||||
File(path).mkdirs()
|
path.toFile().mkdirs()
|
||||||
File("$path/$filename").writeText(config.root().render(ConfigRenderOptions.concise()))
|
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…
x
Reference in New Issue
Block a user