Merge remote-tracking branch 'open/master' into os-merge-aefd90f

# Conflicts:
#	CONTRIBUTORS.md
This commit is contained in:
Shams Asari 2018-07-09 12:33:47 +01:00
commit 5d55a87d70
14 changed files with 49 additions and 75 deletions

View File

@ -48,7 +48,6 @@ import org.junit.Before
import org.junit.ClassRule
import org.junit.Test
import rx.subjects.PublishSubject
import java.io.File.pathSeparator
import java.net.URLClassLoader
import java.nio.file.Paths
import java.util.*
@ -249,15 +248,12 @@ class CordaRPCClientTest : NodeBasedTest(listOf("net.corda.finance")) {
@Test
fun `additional class loader used by WireTransaction when it deserialises its components`() {
val financeLocation = Cash::class.java.location.toPath().toString()
val classpathWithoutFinance = ProcessUtilities.defaultClassPath
.split(pathSeparator)
.filter { financeLocation !in it }
.joinToString(pathSeparator)
val classPathWithoutFinance = ProcessUtilities.defaultClassPath.filter { financeLocation !in it }
// Create a Cash.State object for the StandaloneCashRpcClient to get
node.services.startFlow(CashIssueFlow(100.POUNDS, OpaqueBytes.of(1), identity), InvocationContext.shell()).flatMap { it.resultFuture }.getOrThrow()
val outOfProcessRpc = ProcessUtilities.startJavaProcess<StandaloneCashRpcClient>(
classpath = classpathWithoutFinance,
classPath = classPathWithoutFinance,
arguments = listOf(node.internals.configuration.rpcOptions.address.toString(), financeLocation)
)
assertThat(outOfProcessRpc.waitFor()).isZero() // i.e. no exceptions were thrown

View File

@ -27,11 +27,11 @@ Uploading and downloading
To upload an attachment to the node, or download an attachment named by its hash, you use :doc:`clientrpc`. This
is also available for interactive use via the shell. To **upload** run:
``>>> run uploadAttachment jar: /path/to/the/file.jar``
``>>> run uploadAttachment jar: path/to/the/file.jar``
or
``>>> run uploadAttachmentWithMetadata jar: /path/to/the/file.jar, uploader: myself, filename: original_name.jar``
``>>> run uploadAttachmentWithMetadata jar: path/to/the/file.jar, uploader: myself, filename: original_name.jar``
to include the metadata with the attachment which can be used to find it later on. Note, that currently both uploader
and filename are just plain strings (there is no connection between uploader and the RPC users for example).

View File

@ -99,7 +99,7 @@ Let's add a ``CommercialPaper`` transaction:
}
We can add a transaction to the ledger using the ``transaction`` primitive. The transaction in turn may be defined by
specifying ``input``-s, ``output``-s, ``command``-s and ``attachment``-s.
specifying ``input``s, ``output``s, ``command``s and ``attachment``s.
The above ``input`` call is a bit special; transactions don't actually contain input states, just references
to output states of other transactions. Under the hood the above ``input`` call creates a dummy transaction in the

View File

@ -12,4 +12,4 @@
# Note: sadly, due to present limitation of IntelliJ-IDEA in processing resource files, these constants cannot be
# imported from top-level 'constants.properties' file
jolokiaAgentVersion=1.5.0
jolokiaAgentVersion=1.6.0

View File

@ -75,20 +75,18 @@ class IRSDemoTest : IntegrationTest() {
isDebug = true,
extraCordappPackagesToScan = listOf("net.corda.irs")
)) {
val (nodeA, nodeB) = listOf(
val (controller, nodeA, nodeB) = listOf(
defaultNotaryNode,
startNode(providedName = DUMMY_BANK_A_NAME, rpcUsers = rpcUsers),
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = rpcUsers),
startNode(providedName = CordaX500Name("Regulator", "Moscow", "RU"))
).map { it.getOrThrow() }
val controller = defaultNotaryNode.getOrThrow()
log.info("All nodes started")
val controllerAddrFuture = startSpringBootWebapp(IrsDemoWebApplication::class.java, controller, "/api/irs/demodate")
val nodeAAddrFuture = startSpringBootWebapp(IrsDemoWebApplication::class.java, nodeA, "/api/irs/demodate")
val nodeBAddrFuture = startSpringBootWebapp(IrsDemoWebApplication::class.java, nodeB, "/api/irs/demodate")
val (controllerAddr, nodeAAddr, nodeBAddr) =
listOf(controllerAddrFuture, nodeAAddrFuture, nodeBAddrFuture).map { it.getOrThrow().listenAddress }
val (controllerAddr, nodeAAddr, nodeBAddr) = listOf(controller, nodeA, nodeB).map {
startSpringBootWebapp(IrsDemoWebApplication::class.java, it, "/api/irs/demodate")
}.map { it.getOrThrow().listenAddress }
log.info("All webservers started")

View File

@ -85,16 +85,14 @@ data class SpringBootDriverDSL(private val driverDSL: DriverDSLImpl) : InternalD
}
private fun startApplication(handle: NodeHandle, debugPort: Int?, clazz: Class<*>): Process {
val className = clazz.canonicalName
return ProcessUtilities.startJavaProcessImpl(
className = className, // cannot directly get class for this, so just use string
return ProcessUtilities.startJavaProcess(
className = clazz.canonicalName, // cannot directly get class for this, so just use string
jdwpPort = debugPort,
extraJvmArguments = listOf(
"-Dname=node-${handle.p2pAddress}-webserver",
"-Djava.io.tmpdir=${System.getProperty("java.io.tmpdir")}"
// Inherit from parent process
),
classpath = ProcessUtilities.defaultClassPath,
workingDirectory = handle.baseDirectory,
arguments = listOf(
"--base-directory", handle.baseDirectory.toString(),
@ -102,8 +100,7 @@ data class SpringBootDriverDSL(private val driverDSL: DriverDSLImpl) : InternalD
"--corda.host=${handle.rpcAddress}",
"--corda.user=${handle.rpcUsers.first().username}",
"--corda.password=${handle.rpcUsers.first().password}"
),
maximumHeapSize = null
)
)
}
}
}

View File

@ -34,7 +34,6 @@ import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.millis
import net.corda.node.NodeRegistrationOption
import net.corda.node.VersionInfo
import net.corda.node.internal.ConfigurationException
import net.corda.node.internal.Node
import net.corda.node.internal.StartedNode
import net.corda.node.services.Permissions
@ -846,7 +845,7 @@ class DriverDSLImpl(
it += extraCmdLineFlag
}.toList()
return ProcessUtilities.startCordaProcess(
return ProcessUtilities.startJavaProcess(
className = "net.corda.node.Corda", // cannot directly get class for this, so just use string
arguments = arguments,
jdwpPort = debugPort,
@ -859,13 +858,12 @@ class DriverDSLImpl(
private fun startWebserver(handle: NodeHandleInternal, debugPort: Int?, maximumHeapSize: String): Process {
val className = "net.corda.webserver.WebServer"
writeConfig(handle.baseDirectory, "web-server.conf", handle.toWebServerConfig())
return ProcessUtilities.startCordaProcess(
return ProcessUtilities.startJavaProcess(
className = className, // cannot directly get class for this, so just use string
arguments = listOf("--base-directory", handle.baseDirectory.toString()),
jdwpPort = debugPort,
extraJvmArguments = listOf("-Dname=node-${handle.p2pAddress}-webserver") +
inheritFromParentProcess().map { "-D${it.first}=${it.second}" },
workingDirectory = null,
maximumHeapSize = maximumHeapSize
)
}

View File

@ -11,40 +11,32 @@
package net.corda.testing.node.internal
import net.corda.core.internal.div
import java.io.File
import java.nio.file.Path
object ProcessUtilities {
inline fun <reified C : Any> startJavaProcess(
arguments: List<String>,
classpath: String = defaultClassPath,
classPath: List<String> = defaultClassPath,
workingDirectory: Path? = null,
jdwpPort: Int? = null,
extraJvmArguments: List<String> = emptyList()
extraJvmArguments: List<String> = emptyList(),
maximumHeapSize: String? = null
): Process {
return startJavaProcessImpl(C::class.java.name, arguments, classpath, jdwpPort, extraJvmArguments, null, null)
return startJavaProcess(C::class.java.name, arguments, classPath, workingDirectory, jdwpPort, extraJvmArguments, maximumHeapSize)
}
fun startCordaProcess(
fun startJavaProcess(
className: String,
arguments: List<String>,
jdwpPort: Int?,
extraJvmArguments: List<String>,
workingDirectory: Path?,
maximumHeapSize: String
): Process {
return startJavaProcessImpl(className, arguments, defaultClassPath, jdwpPort, extraJvmArguments, workingDirectory, maximumHeapSize)
}
fun startJavaProcessImpl(
className: String,
arguments: List<String>,
classpath: String,
jdwpPort: Int?,
extraJvmArguments: List<String>,
workingDirectory: Path?,
maximumHeapSize: String?
classPath: List<String> = defaultClassPath,
workingDirectory: Path? = null,
jdwpPort: Int? = null,
extraJvmArguments: List<String> = emptyList(),
maximumHeapSize: String? = null
): Process {
val command = mutableListOf<String>().apply {
add((System.getProperty("java.home") / "bin" / "java").toString())
add(javaPath)
(jdwpPort != null) && add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$jdwpPort")
if (maximumHeapSize != null) add("-Xmx$maximumHeapSize")
add("-XX:+UseG1GC")
@ -54,7 +46,7 @@ object ProcessUtilities {
}
return ProcessBuilder(command).apply {
inheritIO()
environment()["CLASSPATH"] = classpath
environment()["CLASSPATH"] = classPath.joinToString(File.pathSeparator)
if (workingDirectory != null) {
redirectError((workingDirectory / "$className.stderr.log").toFile())
redirectOutput((workingDirectory / "$className.stdout.log").toFile())
@ -63,5 +55,7 @@ object ProcessUtilities {
}.start()
}
val defaultClassPath: String get() = System.getProperty("java.class.path")
private val javaPath = (System.getProperty("java.home") / "bin" / "java").toString()
val defaultClassPath: List<String> = System.getProperty("java.class.path").split(File.pathSeparator)
}

View File

@ -7,7 +7,6 @@ import net.corda.bootstrapper.notaries.NotaryCopier
import net.corda.bootstrapper.notaries.NotaryFinder
import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ConcurrentHashMap
interface NetworkBuilder {
@ -23,7 +22,6 @@ interface NetworkBuilder {
fun onNodePushed(callback: (PushedNode) -> Unit): NetworkBuilder
fun onNodeInstance(callback: (NodeInstance) -> Unit): NetworkBuilder
fun withNodeCounts(map: Map<String, Int>): NetworkBuilder
fun withNetworkName(networtName: String): NetworkBuilder
fun withBasedir(baseDir: File): NetworkBuilder
fun withBackend(backendType: Backend.BackendType): NetworkBuilder
@ -104,11 +102,6 @@ private class NetworkBuilderImpl : NetworkBuilder {
return this
}
override fun withNodeCounts(map: Map<String, Int>): NetworkBuilder {
nodeCounts = ConcurrentHashMap(map.entries.map { it.key.toLowerCase() to it.value }.toMap())
return this
}
override fun withNetworkName(networtName: String): NetworkBuilder {
this.networkName = networtName
return this

View File

@ -8,6 +8,7 @@ import net.corda.bootstrapper.context.Context
import net.corda.bootstrapper.nodes.NodeAdder
import net.corda.bootstrapper.nodes.NodeInstantiator
import net.corda.bootstrapper.toSingleFuture
import net.corda.core.identity.CordaX500Name
import net.corda.core.utilities.getOrThrow
import java.io.File
@ -23,7 +24,6 @@ class CommandLineInterface {
val (_, context) = NetworkBuilder.instance()
.withBasedir(baseDir)
.withNetworkName(networkName)
.withNodeCounts(parsedArgs.nodes)
.onNodeBuild { builtNode -> println("Built node: ${builtNode.name} to image: ${builtNode.localImageId}") }
.onNodePushed { pushedNode -> println("Pushed node: ${pushedNode.name} to: ${pushedNode.remoteImageName}") }
.onNodeInstance { instance ->
@ -40,7 +40,7 @@ class CommandLineInterface {
val (_, instantiator, _) = Backend.fromContext(context, cacheDir)
val nodeAdder = NodeAdder(context, NodeInstantiator(instantiator, context))
parsedArgs.nodesToAdd.map {
nodeAdder.addNode(context, Constants.ALPHA_NUMERIC_ONLY_REGEX.replace(it.toLowerCase(), ""))
nodeAdder.addNode(context, Constants.ALPHA_NUMERIC_ONLY_REGEX.replace(it.key.toLowerCase(), ""), CordaX500Name.parse(it.value))
}.toSingleFuture().getOrThrow()
persistContext(contextFile, objectMapper, context)
}

View File

@ -20,11 +20,9 @@ open class CliParser {
@Option(names = ["-b", "--backend"], description = ["The backend to use when instantiating nodes"])
var backendType: Backend.BackendType = Backend.BackendType.LOCAL_DOCKER
@Option(names = ["--nodes"], split = ":", description = ["The number of each node to create. NodeX:2 will create two instances of NodeX"])
var nodes: MutableMap<String, Int> = hashMapOf()
@Option(names = ["--add", "-a"])
var nodesToAdd: MutableList<String> = arrayListOf()
@Option(names = ["--add"], split = ":", description = ["The node to add. Format is <Name>:<X500>. Eg; \"Node1:O=Bank A, L=New York, C=US, OU=Org Unit, CN=Service Name\""])
var nodesToAdd: MutableMap<String, String> = hashMapOf()
fun isNew(): Boolean {
return nodesToAdd.isEmpty()

View File

@ -21,6 +21,7 @@ import net.corda.bootstrapper.baseArgs
import net.corda.bootstrapper.context.Context
import net.corda.bootstrapper.nodes.*
import net.corda.bootstrapper.notaries.NotaryFinder
import net.corda.core.identity.CordaX500Name
import org.apache.commons.lang3.RandomStringUtils
import org.controlsfx.control.SegmentedButton
import tornadofx.*
@ -70,7 +71,6 @@ class BootstrapperView : View("Corda Network Builder") {
}
}
val nodeCount = controller.foundNodes.map { it.id to it.count }.toMap()
val result = NetworkBuilder.instance()
.withBasedir(controller.baseDir.get())
.withNetworkName(networkName)
@ -81,7 +81,6 @@ class BootstrapperView : View("Corda Network Builder") {
.onNodeInstancesRequested(controller::addInstanceRequests)
.onNodeInstance(controller::addInstance)
.withBackend(selectedBackEnd)
.withNodeCounts(nodeCount)
.withBackendOptions(backendParams)
.build()
@ -118,6 +117,10 @@ class BootstrapperView : View("Corda Network Builder") {
enableWhen { controller.networkContext.isNotNull }
action {
templateChoiceBox.selectionModel.selectedItem?.let { nodeToAdd ->
val textInputDialog = TextInputDialog("O=Bank A, L=New York, C=US, OU=Org Unit, CN=Service Name")
textInputDialog.title = "X500 of node to add"
val x500ToUse = textInputDialog.showAndWait().orElseGet { null }
val context = controller.networkContext.value
runLater {
val (_, instantiator, _) = Backend.fromContext(
@ -125,7 +128,7 @@ class BootstrapperView : View("Corda Network Builder") {
File(controller.baseDir.get(), Constants.BOOTSTRAPPER_DIR_NAME))
val nodeAdder = NodeAdder(context, NodeInstantiator(instantiator, context))
controller.addInstanceRequest(nodeToAdd)
nodeAdder.addNode(context, nodeToAdd).handleAsync { instanceInfo, t ->
nodeAdder.addNode(context, nodeToAdd, x500ToUse?.let { CordaX500Name.parse(it) }).handleAsync { instanceInfo, t ->
t?.let {
GuiUtils.showException("Failed", "Failed to add node", it)
}
@ -263,10 +266,6 @@ class BootstrapperView : View("Corda Network Builder") {
compareValues(o1.nodeType.toString() + o1.templateId, o2.nodeType.toString() + o2.templateId) * -1
})
fun clear() {
networkContext.set(null)
}
fun clearAll() {
networkContext.set(null)
foundNodes.clear()

View File

@ -2,17 +2,18 @@ package net.corda.bootstrapper.nodes
import net.corda.bootstrapper.containers.instance.InstanceInfo
import net.corda.bootstrapper.context.Context
import net.corda.core.identity.CordaX500Name
import java.util.concurrent.CompletableFuture
class NodeAdder(val context: Context,
val nodeInstantiator: NodeInstantiator) {
fun addNode(context: Context, nodeGroupName: String): CompletableFuture<InstanceInfo> {
fun addNode(context: Context, nodeGroupName: String, x500ToAdd: CordaX500Name?): CompletableFuture<InstanceInfo> {
return synchronized(context) {
val nodeGroup = context.nodes[nodeGroupName]!!
val nodeInfo = nodeGroup.iterator().next()
val currentNodeSize = nodeGroup.size
val newInstanceX500 = nodeInfo.groupX500!!.copy(commonName = nodeInfo.groupX500.commonName + (currentNodeSize)).toString()
val newInstanceX500 = x500ToAdd?.toString() ?: nodeInfo.groupX500!!.copy(commonName = nodeInfo.groupX500.commonName + (currentNodeSize)).toString()
val newInstanceName = nodeGroupName + (currentNodeSize)
val nextNodeInfo = nodeInfo.copy(
instanceX500 = newInstanceX500,

View File

@ -21,10 +21,10 @@ open class NodeBuilder {
val copiedNodeConfig = copiedNode.copiedNodeConfig
val nodeDir = copiedNodeConfig.parentFile
if (!copiedNodeConfig.exists()) {
throw IllegalStateException("There is no nodeConfig for dir: " + copiedNodeConfig)
throw IllegalStateException("There is no nodeConfig for dir: $copiedNodeConfig")
}
val nodeConfig = ConfigFactory.parseFile(copiedNodeConfig)
LOG.info("starting to build docker image for: " + nodeDir)
LOG.info("starting to build docker image for: $nodeDir")
val nodeImageId = localDockerClient.buildImageCmd()
.withDockerfile(File(nodeDir, "Dockerfile"))
.withBaseDirectory(nodeDir)