CORDA-2998 fix network builder (#5265)

CORDA-2998 fix network builder
This commit is contained in:
szymonsztuka 2019-07-02 12:32:48 +02:00 committed by Rick Parker
parent fee396efc3
commit f89008c070
59 changed files with 480 additions and 530 deletions

View File

@ -413,7 +413,8 @@ bintrayConfig {
'corda-tools-cliutils', 'corda-tools-cliutils',
'corda-common-configuration-parsing', 'corda-common-configuration-parsing',
'corda-common-validation', 'corda-common-validation',
'corda-common-logging' 'corda-common-logging',
'corda-tools-network-builder'
] ]
license { license {
name = 'Apache-2.0' name = 'Apache-2.0'

View File

@ -8,11 +8,15 @@ containers to abstract the complexity of managing a distributed network away fro
.. image:: _static/images/network-builder-v4.png .. image:: _static/images/network-builder-v4.png
The network you build will either be made up of local ``docker`` nodes *or* of nodes spread across Azure The network you build will either be made up of local ``Docker`` nodes *or* of nodes spread across Azure
containers. More backends may be added in future. The tool is open source, so contributions to add more containers.
For each node a separate Docker image is built based on `corda/corda-zulu-4.0 <https://hub.docker.com/r/corda/corda-zulu-4.0>`_.
Unlike the official image, a `node.conf` file and CorDapps are embedded into the image
(they are not externally provided to the running container via volumes/mount points).
More backends may be added in future. The tool is open source, so contributions to add more
destinations for the containers are welcome! destinations for the containers are welcome!
`Download the Corda Network Builder <https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases/net/corda/corda-network-builder/3.2.1847-corda/corda-network-builder-3.2.1847-corda-executable.jar>`_. `Download the Corda Network Builder <https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases/net/corda/corda-tools-network-builder/|corda_version|/corda-tools-network-builder-|corda_version|.jar>`_.
.. _pre-requisites: .. _pre-requisites:
@ -41,9 +45,9 @@ the following layout:
An easy way to build a valid set of nodes is by running ``deployNodes``. In this document, we will be using An easy way to build a valid set of nodes is by running ``deployNodes``. In this document, we will be using
the output of running ``deployNodes`` for the `Example CorDapp <https://github.com/corda/cordapp-example>`_: the output of running ``deployNodes`` for the `Example CorDapp <https://github.com/corda/cordapp-example>`_:
1. ``git clone https://github.com/corda/cordapp-example`` 1. ``git clone https://github.com/corda/samples``
2. ``cd cordapp-example`` 2. ``cd samples/cordapp-example``
3. ``./gradlew clean deployNodes`` 3. ``./gradlew clean workflows-java:deployNodes``
Building a network via the command line Building a network via the command line
--------------------------------------- ---------------------------------------
@ -54,24 +58,27 @@ Starting the nodes
Quickstart Local Docker Quickstart Local Docker
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
1. ``cd kotlin-source/build/nodes`` 1. ``cd workflows-java/build/nodes``
2. ``java -jar <path/to/network-builder-jar> -d .`` 2. ``java -jar <path/to/corda-tools-network-builder.jar> -d .``
If you run ``docker ps`` to see the running containers, the following output should be displayed: If you run ``docker ps`` to see the running containers, the following output should be displayed:
.. sourcecode:: shell .. sourcecode:: shell
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
406868b4ba69 node-partyc:corda-network "/run-corda.sh" 17 seconds ago Up 16 seconds 0.0.0.0:32902->10003/tcp, 0.0.0.0:32895->10005/tcp, 0.0.0.0:32898->10020/tcp, 0.0.0.0:32900->12222/tcp partyc0 406868b4ba69 node-partyc:corda-network "run-corda" 17 seconds ago Up 16 seconds 0.0.0.0:32902->10003/tcp, 0.0.0.0:32895->10005/tcp, 0.0.0.0:32898->10020/tcp, 0.0.0.0:32900->12222/tcp partyc0
4546a2fa8de7 node-partyb:corda-network "/run-corda.sh" 17 seconds ago Up 17 seconds 0.0.0.0:32896->10003/tcp, 0.0.0.0:32899->10005/tcp, 0.0.0.0:32901->10020/tcp, 0.0.0.0:32903->12222/tcp partyb0 4546a2fa8de7 node-partyb:corda-network "run-corda" 17 seconds ago Up 17 seconds 0.0.0.0:32896->10003/tcp, 0.0.0.0:32899->10005/tcp, 0.0.0.0:32901->10020/tcp, 0.0.0.0:32903->12222/tcp partyb0
c8c44c515bdb node-partya:corda-network "/run-corda.sh" 17 seconds ago Up 17 seconds 0.0.0.0:32894->10003/tcp, 0.0.0.0:32897->10005/tcp, 0.0.0.0:32892->10020/tcp, 0.0.0.0:32893->12222/tcp partya0 c8c44c515bdb node-partya:corda-network "run-corda" 17 seconds ago Up 17 seconds 0.0.0.0:32894->10003/tcp, 0.0.0.0:32897->10005/tcp, 0.0.0.0:32892->10020/tcp, 0.0.0.0:32893->12222/tcp partya0
cf7ab689f493 node-notary:corda-network "/run-corda.sh" 30 seconds ago Up 31 seconds 0.0.0.0:32888->10003/tcp, 0.0.0.0:32889->10005/tcp, 0.0.0.0:32890->10020/tcp, 0.0.0.0:32891->12222/tcp notary0 cf7ab689f493 node-notary:corda-network "run-corda" 30 seconds ago Up 31 seconds 0.0.0.0:32888->10003/tcp, 0.0.0.0:32889->10005/tcp, 0.0.0.0:32890->10020/tcp, 0.0.0.0:32891->12222/tcp notary0
Depending on you machine performance, even after all containers are reported as running,
the underlying Corda nodes may be still starting and SSHing to a node may be not available immediately.
Quickstart Remote Azure Quickstart Remote Azure
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
1. ``cd kotlin-source/build/nodes`` 1. ``cd kotlin-source/build/nodes``
2. ``java -jar <path/to/network-builder-jar> -b AZURE -d .`` 2. ``java -jar <path/to/corda-tools-network-builder.jar> -b AZURE -d .``
.. note:: The Azure configuration is handled by the az-cli utility. See the :ref:`pre-requisites`. .. note:: The Azure configuration is handled by the az-cli utility. See the :ref:`pre-requisites`.
@ -95,21 +102,26 @@ You can interact with the nodes by SSHing into them on the port that is mapped t
>>> run networkMapSnapshot >>> run networkMapSnapshot
[ [
{ "addresses" : [ "partya0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyA, L=London, C=GB" ], "platformVersion" : 3, "serial" : 1532701330613 }, { "addresses" : [ "partya0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyA, L=London, C=GB" ], "platformVersion" : |platform_version|, "serial" : 1532701330613 },
{ "addresses" : [ "notary0:10020" ], "legalIdentitiesAndCerts" : [ "O=Notary, L=London, C=GB" ], "platformVersion" : 3, "serial" : 1532701305115 }, { "addresses" : [ "notary0:10020" ], "legalIdentitiesAndCerts" : [ "O=Notary, L=London, C=GB" ], "platformVersion" : |platform_version|, "serial" : 1532701305115 },
{ "addresses" : [ "partyc0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyC, L=Paris, C=FR" ], "platformVersion" : 3, "serial" : 1532701331608 }, { "addresses" : [ "partyc0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyC, L=Paris, C=FR" ], "platformVersion" : |platform_version|, "serial" : 1532701331608 },
{ "addresses" : [ "partyb0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyB, L=New York, C=US" ], "platformVersion" : 3, "serial" : 1532701330118 } { "addresses" : [ "partyb0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyB, L=New York, C=US" ], "platformVersion" : |platform_version|, "serial" : 1532701330118 }
] ]
>>> >>>
You can also run a flow from cordapp-example: ``flow start com.example.flow.ExampleFlow$Initiator iouValue: 20, otherParty: "PartyB"``
To verify it, connect into the ``partyb0`` node and run ``run vaultQuery contractStateType: "com.example.state.IOUState"``.
The ``partyb0`` vault should contain ``IOUState``.
Adding additional nodes Adding additional nodes
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
It is possible to add additional nodes to the network by reusing the nodes you built earlier. For example, to add a It is possible to add additional nodes to the network by reusing the nodes you built earlier. For example, to add a
node by reusing the existing ``PartyA`` node, you would run: node by reusing the existing ``PartyA`` node, you would run:
``java -jar <network-builder-jar> --add "PartyA=O=PartyZ,L=London,C=GB"`` ``java -jar <path/to/corda-tools-network-builder.jar> --add "PartyA=O=PartyZ,L=London,C=GB"``
To confirm the node has been started correctly, run the following in the previously connected SSH session: To confirm the node has been started correctly, run the following in the previously connected SSH session:
@ -117,18 +129,18 @@ To confirm the node has been started correctly, run the following in the previou
Tue Jul 17 15:47:14 GMT 2018>>> run networkMapSnapshot Tue Jul 17 15:47:14 GMT 2018>>> run networkMapSnapshot
[ [
{ "addresses" : [ "partya0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyA, L=London, C=GB" ], "platformVersion" : 3, "serial" : 1532701330613 }, { "addresses" : [ "partya0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyA, L=London, C=GB" ], "platformVersion" : |platform_version|, "serial" : 1532701330613 },
{ "addresses" : [ "notary0:10020" ], "legalIdentitiesAndCerts" : [ "O=Notary, L=London, C=GB" ], "platformVersion" : 3, "serial" : 1532701305115 }, { "addresses" : [ "notary0:10020" ], "legalIdentitiesAndCerts" : [ "O=Notary, L=London, C=GB" ], "platformVersion" : |platform_version|, "serial" : 1532701305115 },
{ "addresses" : [ "partyc0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyC, L=Paris, C=FR" ], "platformVersion" : 3, "serial" : 1532701331608 }, { "addresses" : [ "partyc0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyC, L=Paris, C=FR" ], "platformVersion" : |platform_version|, "serial" : 1532701331608 },
{ "addresses" : [ "partyb0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyB, L=New York, C=US" ], "platformVersion" : 3, "serial" : 1532701330118 }, { "addresses" : [ "partyb0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyB, L=New York, C=US" ], "platformVersion" : |platform_version|, "serial" : 1532701330118 },
{ "addresses" : [ "partya1:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyZ, L=London, C=GB" ], "platformVersion" : 3, "serial" : 1532701630861 } { "addresses" : [ "partya1:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyZ, L=London, C=GB" ], "platformVersion" : |platform_version|, "serial" : 1532701630861 }
] ]
Building a network in Graphical User Mode Building a network in Graphical User Mode
----------------------------------------- -----------------------------------------
The Corda Network Builder also provides a GUI for when automated interactions are not required. To launch it, run The Corda Network Builder also provides a GUI for when automated interactions are not required. To launch it, run
``java -jar <path/to/network-builder-jar> -g``. ``java -jar <path/to/corda-tools-network-builder.jar> -g``.
Starting the nodes Starting the nodes
^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
@ -146,10 +158,10 @@ see the running containers, the following output should be displayed:
.. sourcecode:: shell .. sourcecode:: shell
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
406868b4ba69 node-partyc:corda-network "/run-corda.sh" 17 seconds ago Up 16 seconds 0.0.0.0:32902->10003/tcp, 0.0.0.0:32895->10005/tcp, 0.0.0.0:32898->10020/tcp, 0.0.0.0:32900->12222/tcp partyc0 406868b4ba69 node-partyc:corda-network "run-corda" 17 seconds ago Up 16 seconds 0.0.0.0:32902->10003/tcp, 0.0.0.0:32895->10005/tcp, 0.0.0.0:32898->10020/tcp, 0.0.0.0:32900->12222/tcp partyc0
4546a2fa8de7 node-partyb:corda-network "/run-corda.sh" 17 seconds ago Up 17 seconds 0.0.0.0:32896->10003/tcp, 0.0.0.0:32899->10005/tcp, 0.0.0.0:32901->10020/tcp, 0.0.0.0:32903->12222/tcp partyb0 4546a2fa8de7 node-partyb:corda-network "run-corda" 17 seconds ago Up 17 seconds 0.0.0.0:32896->10003/tcp, 0.0.0.0:32899->10005/tcp, 0.0.0.0:32901->10020/tcp, 0.0.0.0:32903->12222/tcp partyb0
c8c44c515bdb node-partya:corda-network "/run-corda.sh" 17 seconds ago Up 17 seconds 0.0.0.0:32894->10003/tcp, 0.0.0.0:32897->10005/tcp, 0.0.0.0:32892->10020/tcp, 0.0.0.0:32893->12222/tcp partya0 c8c44c515bdb node-partya:corda-network "run-corda" 17 seconds ago Up 17 seconds 0.0.0.0:32894->10003/tcp, 0.0.0.0:32897->10005/tcp, 0.0.0.0:32892->10020/tcp, 0.0.0.0:32893->12222/tcp partya0
cf7ab689f493 node-notary:corda-network "/run-corda.sh" 30 seconds ago Up 31 seconds 0.0.0.0:32888->10003/tcp, 0.0.0.0:32889->10005/tcp, 0.0.0.0:32890->10020/tcp, 0.0.0.0:32891->12222/tcp notary0 cf7ab689f493 node-notary:corda-network "run-corda" 30 seconds ago Up 31 seconds 0.0.0.0:32888->10003/tcp, 0.0.0.0:32889->10005/tcp, 0.0.0.0:32890->10020/tcp, 0.0.0.0:32891->12222/tcp notary0
Interacting with the nodes Interacting with the nodes
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -173,11 +185,11 @@ node has been started correctly, run the following in the previously connected S
Tue Jul 17 15:47:14 GMT 2018>>> run networkMapSnapshot Tue Jul 17 15:47:14 GMT 2018>>> run networkMapSnapshot
[ [
{ "addresses" : [ "partya0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyA, L=London, C=GB" ], "platformVersion" : 3, "serial" : 1532701330613 }, { "addresses" : [ "partya0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyA, L=London, C=GB" ], "platformVersion" : |platform_version|, "serial" : 1532701330613 },
{ "addresses" : [ "notary0:10020" ], "legalIdentitiesAndCerts" : [ "O=Notary, L=London, C=GB" ], "platformVersion" : 3, "serial" : 1532701305115 }, { "addresses" : [ "notary0:10020" ], "legalIdentitiesAndCerts" : [ "O=Notary, L=London, C=GB" ], "platformVersion" : |platform_version|, "serial" : 1532701305115 },
{ "addresses" : [ "partyc0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyC, L=Paris, C=FR" ], "platformVersion" : 3, "serial" : 1532701331608 }, { "addresses" : [ "partyc0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyC, L=Paris, C=FR" ], "platformVersion" : |platform_version|, "serial" : 1532701331608 },
{ "addresses" : [ "partyb0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyB, L=New York, C=US" ], "platformVersion" : 3, "serial" : 1532701330118 }, { "addresses" : [ "partyb0:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyB, L=New York, C=US" ], "platformVersion" : |platform_version|, "serial" : 1532701330118 },
{ "addresses" : [ "partya1:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyZ, L=London, C=GB" ], "platformVersion" : 3, "serial" : 1532701630861 } { "addresses" : [ "partya1:10020" ], "legalIdentitiesAndCerts" : [ "O=PartyZ, L=London, C=GB" ], "platformVersion" : |platform_version|, "serial" : 1532701630861 }
] ]
Shutting down the nodes Shutting down the nodes

View File

@ -52,7 +52,7 @@ include 'tools:bootstrapper'
include 'tools:blobinspector' include 'tools:blobinspector'
include 'tools:shell' include 'tools:shell'
include 'tools:shell-cli' include 'tools:shell-cli'
include 'tools:network-bootstrapper' include 'tools:network-builder'
include 'tools:cliutils' include 'tools:cliutils'
include 'tools:worldmap' include 'tools:worldmap'
include 'example-code' include 'example-code'

View File

@ -1,49 +0,0 @@
package net.corda.bootstrapper.nodes
import com.github.dockerjava.core.command.BuildImageResultCallback
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigValueFactory
import net.corda.bootstrapper.docker.DockerUtils
import net.corda.common.configuration.parsing.internal.Configuration
import net.corda.common.validation.internal.Validated
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.config.parseAsNodeConfiguration
import org.slf4j.LoggerFactory
import java.io.File
open class NodeBuilder {
companion object {
val LOG = LoggerFactory.getLogger(NodeBuilder::class.java)
}
fun buildNode(copiedNode: CopiedNode): BuiltNode {
val localDockerClient = DockerUtils.createLocalDockerClient()
val copiedNodeConfig = copiedNode.copiedNodeConfig
val nodeDir = copiedNodeConfig.parentFile
if (!copiedNodeConfig.exists()) {
throw IllegalStateException("There is no nodeConfig for dir: $copiedNodeConfig")
}
val nodeConfig = ConfigFactory.parseFile(copiedNodeConfig)
LOG.info("starting to build docker image for: $nodeDir")
val nodeImageId = localDockerClient.buildImageCmd()
.withDockerfile(File(nodeDir, "Dockerfile"))
.withBaseDirectory(nodeDir)
.exec(BuildImageResultCallback()).awaitImageId()
LOG.info("finished building docker image for: $nodeDir with id: $nodeImageId")
val config = nodeConfig.parseAsNodeConfigWithFallback(ConfigFactory.parseFile(copiedNode.configFile)).value()
return copiedNode.builtNode(config, nodeImageId)
}
}
fun Config.parseAsNodeConfigWithFallback(preCopyConfig: Config): Validated<NodeConfiguration, Configuration.Validation.Error> {
val nodeConfig = this
.withValue("baseDirectory", ConfigValueFactory.fromAnyRef(""))
.withFallback(ConfigFactory.parseResources("reference.conf"))
.withFallback(preCopyConfig)
.resolve()
return nodeConfig.parseAsNodeConfiguration()
}

View File

@ -1,32 +0,0 @@
package net.corda.bootstrapper.nodes
import com.typesafe.config.ConfigException
import com.typesafe.config.ConfigFactory
import net.corda.bootstrapper.Constants
import net.corda.core.utilities.contextLogger
import java.io.File
class NodeFinder(private val scratchDir: File) {
fun findNodes(): List<FoundNode> {
return scratchDir.walkBottomUp().filter { it.name == "node.conf" && !it.absolutePath.contains(Constants.BOOTSTRAPPER_DIR_NAME) }.map {
try {
ConfigFactory.parseFile(it) to it
} catch (e: ConfigException) {
null
}
}.filterNotNull()
.filter { !it.first.hasPath("notary") }
.map { (_, nodeConfigFile) ->
LOG.info("We've found a node with name: ${nodeConfigFile.parentFile.name}")
FoundNode(nodeConfigFile, nodeConfigFile.parentFile)
}.toList()
}
companion object {
val LOG = contextLogger()
}
}

View File

@ -1,26 +0,0 @@
package net.corda.bootstrapper.notaries
import com.typesafe.config.ConfigException
import com.typesafe.config.ConfigFactory
import net.corda.bootstrapper.Constants
import net.corda.bootstrapper.nodes.FoundNode
import java.io.File
class NotaryFinder(private val dirToSearch: File) {
fun findNotaries(): List<FoundNode> {
return dirToSearch.walkBottomUp().filter { it.name == "node.conf" && !it.absolutePath.contains(Constants.BOOTSTRAPPER_DIR_NAME) }
.map {
try {
ConfigFactory.parseFile(it) to it
} catch (e: ConfigException) {
null
}
}.filterNotNull()
.filter { it.first.hasPath("notary") }
.map { (_, nodeConfigFile) ->
FoundNode(nodeConfigFile)
}.toList()
}
}

View File

@ -1,37 +0,0 @@
# Base image from (http://phusion.github.io/baseimage-docker)
FROM openjdk:8u151-jre-alpine
RUN apk upgrade --update && \
apk add --update --no-cache bash iputils && \
rm -rf /var/cache/apk/* && \
# Add user to run the app && \
addgroup corda && \
adduser -G corda -D -s /bin/bash corda && \
# Create /opt/corda directory && \
mkdir -p /opt/corda/plugins && \
mkdir -p /opt/corda/logs && \
mkdir -p /opt/corda/additional-node-infos && \
mkdir -p /opt/node-setup
# Copy corda files
ADD --chown=corda:corda corda.jar /opt/corda/corda.jar
ADD --chown=corda:corda node.conf /opt/corda/node.conf
ADD --chown=corda:corda cordapps/ /opt/corda/cordapps
# Copy node info watcher script
ADD --chown=corda:corda node_info_watcher.sh /opt/corda/
COPY run-corda.sh /run-corda.sh
RUN chmod +x /run-corda.sh && \
chmod +x /opt/corda/node_info_watcher.sh && \
sync && \
chown -R corda:corda /opt/corda
# Working directory for Corda
WORKDIR /opt/corda
ENV HOME=/opt/corda
USER corda
# Start it
CMD ["/run-corda.sh"]

View File

@ -1,39 +0,0 @@
# Base image from (http://phusion.github.io/baseimage-docker)
FROM openjdk:8u151-jre-alpine
RUN apk upgrade --update && \
apk add --update --no-cache bash iputils && \
rm -rf /var/cache/apk/* && \
# Add user to run the app && \
addgroup corda && \
adduser -G corda -D -s /bin/bash corda && \
# Create /opt/corda directory && \
mkdir -p /opt/corda/plugins && \
mkdir -p /opt/corda/logs && \
mkdir -p /opt/corda/additional-node-infos && \
mkdir -p /opt/node-setup
# Copy corda files
ADD --chown=corda:corda corda.jar /opt/corda/corda.jar
ADD --chown=corda:corda node.conf /opt/corda/node.conf
ADD --chown=corda:corda cordapps/ /opt/corda/cordapps
ADD --chown=corda:corda certificates/ /opt/corda/certificates
#ADD --chown=corda:corda nodeInfo-* /opt/corda/
# Copy node info watcher script
ADD --chown=corda:corda node_info_watcher.sh /opt/corda/
COPY run-corda.sh /run-corda.sh
RUN chmod +x /run-corda.sh && \
chmod +x /opt/corda/node_info_watcher.sh && \
sync && \
chown -R corda:corda /opt/corda
# Working directory for Corda
WORKDIR /opt/corda
ENV HOME=/opt/corda
USER corda
# Start it
CMD ["/run-corda.sh"]

View File

@ -7,9 +7,11 @@ apply plugin: 'idea'
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'application' apply plugin: 'application'
// We need to set mainClassName before applying the shadow plugin. // We need to set mainClassName before applying the shadow plugin.
mainClassName = 'net.corda.bootstrapper.Main' mainClassName = 'net.corda.networkbuilder.Main'
apply plugin: 'com.github.johnrengelman.shadow' apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'net.corda.plugins.publish-utils'
apply plugin: 'com.jfrog.artifactory'
configurations { configurations {
compile { compile {
@ -49,14 +51,32 @@ tasks.withType(JavaCompile) {
options.compilerArgs << '-proc:none' options.compilerArgs << '-proc:none'
} }
jar.enabled = false processResources {
from file("$rootDir/config/dev/log4j2.xml")
}
shadowJar { shadowJar {
baseName = 'network-bootstrapper' baseName = 'network-builder'
classifier = null classifier = null
version = null version = null
zip64 true zip64 true
} }
task buildNetworkBootstrapper(dependsOn: shadowJar) task buildNetworkBuilder(dependsOn: shadowJar)
assemble.dependsOn buildNetworkBootstrapper assemble.dependsOn buildNetworkBuilder
artifacts {
publish shadowJar {
classifier = ""
}
}
jar {
classifier "ignore"
enabled = false
}
publish {
disableDefaultJar = true
name 'corda-tools-network-builder'
}

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper; package net.corda.networkbuilder;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.embed.swing.JFXPanel; import javafx.embed.swing.JFXPanel;
@ -56,5 +56,4 @@ public class GuiUtils {
} catch (InterruptedException e) { } catch (InterruptedException e) {
} }
} }
} }

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper package net.corda.networkbuilder
import com.fasterxml.jackson.core.JsonGenerator import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.core.JsonParser
@ -12,12 +12,12 @@ import com.microsoft.azure.management.resources.fluentcore.arm.Region
class Constants { class Constants {
companion object { companion object {
val NODE_P2P_PORT = 10020 const val NODE_P2P_PORT = 10020
val NODE_SSHD_PORT = 12222 const val NODE_SSHD_PORT = 12222
val NODE_RPC_PORT = 10003 const val NODE_RPC_PORT = 10003
val NODE_RPC_ADMIN_PORT = 10005 const val NODE_RPC_ADMIN_PORT = 10005
val BOOTSTRAPPER_DIR_NAME = ".bootstrapper" const val BOOTSTRAPPER_DIR_NAME = ".bootstrapper"
fun getContextMapper(): ObjectMapper { fun getContextMapper(): ObjectMapper {
val objectMapper = ObjectMapper(YAMLFactory()).registerKotlinModule() val objectMapper = ObjectMapper(YAMLFactory()).registerKotlinModule()
@ -39,12 +39,10 @@ class Constants {
val ALPHA_NUMERIC_ONLY_REGEX = "[^\\p{IsAlphabetic}\\p{IsDigit}]".toRegex() val ALPHA_NUMERIC_ONLY_REGEX = "[^\\p{IsAlphabetic}\\p{IsDigit}]".toRegex()
val ALPHA_NUMERIC_DOT_AND_UNDERSCORE_ONLY_REGEX = "[^\\p{IsAlphabetic}\\p{IsDigit}._]".toRegex() val ALPHA_NUMERIC_DOT_AND_UNDERSCORE_ONLY_REGEX = "[^\\p{IsAlphabetic}\\p{IsDigit}._]".toRegex()
val REGION_ARG_NAME = "REGION" const val REGION_ARG_NAME = "REGION"
fun ResourceGroup.restFriendlyName(): String { fun ResourceGroup.restFriendlyName(): String {
return this.name().replace(ALPHA_NUMERIC_ONLY_REGEX, "").toLowerCase() return this.name().replace(ALPHA_NUMERIC_ONLY_REGEX, "").toLowerCase()
} }
} }
} }

View File

@ -1,16 +1,16 @@
@file:JvmName("Main") @file:JvmName("Main")
package net.corda.bootstrapper package net.corda.networkbuilder
import javafx.application.Application import javafx.application.Application
import net.corda.bootstrapper.backends.Backend import net.corda.networkbuilder.backends.Backend
import net.corda.bootstrapper.backends.Backend.BackendType.AZURE import net.corda.networkbuilder.backends.Backend.BackendType.AZURE
import net.corda.bootstrapper.cli.AzureParser import net.corda.networkbuilder.cli.AzureParser
import net.corda.bootstrapper.cli.CliParser import net.corda.networkbuilder.cli.CliParser
import net.corda.bootstrapper.cli.CommandLineInterface import net.corda.networkbuilder.cli.CommandLineInterface
import net.corda.bootstrapper.docker.DockerUtils import net.corda.networkbuilder.docker.DockerUtils
import net.corda.bootstrapper.gui.Gui import net.corda.networkbuilder.gui.Gui
import net.corda.bootstrapper.serialization.SerializationEngine import net.corda.networkbuilder.serialization.SerializationEngine
import picocli.CommandLine import picocli.CommandLine
import javax.ws.rs.ProcessingException import javax.ws.rs.ProcessingException
import kotlin.system.exitProcess import kotlin.system.exitProcess

View File

@ -1,10 +1,9 @@
package net.corda.bootstrapper package net.corda.networkbuilder
import net.corda.bootstrapper.backends.Backend import net.corda.networkbuilder.backends.Backend
import net.corda.bootstrapper.context.Context import net.corda.networkbuilder.context.Context
import net.corda.bootstrapper.nodes.* import net.corda.networkbuilder.nodes.*
import net.corda.bootstrapper.notaries.NotaryCopier import net.corda.networkbuilder.notaries.NotaryCopier
import net.corda.bootstrapper.notaries.NotaryFinder
import java.io.File import java.io.File
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
@ -21,8 +20,8 @@ interface NetworkBuilder {
fun onNodeBuild(callback: (BuiltNode) -> Unit): NetworkBuilder fun onNodeBuild(callback: (BuiltNode) -> Unit): NetworkBuilder
fun onNodePushed(callback: (PushedNode) -> Unit): NetworkBuilder fun onNodePushed(callback: (PushedNode) -> Unit): NetworkBuilder
fun onNodeInstance(callback: (NodeInstance) -> Unit): NetworkBuilder fun onNodeInstance(callback: (NodeInstance) -> Unit): NetworkBuilder
/** Sets network name */
fun withNetworkName(networtName: String): NetworkBuilder fun withNetworkName(networkName: String): NetworkBuilder
fun withBasedir(baseDir: File): NetworkBuilder fun withBasedir(baseDir: File): NetworkBuilder
fun withBackend(backendType: Backend.BackendType): NetworkBuilder fun withBackend(backendType: Backend.BackendType): NetworkBuilder
fun withBackendOptions(options: Map<String, String>): NetworkBuilder fun withBackendOptions(options: Map<String, String>): NetworkBuilder
@ -31,12 +30,10 @@ interface NetworkBuilder {
fun onNodeStartBuild(callback: (FoundNode) -> Unit): NetworkBuilder fun onNodeStartBuild(callback: (FoundNode) -> Unit): NetworkBuilder
fun onNodePushStart(callback: (BuiltNode) -> Unit): NetworkBuilder fun onNodePushStart(callback: (BuiltNode) -> Unit): NetworkBuilder
fun onNodeInstancesRequested(callback: (List<NodeInstanceRequest>) -> Unit): NetworkBuilder fun onNodeInstancesRequested(callback: (List<NodeInstanceRequest>) -> Unit): NetworkBuilder
} }
private class NetworkBuilderImpl : NetworkBuilder { private class NetworkBuilderImpl : NetworkBuilder {
@Volatile @Volatile
private var onNodeLocatedCallback: ((FoundNode) -> Unit) = {} private var onNodeLocatedCallback: ((FoundNode) -> Unit) = {}
@Volatile @Volatile
@ -76,10 +73,9 @@ private class NetworkBuilderImpl : NetworkBuilder {
return this return this
} }
override fun onNodeStartBuild(callback: (FoundNode) -> Unit): NetworkBuilder { override fun onNodeStartBuild(callback: (FoundNode) -> Unit): NetworkBuilder {
this.onNodeBuildStartCallback = callback this.onNodeBuildStartCallback = callback
return this; return this
} }
override fun onNodeBuild(callback: (BuiltNode) -> Unit): NetworkBuilder { override fun onNodeBuild(callback: (BuiltNode) -> Unit): NetworkBuilder {
@ -98,12 +94,12 @@ private class NetworkBuilderImpl : NetworkBuilder {
} }
override fun onNodeInstance(callback: (NodeInstance) -> Unit): NetworkBuilder { override fun onNodeInstance(callback: (NodeInstance) -> Unit): NetworkBuilder {
this.onNodeInstanceCallback = callback; this.onNodeInstanceCallback = callback
return this return this
} }
override fun withNetworkName(networtName: String): NetworkBuilder { override fun withNetworkName(networkName: String): NetworkBuilder {
this.networkName = networtName this.networkName = networkName
return this return this
} }
@ -123,19 +119,19 @@ private class NetworkBuilderImpl : NetworkBuilder {
} }
override fun onNodePushStart(callback: (BuiltNode) -> Unit): NetworkBuilder { override fun onNodePushStart(callback: (BuiltNode) -> Unit): NetworkBuilder {
this.onNodePushStartCallback = callback; this.onNodePushStartCallback = callback
return this; return this
} }
override fun build(): CompletableFuture<Pair<List<NodeInstance>, Context>> { override fun build(): CompletableFuture<Pair<List<NodeInstance>, Context>> {
val cacheDir = File(workingDir, cacheDirName) val cacheDir = File(workingDir, cacheDirName)
val baseDir = workingDir!! val baseDir = workingDir!!
val context = Context(networkName, backendType, backendOptions) val context = Context(networkName, backendType, backendOptions)
if (cacheDir.exists()) cacheDir.deleteRecursively() if (cacheDir.exists()) cacheDir.deleteRecursively()
val (containerPusher, instantiator, volume) = Backend.fromContext(context, cacheDir) val (containerPusher, instantiator, volume) = Backend.fromContext(context, cacheDir)
val nodeFinder = NodeFinder(baseDir) val nodeFinder = NodeFinder(baseDir)
val notaryFinder = NotaryFinder(baseDir) val notaryFinder = NodeFinder(baseDir)
val notaryCopier = NotaryCopier(cacheDir) val notaryCopier = NotaryCopier(cacheDir)
val nodeInstantiator = NodeInstantiator(instantiator, context) val nodeInstantiator = NodeInstantiator(instantiator, context)
@ -163,12 +159,21 @@ private class NetworkBuilderImpl : NetworkBuilder {
val notariesFuture = notaryDiscoveryFuture.thenCompose { copiedNotaries -> val notariesFuture = notaryDiscoveryFuture.thenCompose { copiedNotaries ->
copiedNotaries copiedNotaries
.map { copiedNotary -> .map { copiedNotary ->
nodeBuilder.buildNode(copiedNotary).also(onNodeBuiltCallback) nodeBuilder.buildNode(copiedNotary).thenAlsoAsync {
}.map { builtNotary -> onNodeBuildStartCallback.invoke(it)
}
}.map { builtNotaryFuture ->
builtNotaryFuture.thenComposeAsync { builtNotary ->
onNodeBuiltCallback(builtNotary)
onNodePushStartCallback(builtNotary) onNodePushStartCallback(builtNotary)
nodePusher.pushNode(builtNotary).thenApply { it.also(onNodePushedCallback) } nodePusher.pushNode(builtNotary).thenAlsoAsync { pushedNotary ->
onNodePushedCallback(pushedNotary)
}
}
}.map { pushedNotary -> }.map { pushedNotary ->
pushedNotary.thenApplyAsync { nodeInstantiator.createInstanceRequest(it).also { onNodeInstanceRequestedCallback.invoke(listOf(it)) } } pushedNotary.thenApplyAsync {
nodeInstantiator.createInstanceRequest(it).also { onNodeInstanceRequestedCallback(listOf(it)) }
}
}.map { instanceRequest -> }.map { instanceRequest ->
instanceRequest.thenComposeAsync { request -> instanceRequest.thenComposeAsync { request ->
nodeInstantiator.instantiateNotaryInstance(request).thenApply { it.also(onNodeInstanceCallback) } nodeInstantiator.instantiateNotaryInstance(request).thenApply { it.also(onNodeInstanceCallback) }
@ -185,17 +190,16 @@ private class NetworkBuilderImpl : NetworkBuilder {
} }
}.map { copiedNode: CopiedNode -> }.map { copiedNode: CopiedNode ->
onNodeBuildStartCallback.invoke(copiedNode) onNodeBuildStartCallback.invoke(copiedNode)
nodeBuilder.buildNode(copiedNode).let { nodeBuilder.buildNode(copiedNode)
onNodeBuiltCallback.invoke(it) }.map { builtNodeFuture ->
it builtNodeFuture.thenComposeAsync { builtNode ->
onNodeBuiltCallback.invoke(builtNode)
nodePusher.pushNode(builtNode).thenAlsoAsync { pushedNode ->
onNodePushedCallback.invoke(pushedNode)
} }
}.map { builtNode ->
nodePusher.pushNode(builtNode).thenApplyAsync {
onNodePushedCallback.invoke(it)
it
} }
}.map { pushedNode -> }.map { pushedNodeFuture ->
pushedNode.thenApplyAsync { pushedNodeFuture.thenApplyAsync {
nodeInstantiator.createInstanceRequests(it, nodeCount).also(onNodeInstanceRequestedCallback) nodeInstantiator.createInstanceRequests(it, nodeCount).also(onNodeInstanceRequestedCallback)
} }
@ -213,10 +217,10 @@ private class NetworkBuilderImpl : NetworkBuilder {
}.toSingleFuture() }.toSingleFuture()
}.thenCompose { it }.thenApplyAsync { it.flatten() } }.thenCompose { it }.thenApplyAsync { it.flatten() }
return notariesFuture.thenCombineAsync(nodesFuture, { _, nodeInstances -> return notariesFuture.thenCombineAsync(nodesFuture) { _, nodeInstances ->
context.networkInitiated = true context.networkInitiated = true
nodeInstances to context nodeInstances to context
}) }
} }
} }
@ -225,3 +229,11 @@ fun <T> List<CompletableFuture<T>>.toSingleFuture(): CompletableFuture<List<T>>
this.map { it.getNow(null) } this.map { it.getNow(null) }
} }
} }
/** Asynchronously runs `consumer` on the receiver CompletableFuture.*/
fun <T> CompletableFuture<T>.thenAlsoAsync(consumer: (T) -> Unit): CompletableFuture<T> {
return this.thenApplyAsync {
consumer(it)
it
}
}

View File

@ -1,15 +1,15 @@
package net.corda.bootstrapper.backends package net.corda.networkbuilder.backends
import com.microsoft.azure.CloudException import com.microsoft.azure.CloudException
import com.microsoft.azure.credentials.AzureCliCredentials import com.microsoft.azure.credentials.AzureCliCredentials
import com.microsoft.azure.management.Azure import com.microsoft.azure.management.Azure
import com.microsoft.rest.LogLevel import com.microsoft.rest.LogLevel
import net.corda.bootstrapper.Constants import net.corda.networkbuilder.Constants
import net.corda.bootstrapper.containers.instance.azure.AzureInstantiator import net.corda.networkbuilder.containers.instance.azure.AzureInstantiator
import net.corda.bootstrapper.containers.push.azure.AzureContainerPusher import net.corda.networkbuilder.containers.push.azure.AzureContainerPusher
import net.corda.bootstrapper.containers.push.azure.RegistryLocator import net.corda.networkbuilder.containers.push.azure.RegistryLocator
import net.corda.bootstrapper.context.Context import net.corda.networkbuilder.context.Context
import net.corda.bootstrapper.volumes.azure.AzureSmbVolume import net.corda.networkbuilder.volumes.azure.AzureSmbVolume
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
@ -49,14 +49,12 @@ data class AzureBackend(override val containerPusher: AzureContainerPusher,
RegistryLocator(azure, resourceGroup) RegistryLocator(azure, resourceGroup)
} }
val containerPusherFuture = registryLocatorFuture.thenApplyAsync { val containerPusherFuture = registryLocatorFuture.thenApplyAsync {
AzureContainerPusher(azure, it.registry) AzureContainerPusher(it.registry)
} }
val azureNetworkStore = CompletableFuture.supplyAsync { AzureSmbVolume(azure, resourceGroup) } val azureNetworkStore = CompletableFuture.supplyAsync { AzureSmbVolume(azure, resourceGroup) }
val azureInstantiatorFuture = azureNetworkStore.thenCombine(registryLocatorFuture, val azureInstantiatorFuture = azureNetworkStore.thenCombine(registryLocatorFuture) { azureVolume, registryLocator ->
{ azureVolume, registryLocator ->
AzureInstantiator(azure, registryLocator.registry, azureVolume, resourceGroup) AzureInstantiator(azure, registryLocator.registry, azureVolume, resourceGroup)
} }
)
return AzureBackend(containerPusherFuture.get(), azureInstantiatorFuture.get(), azureNetworkStore.get()) return AzureBackend(containerPusherFuture.get(), azureInstantiatorFuture.get(), azureNetworkStore.get())
} }
} }

View File

@ -1,11 +1,11 @@
package net.corda.bootstrapper.backends package net.corda.networkbuilder.backends
import net.corda.bootstrapper.backends.Backend.BackendType.AZURE import net.corda.networkbuilder.backends.Backend.BackendType.AZURE
import net.corda.bootstrapper.backends.Backend.BackendType.LOCAL_DOCKER import net.corda.networkbuilder.backends.Backend.BackendType.LOCAL_DOCKER
import net.corda.bootstrapper.containers.instance.Instantiator import net.corda.networkbuilder.containers.instance.Instantiator
import net.corda.bootstrapper.containers.push.ContainerPusher import net.corda.networkbuilder.containers.push.ContainerPusher
import net.corda.bootstrapper.context.Context import net.corda.networkbuilder.context.Context
import net.corda.bootstrapper.volumes.Volume import net.corda.networkbuilder.volumes.Volume
import java.io.File import java.io.File
interface Backend { interface Backend {
@ -26,12 +26,9 @@ interface Backend {
AZURE("Azure Containers"), LOCAL_DOCKER("Local Docker"); AZURE("Azure Containers"), LOCAL_DOCKER("Local Docker");
override fun toString(): String { override fun toString(): String {
return this.displayName return this.displayName
} }
} }
operator fun component1(): ContainerPusher { operator fun component1(): ContainerPusher {

View File

@ -1,16 +1,15 @@
package net.corda.bootstrapper.backends package net.corda.networkbuilder.backends
import net.corda.bootstrapper.containers.instance.docker.DockerInstantiator import net.corda.networkbuilder.containers.instance.docker.DockerInstantiator
import net.corda.bootstrapper.containers.push.docker.DockerContainerPusher import net.corda.networkbuilder.containers.push.docker.DockerContainerPusher
import net.corda.bootstrapper.context.Context import net.corda.networkbuilder.context.Context
import net.corda.bootstrapper.volumes.docker.LocalVolume import net.corda.networkbuilder.volumes.docker.LocalVolume
import java.io.File import java.io.File
class DockerBackend(override val containerPusher: DockerContainerPusher, class DockerBackend(override val containerPusher: DockerContainerPusher,
override val instantiator: DockerInstantiator, override val instantiator: DockerInstantiator,
override val volume: LocalVolume) : Backend { override val volume: LocalVolume) : Backend {
companion object { companion object {
fun fromContext(context: Context, baseDir: File): DockerBackend { fun fromContext(context: Context, baseDir: File): DockerBackend {
val dockerContainerPusher = DockerContainerPusher() val dockerContainerPusher = DockerContainerPusher()
@ -19,7 +18,4 @@ class DockerBackend(override val containerPusher: DockerContainerPusher,
return DockerBackend(dockerContainerPusher, dockerInstantiator, localVolume) return DockerBackend(dockerContainerPusher, dockerInstantiator, localVolume)
} }
} }
} }

View File

@ -1,13 +1,13 @@
package net.corda.bootstrapper.cli package net.corda.networkbuilder.cli
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import net.corda.bootstrapper.Constants import net.corda.networkbuilder.Constants
import net.corda.bootstrapper.NetworkBuilder import net.corda.networkbuilder.NetworkBuilder
import net.corda.bootstrapper.backends.Backend import net.corda.networkbuilder.backends.Backend
import net.corda.bootstrapper.context.Context import net.corda.networkbuilder.context.Context
import net.corda.bootstrapper.nodes.NodeAdder import net.corda.networkbuilder.nodes.NodeAdder
import net.corda.bootstrapper.nodes.NodeInstantiator import net.corda.networkbuilder.nodes.NodeInstantiator
import net.corda.bootstrapper.toSingleFuture import net.corda.networkbuilder.toSingleFuture
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import java.io.File import java.io.File
@ -44,13 +44,12 @@ class CommandLineInterface {
}.toSingleFuture().getOrThrow() }.toSingleFuture().getOrThrow()
persistContext(contextFile, objectMapper, context) persistContext(contextFile, objectMapper, context)
} }
} }
private fun setupContextFromExisting(contextFile: File, objectMapper: ObjectMapper): Context { private fun setupContextFromExisting(contextFile: File, objectMapper: ObjectMapper): Context {
return contextFile.let { return contextFile.let { file ->
if (it.exists()) { if (file.exists()) {
it.inputStream().use { file.inputStream().use {
objectMapper.readValue(it, Context::class.java) objectMapper.readValue(it, Context::class.java)
} }
} else { } else {
@ -59,7 +58,6 @@ class CommandLineInterface {
} }
} }
private fun persistContext(contextFile: File, objectMapper: ObjectMapper, context: Context?) { private fun persistContext(contextFile: File, objectMapper: ObjectMapper, context: Context?) {
contextFile.outputStream().use { contextFile.outputStream().use {
objectMapper.writeValue(it, context) objectMapper.writeValue(it, context)

View File

@ -1,8 +1,8 @@
package net.corda.bootstrapper.cli package net.corda.networkbuilder.cli
import com.microsoft.azure.management.resources.fluentcore.arm.Region import com.microsoft.azure.management.resources.fluentcore.arm.Region
import net.corda.bootstrapper.Constants import net.corda.networkbuilder.Constants
import net.corda.bootstrapper.backends.Backend import net.corda.networkbuilder.backends.Backend
import picocli.CommandLine import picocli.CommandLine
import picocli.CommandLine.Option import picocli.CommandLine.Option
import java.io.File import java.io.File

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper.containers.instance package net.corda.networkbuilder.containers.instance
data class InstanceInfo(val groupId: String, data class InstanceInfo(val groupId: String,
val instanceName: String, val instanceName: String,

View File

@ -1,17 +1,15 @@
package net.corda.bootstrapper.containers.instance package net.corda.networkbuilder.containers.instance
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
interface Instantiator { interface Instantiator {
fun instantiateContainer(imageId: String, fun instantiateContainer(imageId: String,
portsToOpen: List<Int>, portsToOpen: List<Int>,
instanceName: String, instanceName: String,
env: Map<String, String>? = null): CompletableFuture<Pair<String, Map<Int, Int>>> env: Map<String, String>? = null): CompletableFuture<Pair<String, Map<Int, Int>>>
companion object { companion object {
val ADDITIONAL_NODE_INFOS_PATH = "/opt/corda/additional-node-infos" const val ADDITIONAL_NODE_INFOS_PATH = "/opt/corda/additional-node-infos"
} }
fun getExpectedFQDN(instanceName: String): String fun getExpectedFQDN(instanceName: String): String

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper.containers.instance.azure package net.corda.networkbuilder.containers.instance.azure
import com.microsoft.azure.management.Azure import com.microsoft.azure.management.Azure
import com.microsoft.azure.management.containerinstance.ContainerGroup import com.microsoft.azure.management.containerinstance.ContainerGroup
@ -6,11 +6,11 @@ import com.microsoft.azure.management.containerinstance.ContainerGroupRestartPol
import com.microsoft.azure.management.containerregistry.Registry import com.microsoft.azure.management.containerregistry.Registry
import com.microsoft.azure.management.resources.ResourceGroup import com.microsoft.azure.management.resources.ResourceGroup
import com.microsoft.rest.ServiceCallback import com.microsoft.rest.ServiceCallback
import net.corda.bootstrapper.Constants.Companion.restFriendlyName import net.corda.networkbuilder.Constants.Companion.restFriendlyName
import net.corda.bootstrapper.containers.instance.Instantiator import net.corda.networkbuilder.containers.instance.Instantiator
import net.corda.bootstrapper.containers.instance.Instantiator.Companion.ADDITIONAL_NODE_INFOS_PATH import net.corda.networkbuilder.containers.instance.Instantiator.Companion.ADDITIONAL_NODE_INFOS_PATH
import net.corda.bootstrapper.containers.push.azure.RegistryLocator.Companion.parseCredentials import net.corda.networkbuilder.containers.push.azure.RegistryLocator.Companion.parseCredentials
import net.corda.bootstrapper.volumes.azure.AzureSmbVolume import net.corda.networkbuilder.volumes.azure.AzureSmbVolume
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
@ -28,9 +28,9 @@ class AzureInstantiator(private val azure: Azure,
LOG.info("Starting instantiation of container: $instanceName using $imageId") LOG.info("Starting instantiation of container: $instanceName using $imageId")
val registryAddress = registry.loginServerUrl() val registryAddress = registry.loginServerUrl()
val (username, password) = registry.parseCredentials(); val (username, password) = registry.parseCredentials()
val mountName = "node-setup" val mountName = "node-setup"
val future = CompletableFuture<Pair<String, Map<Int, Int>>>().also { return CompletableFuture<Pair<String, Map<Int, Int>>>().also {
azure.containerGroups().define(buildIdent(instanceName)) azure.containerGroups().define(buildIdent(instanceName))
.withRegion(resourceGroup.region()) .withRegion(resourceGroup.region())
.withExistingResourceGroup(resourceGroup) .withExistingResourceGroup(resourceGroup)
@ -56,11 +56,10 @@ class AzureInstantiator(private val azure: Azure,
override fun success(result: ContainerGroup) { override fun success(result: ContainerGroup) {
val fqdn = result.fqdn() val fqdn = result.fqdn()
LOG.info("Completed instantiation: $instanceName is running at $fqdn with port(s) $portsToOpen exposed") LOG.info("Completed instantiation: $instanceName is running at $fqdn with port(s) $portsToOpen exposed")
it.complete(result.fqdn() to portsToOpen.map { it to it }.toMap()) it.complete(result.fqdn() to portsToOpen.map { port -> port to port }.toMap())
} }
}) })
} }
return future
} }
private fun buildIdent(instanceName: String) = "$instanceName-${resourceGroup.restFriendlyName()}" private fun buildIdent(instanceName: String) = "$instanceName-${resourceGroup.restFriendlyName()}"
@ -75,11 +74,10 @@ class AzureInstantiator(private val azure: Azure,
LOG.info("Found an existing instance of: $containerName destroying ContainerGroup") LOG.info("Found an existing instance of: $containerName destroying ContainerGroup")
azure.containerGroups().deleteByResourceGroup(resourceGroup.name(), containerName) azure.containerGroups().deleteByResourceGroup(resourceGroup.name(), containerName)
} }
return existingContainer; return existingContainer
} }
companion object { companion object {
val LOG = LoggerFactory.getLogger(AzureInstantiator::class.java) val LOG = LoggerFactory.getLogger(AzureInstantiator::class.java)
} }
} }

View File

@ -1,19 +1,18 @@
package net.corda.bootstrapper.containers.instance.docker package net.corda.networkbuilder.containers.instance.docker
import com.github.dockerjava.api.model.* import com.github.dockerjava.api.model.*
import net.corda.bootstrapper.Constants import net.corda.networkbuilder.Constants
import net.corda.bootstrapper.containers.instance.Instantiator import net.corda.networkbuilder.containers.instance.Instantiator
import net.corda.bootstrapper.context.Context import net.corda.networkbuilder.context.Context
import net.corda.bootstrapper.docker.DockerUtils import net.corda.networkbuilder.docker.DockerUtils
import net.corda.bootstrapper.volumes.docker.LocalVolume import net.corda.networkbuilder.volumes.docker.LocalVolume
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class DockerInstantiator(private val volume: LocalVolume, class DockerInstantiator(private val volume: LocalVolume,
private val context: Context) : Instantiator { private val context: Context) : Instantiator {
val networkId = setupNetwork(); private val networkId = setupNetwork()
override fun instantiateContainer(imageId: String, override fun instantiateContainer(imageId: String,
portsToOpen: List<Int>, portsToOpen: List<Int>,
@ -43,7 +42,9 @@ class DockerInstantiator(private val volume: LocalVolume,
} }
LOG.info("starting local docker instance of: $imageId with name $instanceName and env: $env") LOG.info("starting local docker instance of: $imageId with name $instanceName and env: $env")
val ports = (portsToOpen + Constants.NODE_RPC_ADMIN_PORT).map { ExposedPort.tcp(it) }.map { PortBinding(null, it) }.let { Ports(*it.toTypedArray()) } val ports = (portsToOpen + Constants.NODE_RPC_ADMIN_PORT).map { ExposedPort.tcp(it) }
.map { PortBinding(null, it) }
.let { Ports(*it.toTypedArray()) }
val createCmd = localClient.createContainerCmd(imageId) val createCmd = localClient.createContainerCmd(imageId)
.withName(instanceName) .withName(instanceName)
.withVolumes(nodeInfosVolume) .withVolumes(nodeInfosVolume)
@ -56,25 +57,20 @@ class DockerInstantiator(private val volume: LocalVolume,
localClient.startContainerCmd(createCmd.id).exec() localClient.startContainerCmd(createCmd.id).exec()
val foundContainer = localClient.listContainersCmd().exec() val foundContainer = localClient.listContainersCmd().exec()
.filter { it.id == (createCmd.id) } .firstOrNull { it.id == createCmd.id }
.firstOrNull()
val portMappings = foundContainer?.ports?.map { val portMappings = foundContainer?.ports?.map {
(it.privatePort ?: 0) to (it.publicPort ?: 0) (it.privatePort ?: 0) to (it.publicPort ?: 0)
}?.toMap()?.toMap() }?.toMap()?.toMap()
?: portsToOpen.map { it to it }.toMap() ?: portsToOpen.map { it to it }.toMap()
return CompletableFuture.completedFuture(("localhost") to portMappings) return CompletableFuture.completedFuture(("localhost") to portMappings)
} }
private fun buildDockerEnv(env: Map<String, String>?) = private fun buildDockerEnv(env: Map<String, String>?) =
(env ?: emptyMap()).entries.map { (key, value) -> "$key=$value" }.toList() (env ?: emptyMap()).entries.map { (key, value) -> "$key=$value" }.toList()
override fun getExpectedFQDN(instanceName: String): String { override fun getExpectedFQDN(instanceName: String): String = instanceName
return instanceName
}
private fun setupNetwork(): String { private fun setupNetwork(): String {
val createLocalDockerClient = DockerUtils.createLocalDockerClient() val createLocalDockerClient = DockerUtils.createLocalDockerClient()

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper.containers.push package net.corda.networkbuilder.containers.push
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture

View File

@ -1,25 +1,21 @@
package net.corda.bootstrapper.containers.push.azure package net.corda.networkbuilder.containers.push.azure
import com.github.dockerjava.api.async.ResultCallback import com.github.dockerjava.api.async.ResultCallback
import com.github.dockerjava.api.model.PushResponseItem import com.github.dockerjava.api.model.PushResponseItem
import com.microsoft.azure.management.Azure
import com.microsoft.azure.management.containerregistry.Registry import com.microsoft.azure.management.containerregistry.Registry
import net.corda.bootstrapper.containers.push.ContainerPusher import net.corda.networkbuilder.containers.push.ContainerPusher
import net.corda.bootstrapper.containers.push.azure.RegistryLocator.Companion.parseCredentials import net.corda.networkbuilder.containers.push.azure.RegistryLocator.Companion.parseCredentials
import net.corda.bootstrapper.docker.DockerUtils import net.corda.networkbuilder.docker.DockerUtils
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.Closeable import java.io.Closeable
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class AzureContainerPusher(private val azureRegistry: Registry) : ContainerPusher {
class AzureContainerPusher(private val azure: Azure, private val azureRegistry: Registry) : ContainerPusher {
override fun pushContainerToImageRepository(localImageId: String, override fun pushContainerToImageRepository(localImageId: String,
remoteImageName: String, remoteImageName: String,
networkName: String): CompletableFuture<String> { networkName: String): CompletableFuture<String> {
val (registryUser, registryPassword) = azureRegistry.parseCredentials() val (registryUser, registryPassword) = azureRegistry.parseCredentials()
val dockerClient = DockerUtils.createDockerClient( val dockerClient = DockerUtils.createDockerClient(
azureRegistry.loginServerUrl(), azureRegistry.loginServerUrl(),
@ -57,6 +53,4 @@ class AzureContainerPusher(private val azure: Azure, private val azureRegistry:
companion object { companion object {
val LOG = LoggerFactory.getLogger(AzureContainerPusher::class.java) val LOG = LoggerFactory.getLogger(AzureContainerPusher::class.java)
} }
} }

View File

@ -1,37 +1,34 @@
package net.corda.bootstrapper.containers.push.azure package net.corda.networkbuilder.containers.push.azure
import com.microsoft.azure.management.Azure import com.microsoft.azure.management.Azure
import com.microsoft.azure.management.containerregistry.AccessKeyType import com.microsoft.azure.management.containerregistry.AccessKeyType
import com.microsoft.azure.management.containerregistry.Registry import com.microsoft.azure.management.containerregistry.Registry
import com.microsoft.azure.management.resources.ResourceGroup import com.microsoft.azure.management.resources.ResourceGroup
import net.corda.bootstrapper.Constants.Companion.restFriendlyName import net.corda.networkbuilder.Constants.Companion.restFriendlyName
import net.corda.bootstrapper.containers.instance.azure.AzureInstantiator import net.corda.networkbuilder.containers.instance.azure.AzureInstantiator
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
class RegistryLocator(private val azure: Azure, class RegistryLocator(private val azure: Azure,
private val resourceGroup: ResourceGroup) { private val resourceGroup: ResourceGroup) {
val registry: Registry = locateRegistry() val registry: Registry = locateRegistry()
private fun locateRegistry(): Registry { private fun locateRegistry(): Registry {
LOG.info("Attempting to find existing registry with name: ${resourceGroup.restFriendlyName()}") LOG.info("Attempting to find existing registry with name: ${resourceGroup.restFriendlyName()}")
val found = azure.containerRegistries().getByResourceGroup(resourceGroup.name(), resourceGroup.restFriendlyName()) val found = azure.containerRegistries().getByResourceGroup(resourceGroup.name(), resourceGroup.restFriendlyName())
if (found == null) { return if (found == null) {
LOG.info("Did not find existing container registry - creating new registry with name ${resourceGroup.restFriendlyName()}") LOG.info("Did not find existing container registry - creating new registry with name ${resourceGroup.restFriendlyName()}")
return azure.containerRegistries() azure.containerRegistries()
.define(resourceGroup.restFriendlyName()) .define(resourceGroup.restFriendlyName())
.withRegion(resourceGroup.region().name()) .withRegion(resourceGroup.region().name())
.withExistingResourceGroup(resourceGroup) .withExistingResourceGroup(resourceGroup)
.withBasicSku() .withBasicSku()
.withRegistryNameAsAdminUser() .withRegistryNameAsAdminUser()
.create() .create()
} else { } else {
LOG.info("found existing registry with name: ${resourceGroup.restFriendlyName()} reusing") LOG.info("found existing registry with name: ${resourceGroup.restFriendlyName()} reusing")
return found found
} }
} }
@ -44,12 +41,5 @@ class RegistryLocator(private val azure: Azure,
} }
val LOG = LoggerFactory.getLogger(AzureInstantiator::class.java) val LOG = LoggerFactory.getLogger(AzureInstantiator::class.java)
} }
} }

View File

@ -1,12 +1,11 @@
package net.corda.bootstrapper.containers.push.docker package net.corda.networkbuilder.containers.push.docker
import net.corda.bootstrapper.containers.push.ContainerPusher import net.corda.networkbuilder.containers.push.ContainerPusher
import net.corda.bootstrapper.docker.DockerUtils import net.corda.networkbuilder.docker.DockerUtils
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class DockerContainerPusher : ContainerPusher { class DockerContainerPusher : ContainerPusher {
override fun pushContainerToImageRepository(localImageId: String, remoteImageName: String, networkName: String): CompletableFuture<String> { override fun pushContainerToImageRepository(localImageId: String, remoteImageName: String, networkName: String): CompletableFuture<String> {
val dockerClient = DockerUtils.createLocalDockerClient() val dockerClient = DockerUtils.createLocalDockerClient()
dockerClient.tagImageCmd(localImageId, remoteImageName, networkName).withForce().exec() dockerClient.tagImageCmd(localImageId, remoteImageName, networkName).withForce().exec()

View File

@ -1,15 +1,14 @@
package net.corda.bootstrapper.context package net.corda.networkbuilder.context
import net.corda.bootstrapper.Constants import net.corda.networkbuilder.Constants
import net.corda.bootstrapper.backends.Backend import net.corda.networkbuilder.backends.Backend
import net.corda.bootstrapper.nodes.NodeInstanceRequest import net.corda.networkbuilder.nodes.NodeInstanceRequest
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
class Context(val networkName: String, val backendType: Backend.BackendType, backendOptions: Map<String, String> = emptyMap()) { class Context(val networkName: String, val backendType: Backend.BackendType, backendOptions: Map<String, String> = emptyMap()) {
@Volatile @Volatile
var safeNetworkName: String = networkName.replace(Constants.ALPHA_NUMERIC_ONLY_REGEX, "").toLowerCase() var safeNetworkName: String = networkName.replace(Constants.ALPHA_NUMERIC_ONLY_REGEX, "").toLowerCase()
@ -30,7 +29,6 @@ class Context(val networkName: String, val backendType: Backend.BackendType, bac
registerNode(request.name, request) registerNode(request.name, request)
} }
data class PersistableNodeInstance( data class PersistableNodeInstance(
val groupName: String, val groupName: String,
val groupX500: CordaX500Name?, val groupX500: CordaX500Name?,
@ -43,7 +41,6 @@ class Context(val networkName: String, val backendType: Backend.BackendType, bac
val rpcUser: String, val rpcUser: String,
val rpcPassword: String) val rpcPassword: String)
companion object { companion object {
fun fromInstanceRequest(nodeInstanceRequest: NodeInstanceRequest): PersistableNodeInstance { fun fromInstanceRequest(nodeInstanceRequest: NodeInstanceRequest): PersistableNodeInstance {
return PersistableNodeInstance( return PersistableNodeInstance(
@ -58,7 +55,6 @@ class Context(val networkName: String, val backendType: Backend.BackendType, bac
"", "",
"" ""
) )
} }
} }

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper.docker package net.corda.networkbuilder.docker
import com.github.dockerjava.api.DockerClient import com.github.dockerjava.api.DockerClient
import com.github.dockerjava.core.DefaultDockerClientConfig import com.github.dockerjava.core.DefaultDockerClientConfig
@ -30,6 +30,4 @@ object DockerUtils {
.withRegistryPassword(password) .withRegistryPassword(password)
.build() .build()
} }
} }

View File

@ -1,6 +1,7 @@
package net.corda.bootstrapper.gui package net.corda.networkbuilder.gui
import com.microsoft.azure.management.resources.fluentcore.arm.Region import com.microsoft.azure.management.resources.fluentcore.arm.Region
import javafx.beans.binding.Bindings
import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleObjectProperty
import javafx.beans.property.SimpleStringProperty import javafx.beans.property.SimpleStringProperty
import javafx.collections.ObservableListBase import javafx.collections.ObservableListBase
@ -13,14 +14,13 @@ import javafx.scene.layout.HBox
import javafx.scene.layout.Priority import javafx.scene.layout.Priority
import javafx.scene.layout.VBox import javafx.scene.layout.VBox
import javafx.stage.DirectoryChooser import javafx.stage.DirectoryChooser
import net.corda.bootstrapper.Constants import net.corda.networkbuilder.Constants
import net.corda.bootstrapper.GuiUtils import net.corda.networkbuilder.GuiUtils
import net.corda.bootstrapper.NetworkBuilder import net.corda.networkbuilder.NetworkBuilder
import net.corda.bootstrapper.backends.Backend import net.corda.networkbuilder.backends.Backend
import net.corda.bootstrapper.baseArgs import net.corda.networkbuilder.baseArgs
import net.corda.bootstrapper.context.Context import net.corda.networkbuilder.context.Context
import net.corda.bootstrapper.nodes.* import net.corda.networkbuilder.nodes.*
import net.corda.bootstrapper.notaries.NotaryFinder
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import org.apache.commons.lang3.RandomStringUtils import org.apache.commons.lang3.RandomStringUtils
import org.controlsfx.control.SegmentedButton import org.controlsfx.control.SegmentedButton
@ -50,7 +50,7 @@ class BootstrapperView : View("Corda Network Builder") {
visuallyTweakBackendSelector() visuallyTweakBackendSelector()
buildButton.run { buildButton.run {
enableWhen { controller.baseDir.isNotNull } enableWhen { controller.hasNodesOrNotaries.and(controller.baseDir.isNotNull) }
action { action {
var networkName = "corda-network" var networkName = "corda-network"
@ -104,7 +104,6 @@ class BootstrapperView : View("Corda Network Builder") {
override fun get(index: Int): String { override fun get(index: Int): String {
return controller.foundNodes[index].id return controller.foundNodes[index].id
} }
override val size: Int override val size: Int
get() = controller.foundNodes.size get() = controller.foundNodes.size
} }
@ -139,7 +138,8 @@ class BootstrapperView : View("Corda Network Builder") {
it.instanceName, it.instanceName,
it.instanceAddress, it.instanceAddress,
it.reachableAddress, it.reachableAddress,
it.portMapping[Constants.NODE_P2P_PORT] ?: Constants.NODE_P2P_PORT, it.portMapping[Constants.NODE_P2P_PORT]
?: Constants.NODE_P2P_PORT,
it.portMapping[Constants.NODE_SSHD_PORT] it.portMapping[Constants.NODE_SSHD_PORT]
?: Constants.NODE_SSHD_PORT)) ?: Constants.NODE_SSHD_PORT))
} }
@ -160,7 +160,7 @@ class BootstrapperView : View("Corda Network Builder") {
columnResizePolicy = TableView.CONSTRAINED_RESIZE_POLICY columnResizePolicy = TableView.CONSTRAINED_RESIZE_POLICY
hgrow = Priority.ALWAYS hgrow = Priority.ALWAYS
onMouseClicked = EventHandler<MouseEvent> { _ -> onMouseClicked = EventHandler<MouseEvent> {
val selectedItem: NodeTemplateInfo = selectionModel.selectedItem ?: return@EventHandler val selectedItem: NodeTemplateInfo = selectionModel.selectedItem ?: return@EventHandler
infoTextArea.text = YAML_MAPPER.writeValueAsString(translateForPrinting(selectedItem)) infoTextArea.text = YAML_MAPPER.writeValueAsString(translateForPrinting(selectedItem))
} }
@ -221,17 +221,17 @@ class BootstrapperView : View("Corda Network Builder") {
nodeFinder.findNodes() nodeFinder.findNodes()
} }
val foundNotaries = CompletableFuture.supplyAsync { val foundNotaries = CompletableFuture.supplyAsync {
val notaryFinder = NotaryFinder(dir) val notaryFinder = NodeFinder(dir)
notaryFinder.findNotaries() notaryFinder.findNotaries()
} }
foundNodes.thenCombine(foundNotaries) { nodes, notaries -> foundNodes.thenCombine(foundNotaries) { nodes, notaries ->
notaries to nodes notaries to nodes
}.thenAcceptAsync({ (notaries: List<FoundNode>, nodes: List<FoundNode>) -> }.thenAcceptAsync { (notaries: List<FoundNode>, nodes: List<FoundNode>) ->
runLater { runLater {
controller.foundNodes(nodes) controller.foundNodes(nodes)
controller.notaries(notaries) controller.notaries(notaries)
} }
}) }
} }
class NodeTemplateInfo(templateId: String, type: NodeType) { class NodeTemplateInfo(templateId: String, type: NodeType) {
@ -260,7 +260,7 @@ class BootstrapperView : View("Corda Network Builder") {
val foundNodes = Collections.synchronizedList(ArrayList<FoundNodeTableEntry>()).observable() val foundNodes = Collections.synchronizedList(ArrayList<FoundNodeTableEntry>()).observable()
val foundNotaries = Collections.synchronizedList(ArrayList<FoundNode>()).observable() val foundNotaries = Collections.synchronizedList(ArrayList<FoundNode>()).observable()
val networkContext = SimpleObjectProperty<Context>(null) val networkContext = SimpleObjectProperty<Context>(null)
var hasNodesOrNotaries = Bindings.size(foundNotaries).greaterThan(0).or(Bindings.size(foundNotaries).greaterThan(0))
val unsortedNodes = Collections.synchronizedList(ArrayList<NodeTemplateInfo>()).observable() val unsortedNodes = Collections.synchronizedList(ArrayList<NodeTemplateInfo>()).observable()
val sortedNodes = SortedList(unsortedNodes, Comparator<NodeTemplateInfo> { o1, o2 -> val sortedNodes = SortedList(unsortedNodes, Comparator<NodeTemplateInfo> { o1, o2 ->
compareValues(o1.nodeType.toString() + o1.templateId, o2.nodeType.toString() + o2.templateId) * -1 compareValues(o1.nodeType.toString() + o1.templateId, o2.nodeType.toString() + o2.templateId) * -1
@ -324,8 +324,10 @@ class BootstrapperView : View("Corda Network Builder") {
nodeInstance.nodeInstanceName, nodeInstance.nodeInstanceName,
nodeInstance.expectedFqName, nodeInstance.expectedFqName,
nodeInstance.reachableAddress, nodeInstance.reachableAddress,
nodeInstance.portMapping[Constants.NODE_P2P_PORT] ?: Constants.NODE_P2P_PORT, nodeInstance.portMapping[Constants.NODE_P2P_PORT]
nodeInstance.portMapping[Constants.NODE_SSHD_PORT] ?: Constants.NODE_SSHD_PORT) ?: Constants.NODE_P2P_PORT,
nodeInstance.portMapping[Constants.NODE_SSHD_PORT]
?: Constants.NODE_SSHD_PORT)
) )
} }

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper.gui package net.corda.networkbuilder.gui
import javafx.stage.Stage import javafx.stage.Stage
import tornadofx.App import tornadofx.App

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper.nodes package net.corda.networkbuilder.nodes
import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.NodeConfiguration
import java.io.File import java.io.File
@ -7,7 +7,6 @@ open class BuiltNode(configFile: File, baseDirectory: File,
copiedNodeConfig: File, copiedNodeDir: File, copiedNodeConfig: File, copiedNodeDir: File,
val nodeConfig: NodeConfiguration, val localImageId: String) : CopiedNode(configFile, baseDirectory, copiedNodeConfig, copiedNodeDir) { val nodeConfig: NodeConfiguration, val localImageId: String) : CopiedNode(configFile, baseDirectory, copiedNodeConfig, copiedNodeDir) {
override fun toString(): String { override fun toString(): String {
return "BuiltNode(" + return "BuiltNode(" +
"nodeConfig=$nodeConfig," + "nodeConfig=$nodeConfig," +

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper.nodes package net.corda.networkbuilder.nodes
import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.NodeConfiguration
import java.io.File import java.io.File
@ -12,11 +12,11 @@ open class CopiedNode(configFile: File, baseDirectory: File,
) )
operator fun component4(): File { operator fun component4(): File {
return copiedNodeDir; return copiedNodeDir
} }
operator fun component5(): File { operator fun component5(): File {
return copiedNodeConfig; return copiedNodeConfig
} }
@ -35,6 +35,4 @@ open class CopiedNode(configFile: File, baseDirectory: File,
fun toBuiltNode(nodeConfig: NodeConfiguration, localImageId: String): BuiltNode { fun toBuiltNode(nodeConfig: NodeConfiguration, localImageId: String): BuiltNode {
return BuiltNode(this.configFile, this.baseDirectory, this.copiedNodeConfig, this.copiedNodeDir, nodeConfig, localImageId) return BuiltNode(this.configFile, this.baseDirectory, this.copiedNodeConfig, this.copiedNodeDir, nodeConfig, localImageId)
} }
} }

View File

@ -1,22 +1,22 @@
package net.corda.bootstrapper.nodes package net.corda.networkbuilder.nodes
import net.corda.networkbuilder.Constants
import java.io.File import java.io.File
open class FoundNode(open val configFile: File, open class FoundNode(open val configFile: File,
open val baseDirectory: File = configFile.parentFile, open val baseDirectory: File = configFile.parentFile,
val name: String = configFile.parentFile.name.toLowerCase().replace(net.corda.bootstrapper.Constants.ALPHA_NUMERIC_ONLY_REGEX, "")) { val name: String = configFile.parentFile.name.toLowerCase().replace(Constants.ALPHA_NUMERIC_ONLY_REGEX, "")) {
operator fun component1(): File { operator fun component1(): File {
return baseDirectory; return baseDirectory
} }
operator fun component2(): File { operator fun component2(): File {
return configFile; return configFile
} }
operator fun component3(): String { operator fun component3(): String {
return name; return name
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
@ -46,8 +46,4 @@ open class FoundNode(open val configFile: File,
fun toCopiedNode(copiedNodeConfig: File, copiedNodeDir: File): CopiedNode { fun toCopiedNode(copiedNodeConfig: File, copiedNodeDir: File): CopiedNode {
return CopiedNode(this.configFile, this.baseDirectory, copiedNodeConfig, copiedNodeDir) return CopiedNode(this.configFile, this.baseDirectory, copiedNodeConfig, copiedNodeDir)
} }
} }

View File

@ -1,7 +1,7 @@
package net.corda.bootstrapper.nodes package net.corda.networkbuilder.nodes
import net.corda.bootstrapper.containers.instance.InstanceInfo import net.corda.networkbuilder.containers.instance.InstanceInfo
import net.corda.bootstrapper.context.Context import net.corda.networkbuilder.context.Context
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture

View File

@ -0,0 +1,71 @@
package net.corda.networkbuilder.nodes
import com.github.dockerjava.api.model.BuildResponseItem
import com.github.dockerjava.core.async.ResultCallbackTemplate
import com.github.dockerjava.core.command.BuildImageResultCallback
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigValueFactory
import net.corda.networkbuilder.docker.DockerUtils
import net.corda.common.configuration.parsing.internal.Configuration
import net.corda.common.validation.internal.Validated
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.config.parseAsNodeConfiguration
import org.slf4j.LoggerFactory
import java.io.File
import java.util.concurrent.CompletableFuture
/** Builds a Docker image. */
open class NodeBuilder {
companion object {
val LOG = LoggerFactory.getLogger(NodeBuilder::class.java)
}
fun buildNode(copiedNode: CopiedNode): CompletableFuture<BuiltNode> {
val future: CompletableFuture<BuiltNode> = CompletableFuture()
val localDockerClient = DockerUtils.createLocalDockerClient()
val copiedNodeConfig = copiedNode.copiedNodeConfig
val nodeDir = copiedNodeConfig.parentFile
if (!copiedNodeConfig.exists()) {
throw IllegalStateException("There is no nodeConfig for dir: $copiedNodeConfig")
}
val nodeConfig = ConfigFactory.parseFile(copiedNodeConfig)
LOG.info("starting to build docker image for: $nodeDir")
localDockerClient.buildImageCmd()
.withDockerfile(File(nodeDir, "Dockerfile"))
.withBaseDirectory(nodeDir).exec(object : ResultCallbackTemplate<BuildImageResultCallback, BuildResponseItem>() {
var result: BuildResponseItem? = null
override fun onNext(`object`: BuildResponseItem?) {
this.result = `object`
}
override fun onError(throwable: Throwable?) {
future.completeExceptionally(throwable)
}
override fun onComplete() {
super.onComplete()
LOG.info("finished building docker image for: $nodeDir with id: ${result?.imageId}")
if (result == null || (result?.id == null && result?.errorDetail != null)) {
future.completeExceptionally(IllegalStateException("Could not build image for: $nodeDir, reason: ${result?.errorDetail}"))
}
val config = nodeConfig.parseAsNodeConfigWithFallback(ConfigFactory.parseFile(copiedNode.configFile)).value()
future.complete(copiedNode.builtNode(config, result?.imageId!!))
}
})
return future
}
}
fun Config.parseAsNodeConfigWithFallback(preCopyConfig: Config): Validated<NodeConfiguration, Configuration.Validation.Error> {
val nodeConfig = this
.withValue("baseDirectory", ConfigValueFactory.fromAnyRef(""))
.withFallback(ConfigFactory.parseResources("reference.conf"))
.withFallback(preCopyConfig)
.resolve()
return nodeConfig.parseAsNodeConfiguration()
}

View File

@ -1,29 +1,32 @@
package net.corda.bootstrapper.nodes package net.corda.networkbuilder.nodes
import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigRenderOptions import com.typesafe.config.ConfigRenderOptions
import com.typesafe.config.ConfigValue import com.typesafe.config.ConfigValue
import net.corda.core.internal.div
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.File import java.io.File
import java.nio.file.Files
import java.nio.file.Path
open class NodeCopier(private val cacheDir: File) { open class NodeCopier(private val cacheDir: File) {
fun copyNode(foundNode: FoundNode): CopiedNode { fun copyNode(foundNode: FoundNode): CopiedNode {
val nodeCacheDir = File(cacheDir, foundNode.baseDirectory.name) val nodeCacheDir = File(cacheDir, foundNode.baseDirectory.name)
nodeCacheDir.deleteRecursively() nodeCacheDir.deleteRecursively()
LOG.info("copying: ${foundNode.baseDirectory} to $nodeCacheDir") LOG.info("copying: ${foundNode.baseDirectory} to $nodeCacheDir")
foundNode.baseDirectory.copyRecursively(nodeCacheDir, overwrite = true) foundNode.baseDirectory.copyRecursively(nodeCacheDir, overwrite = true)
//docker-java lib doesn't copy an empty folder, so if it's empty add a dummy file
ensureDirectoryIsNonEmpty(nodeCacheDir.toPath()/("cordapps"))
copyBootstrapperFiles(nodeCacheDir) copyBootstrapperFiles(nodeCacheDir)
val configInCacheDir = File(nodeCacheDir, "node.conf") val configInCacheDir = File(nodeCacheDir, "node.conf")
LOG.info("Applying precanned config " + configInCacheDir) LOG.info("Applying precanned config $configInCacheDir")
val rpcSettings = getDefaultRpcSettings() val rpcSettings = getDefaultRpcSettings()
val sshSettings = getDefaultSshSettings(); val sshSettings = getDefaultSshSettings()
mergeConfigs(configInCacheDir, rpcSettings, sshSettings) mergeConfigs(configInCacheDir, rpcSettings, sshSettings)
return CopiedNode(foundNode, configInCacheDir, nodeCacheDir) return CopiedNode(foundNode, configInCacheDir, nodeCacheDir)
} }
fun copyBootstrapperFiles(nodeCacheDir: File) { fun copyBootstrapperFiles(nodeCacheDir: File) {
this.javaClass.classLoader.getResourceAsStream("node-Dockerfile").use { nodeDockerFileInStream -> this.javaClass.classLoader.getResourceAsStream("node-Dockerfile").use { nodeDockerFileInStream ->
val nodeDockerFile = File(nodeCacheDir, "Dockerfile") val nodeDockerFile = File(nodeCacheDir, "Dockerfile")
@ -88,14 +91,21 @@ open class NodeCopier(private val cacheDir: File) {
} }
} }
/** Adds a dummy file if the directory is empty. Creates a directory if it doesn't exists. */
internal fun ensureDirectoryIsNonEmpty(path: Path, dummyFileName: String = "dummy.txt") {
if (!Files.exists(path)) {
Files.createDirectories(path)
}
if (Files.list(path).noneMatch { !Files.isDirectory(it) }) {
Files.createFile(path / dummyFileName)
}
}
internal enum class Mode { internal enum class Mode {
NOTARY, NODE NOTARY, NODE
} }
companion object { companion object {
val LOG = LoggerFactory.getLogger(NodeCopier::class.java) val LOG = LoggerFactory.getLogger(NodeCopier::class.java)
} }
} }

View File

@ -0,0 +1,38 @@
package net.corda.networkbuilder.nodes
import com.typesafe.config.Config
import com.typesafe.config.ConfigException
import com.typesafe.config.ConfigFactory
import net.corda.networkbuilder.Constants
import net.corda.core.utilities.contextLogger
import java.io.File
class NodeFinder(private val dirToSearch: File) {
fun findNodes(): List<FoundNode> = findNodes { config -> !isNotary(config) }
fun findNotaries(): List<FoundNode> = findNodes { config -> isNotary(config) }
private fun isNotary(config: Config) = config.hasPath("notary")
private fun findNodes(filter: (Config) -> Boolean): List<FoundNode> {
return dirToSearch.walkBottomUp().filter {
it.name == "node.conf" && !it.absolutePath.contains(Constants.BOOTSTRAPPER_DIR_NAME)
}.mapNotNull {
try {
ConfigFactory.parseFile(it) to it
} catch (e: ConfigException) {
null
}
}.filter {
filter(it.first)
}.map { (_, nodeConfigFile) ->
LOG.info("We've found a node with name: ${nodeConfigFile.parentFile.name}")
FoundNode(nodeConfigFile, nodeConfigFile.parentFile)
}.toList()
}
companion object {
val LOG = contextLogger()
}
}

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper.nodes package net.corda.networkbuilder.nodes
import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.NodeConfiguration
import java.io.File import java.io.File
@ -26,6 +26,4 @@ class NodeInstance(configFile: File,
nodeInstanceName, nodeInstanceName,
actualX500, actualX500,
expectedFqName expectedFqName
) { )
}

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper.nodes package net.corda.networkbuilder.nodes
import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.NodeConfiguration
import java.io.File import java.io.File
@ -17,8 +17,7 @@ open class NodeInstanceRequest(configFile: File, baseDirectory: File,
} }
fun toNodeInstance(reachableAddress: String, portMapping: Map<Int, Int>): NodeInstance { fun toNodeInstance(reachableAddress: String, portMapping: Map<Int, Int>): NodeInstance {
return NodeInstance(configFile, baseDirectory, copiedNodeConfig, copiedNodeDir, nodeConfig, localImageId, remoteImageName, nodeInstanceName, actualX500, expectedFqName, reachableAddress, portMapping) return NodeInstance(configFile, baseDirectory, copiedNodeConfig, copiedNodeDir, nodeConfig,
localImageId, remoteImageName, nodeInstanceName, actualX500, expectedFqName, reachableAddress, portMapping)
} }
} }

View File

@ -1,16 +1,15 @@
package net.corda.bootstrapper.nodes package net.corda.networkbuilder.nodes
import net.corda.bootstrapper.Constants import net.corda.networkbuilder.Constants
import net.corda.bootstrapper.containers.instance.InstanceInfo import net.corda.networkbuilder.containers.instance.InstanceInfo
import net.corda.bootstrapper.containers.instance.Instantiator import net.corda.networkbuilder.containers.instance.Instantiator
import net.corda.bootstrapper.context.Context import net.corda.networkbuilder.context.Context
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class NodeInstantiator(val instantiator: Instantiator, class NodeInstantiator(val instantiator: Instantiator,
val context: Context) { val context: Context) {
fun createInstanceRequests(pushedNode: PushedNode, nodeCount: Map<FoundNode, Int>): List<NodeInstanceRequest> { fun createInstanceRequests(pushedNode: PushedNode, nodeCount: Map<FoundNode, Int>): List<NodeInstanceRequest> {
val namedMap = nodeCount.map { it.key.name.toLowerCase() to it.value }.toMap() val namedMap = nodeCount.map { it.key.name.toLowerCase() to it.value }.toMap()
@ -30,7 +29,6 @@ class NodeInstantiator(val instantiator: Instantiator,
return createInstanceRequest(node, 0) return createInstanceRequest(node, 0)
} }
private fun buildX500(baseX500: CordaX500Name, i: Int): String { private fun buildX500(baseX500: CordaX500Name, i: Int): String {
if (i == 0) { if (i == 0) {
return baseX500.toString() return baseX500.toString()
@ -87,6 +85,4 @@ class NodeInstantiator(val instantiator: Instantiator,
fun expectedFqdn(newInstanceName: String): String { fun expectedFqdn(newInstanceName: String): String {
return instantiator.getExpectedFQDN(newInstanceName) return instantiator.getExpectedFQDN(newInstanceName)
} }
} }

View File

@ -1,13 +1,12 @@
package net.corda.bootstrapper.nodes package net.corda.networkbuilder.nodes
import net.corda.bootstrapper.containers.push.ContainerPusher import net.corda.networkbuilder.containers.push.ContainerPusher
import net.corda.bootstrapper.context.Context import net.corda.networkbuilder.context.Context
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class NodePusher(private val containerPusher: ContainerPusher, class NodePusher(private val containerPusher: ContainerPusher,
private val context: Context) { private val context: Context) {
fun pushNode(builtNode: BuiltNode): CompletableFuture<PushedNode> { fun pushNode(builtNode: BuiltNode): CompletableFuture<PushedNode> {
val localImageId = builtNode.localImageId val localImageId = builtNode.localImageId

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper.nodes package net.corda.networkbuilder.nodes
import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.NodeConfiguration
import java.io.File import java.io.File
@ -20,6 +20,4 @@ open class PushedNode(configFile: File, baseDirectory: File,
override fun toString(): String { override fun toString(): String {
return "PushedNode(remoteImageName='$remoteImageName') ${super.toString()}" return "PushedNode(remoteImageName='$remoteImageName') ${super.toString()}"
} }
} }

View File

@ -1,12 +1,11 @@
package net.corda.bootstrapper.notaries package net.corda.networkbuilder.notaries
import net.corda.bootstrapper.nodes.CopiedNode import net.corda.networkbuilder.nodes.CopiedNode
import java.io.File import java.io.File
class CopiedNotary(configFile: File, baseDirectory: File, class CopiedNotary(configFile: File, baseDirectory: File,
copiedNodeConfig: File, copiedNodeDir: File, val nodeInfoFile: File) : copiedNodeConfig: File, copiedNodeDir: File, val nodeInfoFile: File) :
CopiedNode(configFile, baseDirectory, copiedNodeConfig, copiedNodeDir) { CopiedNode(configFile, baseDirectory, copiedNodeConfig, copiedNodeDir)
}
fun CopiedNode.toNotary(nodeInfoFile: File): CopiedNotary { fun CopiedNode.toNotary(nodeInfoFile: File): CopiedNotary {

View File

@ -1,23 +1,26 @@
package net.corda.bootstrapper.notaries package net.corda.networkbuilder.notaries
import net.corda.bootstrapper.nodes.CopiedNode import net.corda.core.internal.div
import net.corda.bootstrapper.nodes.FoundNode import net.corda.networkbuilder.nodes.CopiedNode
import net.corda.bootstrapper.nodes.NodeCopier import net.corda.networkbuilder.nodes.FoundNode
import net.corda.networkbuilder.nodes.NodeCopier
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.File import java.io.File
class NotaryCopier(val cacheDir: File) : NodeCopier(cacheDir) { class NotaryCopier(private val cacheDir: File) : NodeCopier(cacheDir) {
fun copyNotary(foundNotary: FoundNode): CopiedNotary { fun copyNotary(foundNotary: FoundNode): CopiedNotary {
val nodeCacheDir = File(cacheDir, foundNotary.baseDirectory.name) val nodeCacheDir = File(cacheDir, foundNotary.baseDirectory.name)
nodeCacheDir.deleteRecursively() nodeCacheDir.deleteRecursively()
LOG.info("copying: ${foundNotary.baseDirectory} to $nodeCacheDir") LOG.info("copying: ${foundNotary.baseDirectory} to $nodeCacheDir")
foundNotary.baseDirectory.copyRecursively(nodeCacheDir, overwrite = true) foundNotary.baseDirectory.copyRecursively(nodeCacheDir, overwrite = true)
//docker-java lib doesn't copy an empty folder, so if it's empty add a dummy file
ensureDirectoryIsNonEmpty(nodeCacheDir.toPath()/("cordapps"))
copyNotaryBootstrapperFiles(nodeCacheDir) copyNotaryBootstrapperFiles(nodeCacheDir)
val configInCacheDir = File(nodeCacheDir, "node.conf") val configInCacheDir = File(nodeCacheDir, "node.conf")
LOG.info("Applying precanned config " + configInCacheDir) LOG.info("Applying precanned config $configInCacheDir")
val rpcSettings = getDefaultRpcSettings() val rpcSettings = getDefaultRpcSettings()
val sshSettings = getDefaultSshSettings(); val sshSettings = getDefaultSshSettings()
mergeConfigs(configInCacheDir, rpcSettings, sshSettings, Mode.NOTARY) mergeConfigs(configInCacheDir, rpcSettings, sshSettings, Mode.NOTARY)
val generatedNodeInfo = generateNodeInfo(nodeCacheDir) val generatedNodeInfo = generateNodeInfo(nodeCacheDir)
return CopiedNode(foundNotary, configInCacheDir, nodeCacheDir).toNotary(generatedNodeInfo) return CopiedNode(foundNotary, configInCacheDir, nodeCacheDir).toNotary(generatedNodeInfo)
@ -32,10 +35,9 @@ class NotaryCopier(val cacheDir: File) : NodeCopier(cacheDir) {
val exitCode = nodeInfoGeneratorProcess.waitFor() val exitCode = nodeInfoGeneratorProcess.waitFor()
if (exitCode != 0) { if (exitCode != 0) {
throw IllegalStateException("Failed to generate nodeInfo for notary: " + dirToGenerateFrom) throw IllegalStateException("Failed to generate nodeInfo for notary: $dirToGenerateFrom")
} }
val nodeInfoFile = dirToGenerateFrom.listFiles().filter { it.name.startsWith("nodeInfo") }.single() return dirToGenerateFrom.listFiles().single { it.name.startsWith("nodeInfo") }
return nodeInfoFile;
} }
private fun copyNotaryBootstrapperFiles(nodeCacheDir: File) { private fun copyNotaryBootstrapperFiles(nodeCacheDir: File) {
@ -64,6 +66,4 @@ class NotaryCopier(val cacheDir: File) : NodeCopier(cacheDir) {
companion object { companion object {
val LOG = LoggerFactory.getLogger(NotaryCopier::class.java) val LOG = LoggerFactory.getLogger(NotaryCopier::class.java)
} }
} }

View File

@ -1,4 +1,4 @@
package net.corda.bootstrapper.serialization package net.corda.networkbuilder.serialization
import net.corda.core.serialization.internal.SerializationEnvironment import net.corda.core.serialization.internal.SerializationEnvironment
import net.corda.core.serialization.internal.nodeSerializationEnv import net.corda.core.serialization.internal.nodeSerializationEnv
@ -22,7 +22,6 @@ class SerializationEngine {
p2pContext = AMQP_P2P_CONTEXT.withClassLoader(classloader), p2pContext = AMQP_P2P_CONTEXT.withClassLoader(classloader),
rpcServerContext = AMQP_P2P_CONTEXT.withClassLoader(classloader), rpcServerContext = AMQP_P2P_CONTEXT.withClassLoader(classloader),
storageContext = AMQP_STORAGE_CONTEXT.withClassLoader(classloader), storageContext = AMQP_STORAGE_CONTEXT.withClassLoader(classloader),
checkpointContext = KRYO_CHECKPOINT_CONTEXT.withClassLoader(classloader), checkpointContext = KRYO_CHECKPOINT_CONTEXT.withClassLoader(classloader),
checkpointSerializer = KryoCheckpointSerializer checkpointSerializer = KryoCheckpointSerializer
) )

View File

@ -1,9 +1,9 @@
package net.corda.bootstrapper.volumes package net.corda.networkbuilder.volumes
import com.microsoft.azure.storage.file.CloudFile import com.microsoft.azure.storage.file.CloudFile
import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigFactory
import net.corda.bootstrapper.notaries.CopiedNotary import net.corda.networkbuilder.notaries.CopiedNotary
import net.corda.bootstrapper.serialization.SerializationEngine import net.corda.networkbuilder.serialization.SerializationEngine
import net.corda.core.node.NetworkParameters import net.corda.core.node.NetworkParameters
import net.corda.core.node.NotaryInfo import net.corda.core.node.NotaryInfo
import net.corda.core.serialization.deserialize import net.corda.core.serialization.deserialize
@ -26,7 +26,6 @@ interface Volume {
internal val networkMapCa = createDevNetworkMapCa(DEV_ROOT_CA) internal val networkMapCa = createDevNetworkMapCa(DEV_ROOT_CA)
internal val networkMapCert: X509Certificate = networkMapCa.certificate internal val networkMapCert: X509Certificate = networkMapCa.certificate
internal val keyPair = networkMapCa.keyPair internal val keyPair = networkMapCa.keyPair
} }
@ -34,7 +33,6 @@ interface Volume {
this.uploadFromByteArray(array, 0, array.size) this.uploadFromByteArray(array, 0, array.size)
} }
fun convertNodeIntoToNetworkParams(notaryFiles: List<Pair<File, File>>): NetworkParameters { fun convertNodeIntoToNetworkParams(notaryFiles: List<Pair<File, File>>): NetworkParameters {
val notaryInfos = notaryFiles.map { (configFile, nodeInfoFile) -> val notaryInfos = notaryFiles.map { (configFile, nodeInfoFile) ->
val validating = ConfigFactory.parseFile(configFile).getConfig("notary").getBooleanCaseInsensitive("validating") val validating = ConfigFactory.parseFile(configFile).getConfig("notary").getBooleanCaseInsensitive("validating")
@ -52,6 +50,4 @@ interface Volume {
whitelistedContractImplementations = emptyMap()) whitelistedContractImplementations = emptyMap())
} }
} }
} }

View File

@ -1,14 +1,14 @@
package net.corda.bootstrapper.volumes.azure package net.corda.networkbuilder.volumes.azure
import com.microsoft.azure.management.Azure import com.microsoft.azure.management.Azure
import com.microsoft.azure.management.resources.ResourceGroup import com.microsoft.azure.management.resources.ResourceGroup
import com.microsoft.azure.management.storage.StorageAccount import com.microsoft.azure.management.storage.StorageAccount
import com.microsoft.azure.storage.CloudStorageAccount import com.microsoft.azure.storage.CloudStorageAccount
import net.corda.bootstrapper.Constants.Companion.restFriendlyName import net.corda.networkbuilder.Constants.Companion.restFriendlyName
import net.corda.bootstrapper.notaries.CopiedNotary import net.corda.networkbuilder.notaries.CopiedNotary
import net.corda.bootstrapper.volumes.Volume import net.corda.networkbuilder.volumes.Volume
import net.corda.bootstrapper.volumes.Volume.Companion.keyPair import net.corda.networkbuilder.volumes.Volume.Companion.keyPair
import net.corda.bootstrapper.volumes.Volume.Companion.networkMapCert import net.corda.networkbuilder.volumes.Volume.Companion.networkMapCert
import net.corda.core.internal.signWithCert import net.corda.core.internal.signWithCert
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
@ -38,7 +38,6 @@ class AzureSmbVolume(private val azure: Azure, private val resourceGroup: Resour
val storageAccountKey: String val storageAccountKey: String
get() = accKeys.value() get() = accKeys.value()
init { init {
while (true) { while (true) {
try { try {
@ -64,18 +63,12 @@ class AzureSmbVolume(private val azure: Azure, private val resourceGroup: Resour
override fun notariesForNetworkParams(notaries: List<CopiedNotary>) { override fun notariesForNetworkParams(notaries: List<CopiedNotary>) {
val networkParamsFile = networkParamsFolder.getFileReference(NETWORK_PARAMS_FILE_NAME) val networkParamsFile = networkParamsFolder.getFileReference(NETWORK_PARAMS_FILE_NAME)
networkParamsFile.deleteIfExists() networkParamsFile.deleteIfExists()
LOG.info("Storing network-params in AzureFile location: " + networkParamsFile.uri) LOG.info("Storing network-params in AzureFile location: ${networkParamsFile.uri}")
val networkParameters = convertNodeIntoToNetworkParams(notaries.map { it.configFile to it.nodeInfoFile }) val networkParameters = convertNodeIntoToNetworkParams(notaries.map { it.configFile to it.nodeInfoFile })
networkParamsFile.uploadFromByteArray(networkParameters.signWithCert(keyPair.private, networkMapCert).serialize().bytes) networkParamsFile.uploadFromByteArray(networkParameters.signWithCert(keyPair.private, networkMapCert).serialize().bytes)
} }
companion object { companion object {
val LOG = LoggerFactory.getLogger(AzureSmbVolume::class.java) val LOG = LoggerFactory.getLogger(AzureSmbVolume::class.java)
} }
} }

View File

@ -1,8 +1,8 @@
package net.corda.bootstrapper.volumes.docker package net.corda.networkbuilder.volumes.docker
import net.corda.bootstrapper.context.Context import net.corda.networkbuilder.context.Context
import net.corda.bootstrapper.notaries.CopiedNotary import net.corda.networkbuilder.notaries.CopiedNotary
import net.corda.bootstrapper.volumes.Volume import net.corda.networkbuilder.volumes.Volume
import net.corda.core.internal.signWithCert import net.corda.core.internal.signWithCert
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
@ -24,7 +24,6 @@ class LocalVolume(scratchDir: File, context: Context) : Volume {
LOG.info("wrote network params to local file: ${networkParamsFile.absolutePath}") LOG.info("wrote network params to local file: ${networkParamsFile.absolutePath}")
} }
fun getPath(): String { fun getPath(): String {
return volumeDir.absolutePath return volumeDir.absolutePath
} }

View File

@ -0,0 +1,21 @@
FROM corda/corda-zulu-4.0
# Copy corda files
ADD --chown=corda:corda node.conf /opt/corda/node.conf
ADD --chown=corda:corda cordapps/ /opt/corda/cordapps
# Copy node info watcher script
ADD --chown=corda:corda node_info_watcher.sh /opt/corda/
COPY --chown=corda:corda run-corda.sh /opt/corda/bin/run-corda
RUN chmod +x /opt/corda/bin/run-corda && \
chmod +x /opt/corda/node_info_watcher.sh && \
sync
# Working directory for Corda
WORKDIR /opt/corda
ENV HOME=/opt/corda
# Start it
CMD ["run-corda"]

View File

@ -0,0 +1,22 @@
FROM corda/corda-zulu-4.0
# Copy corda files
ADD --chown=corda:corda node.conf /opt/corda/node.conf
ADD --chown=corda:corda cordapps/ /opt/corda/cordapps
ADD --chown=corda:corda certificates/ /opt/corda/certificates
# Copy node info watcher script
ADD --chown=corda:corda node_info_watcher.sh /opt/corda/
COPY --chown=corda:corda run-corda.sh /opt/corda/bin/run-corda
RUN chmod +x /opt/corda/bin/run-corda && \
chmod +x /opt/corda/node_info_watcher.sh && \
sync
# Working directory for Corda
WORKDIR /opt/corda
ENV HOME=/opt/corda
# Start it
CMD ["run-corda"]

View File

@ -18,7 +18,7 @@ bash node_info_watcher.sh &
cd ${CORDA_HOME} cd ${CORDA_HOME}
if java ${JAVA_OPTIONS} -jar ${CORDA_HOME}/corda.jar 2>&1 ; then if java ${JAVA_OPTIONS} -jar ${CORDA_HOME}/bin/corda.jar 2>&1 ; then
echo "Corda exited with zero exit code" echo "Corda exited with zero exit code"
else else
echo "Corda exited with nonzero exit code, sleeping to allow log collection" echo "Corda exited with nonzero exit code, sleeping to allow log collection"

View File

@ -14,7 +14,7 @@ bash node_info_watcher.sh &
cd ${CORDA_HOME} cd ${CORDA_HOME}
if java ${JAVA_OPTIONS} -jar ${CORDA_HOME}/corda.jar 2>&1 ; then if java ${JAVA_OPTIONS} -jar ${CORDA_HOME}/bin/corda.jar 2>&1 ; then
echo "Corda exited with zero exit code" echo "Corda exited with zero exit code"
else else
echo "Corda exited with nonzero exit code, sleeping to allow log collection" echo "Corda exited with nonzero exit code, sleeping to allow log collection"

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB