mirror of
https://github.com/corda/corda.git
synced 2025-06-18 15:18:16 +00:00
ENT-1387 h2port config changes with new h2Settings block
* Introduce new h2Settings config block which overrides h2Port * H2 server listens on localhost by default * Change is backward compatible and old h2Port option can still be used but that always listens on localhost now * Update changelog and docs with H2 changes
This commit is contained in:
@ -7,6 +7,11 @@ release, see :doc:`upgrade-notes`.
|
|||||||
Unreleased
|
Unreleased
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
* H2 database changes:
|
||||||
|
* The node's H2 database now listens on ``localhost`` by default.
|
||||||
|
* The database server address must also be enabled in the node configuration.
|
||||||
|
* A new ``h2Settings`` configuration block supercedes the ``h2Port`` option.
|
||||||
|
|
||||||
* Improved documentation PDF quality. Building the documentation now requires ``LaTex`` to be installed on the OS.
|
* Improved documentation PDF quality. Building the documentation now requires ``LaTex`` to be installed on the OS.
|
||||||
|
|
||||||
* Add ``devModeOptions.allowCompatibilityZone`` to re-enable the use of a compatibility zone and ``devMode``
|
* Add ``devModeOptions.allowCompatibilityZone`` to re-enable the use of a compatibility zone and ``devMode``
|
||||||
@ -47,6 +52,8 @@ Unreleased
|
|||||||
* The node's configuration is only printed on startup if ``devMode`` is ``true``, avoiding the risk of printing passwords
|
* The node's configuration is only printed on startup if ``devMode`` is ``true``, avoiding the risk of printing passwords
|
||||||
in a production setup.
|
in a production setup.
|
||||||
|
|
||||||
|
* ``NodeStartup`` will now only print node's configuration if ``devMode`` is ``true``, avoiding the risk of printing passwords in a production setup.
|
||||||
|
|
||||||
* SLF4J's MDC will now only be printed to the console if not empty. No more log lines ending with "{}".
|
* SLF4J's MDC will now only be printed to the console if not empty. No more log lines ending with "{}".
|
||||||
|
|
||||||
* ``WireTransaction.Companion.createComponentGroups`` has been marked as ``@CordaInternal``. It was never intended to be
|
* ``WireTransaction.Companion.createComponentGroups`` has been marked as ``@CordaInternal``. It was never intended to be
|
||||||
|
@ -59,11 +59,10 @@ Node can be configured to run SSH server. See :doc:`shell` for details.
|
|||||||
|
|
||||||
Database access
|
Database access
|
||||||
---------------
|
---------------
|
||||||
|
The node can be configured to expose its internal database over socket which can be browsed using any tool that can use JDBC drivers.
|
||||||
The node exposes its internal database over a socket which can be browsed using any tool that can use JDBC drivers.
|
|
||||||
The JDBC URL is printed during node startup to the log and will typically look like this:
|
The JDBC URL is printed during node startup to the log and will typically look like this:
|
||||||
|
|
||||||
``jdbc:h2:tcp://192.168.0.31:31339/node``
|
``jdbc:h2:tcp://localhost:31339/node``
|
||||||
|
|
||||||
The username and password can be altered in the :doc:`corda-configuration-file` but default to username "sa" and a blank
|
The username and password can be altered in the :doc:`corda-configuration-file` but default to username "sa" and a blank
|
||||||
password.
|
password.
|
||||||
@ -72,6 +71,19 @@ Any database browsing tool that supports JDBC can be used, but if you have Intel
|
|||||||
a tool integrated with your IDE. Just open the database window and add an H2 data source with the above details.
|
a tool integrated with your IDE. Just open the database window and add an H2 data source with the above details.
|
||||||
You will now be able to browse the tables and row data within them.
|
You will now be able to browse the tables and row data within them.
|
||||||
|
|
||||||
|
By default the node will expose its database on the localhost network interface. This behaviour can be
|
||||||
|
overridden by specifying the full network address (interface and port), using the new h2Settings
|
||||||
|
syntax in the node configuration:
|
||||||
|
|
||||||
|
.. sourcecode:: groovy
|
||||||
|
h2Settings {
|
||||||
|
address: "localhost:12345"
|
||||||
|
}
|
||||||
|
|
||||||
|
The configuration above will restrict the H2 service to run on localhost. If remote access is required, the address
|
||||||
|
can be changed to 0.0.0.0. However it is recommended to change the default username and password
|
||||||
|
before doing so.
|
||||||
|
|
||||||
Monitoring your node
|
Monitoring your node
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
@ -6,6 +6,13 @@ Default in-memory database
|
|||||||
By default, nodes store their data in an H2 database. You can connect directly to a running node's database to see its
|
By default, nodes store their data in an H2 database. You can connect directly to a running node's database to see its
|
||||||
stored states, transactions and attachments as follows:
|
stored states, transactions and attachments as follows:
|
||||||
|
|
||||||
|
* Enable the H2 database access in the node configuration using the following syntax:
|
||||||
|
|
||||||
|
.. sourcecode:: groovy
|
||||||
|
h2Settings {
|
||||||
|
address: "localhost:0"
|
||||||
|
}
|
||||||
|
|
||||||
* Download the **last stable** `h2 platform-independent zip <http://www.h2database.com/html/download.html>`_, unzip the zip, and
|
* Download the **last stable** `h2 platform-independent zip <http://www.h2database.com/html/download.html>`_, unzip the zip, and
|
||||||
navigate in a terminal window to the unzipped folder
|
navigate in a terminal window to the unzipped folder
|
||||||
* Change directories to the bin folder: ``cd h2/bin``
|
* Change directories to the bin folder: ``cd h2/bin``
|
||||||
@ -25,6 +32,10 @@ stored states, transactions and attachments as follows:
|
|||||||
You will be presented with a web interface that shows the contents of your node's storage and vault, and provides an
|
You will be presented with a web interface that shows the contents of your node's storage and vault, and provides an
|
||||||
interface for you to query them using SQL.
|
interface for you to query them using SQL.
|
||||||
|
|
||||||
|
The default behaviour is to expose the H2 database on localhost. This can be overridden in the
|
||||||
|
node configuration using ``h2Settings.address`` and specifying the address of the network interface to listen on,
|
||||||
|
or simply using ``0.0.0.0:0`` to listen on all interfaces.
|
||||||
|
|
||||||
PostgreSQL
|
PostgreSQL
|
||||||
----------
|
----------
|
||||||
Nodes also have untested support for PostgreSQL 9.6, using PostgreSQL JDBC Driver 42.1.4.
|
Nodes also have untested support for PostgreSQL 9.6, using PostgreSQL JDBC Driver 42.1.4.
|
||||||
|
@ -336,15 +336,19 @@ open class Node(configuration: NodeConfiguration,
|
|||||||
wellKnownPartyFromAnonymous: (AbstractParty) -> Party?): CordaPersistence {
|
wellKnownPartyFromAnonymous: (AbstractParty) -> Party?): CordaPersistence {
|
||||||
val databaseUrl = configuration.dataSourceProperties.getProperty("dataSource.url")
|
val databaseUrl = configuration.dataSourceProperties.getProperty("dataSource.url")
|
||||||
val h2Prefix = "jdbc:h2:file:"
|
val h2Prefix = "jdbc:h2:file:"
|
||||||
|
|
||||||
if (databaseUrl != null && databaseUrl.startsWith(h2Prefix)) {
|
if (databaseUrl != null && databaseUrl.startsWith(h2Prefix)) {
|
||||||
val h2Port = databaseUrl.substringAfter(";AUTO_SERVER_PORT=", "").substringBefore(';')
|
val effectiveH2Settings = configuration.effectiveH2Settings
|
||||||
if (h2Port.isNotBlank()) {
|
|
||||||
|
if(effectiveH2Settings != null && effectiveH2Settings.address != null) {
|
||||||
val databaseName = databaseUrl.removePrefix(h2Prefix).substringBefore(';')
|
val databaseName = databaseUrl.removePrefix(h2Prefix).substringBefore(';')
|
||||||
val server = org.h2.tools.Server.createTcpServer(
|
val server = org.h2.tools.Server.createTcpServer(
|
||||||
"-tcpPort", h2Port,
|
"-tcpPort", effectiveH2Settings.address.port.toString(),
|
||||||
"-tcpAllowOthers",
|
"-tcpAllowOthers",
|
||||||
"-tcpDaemon",
|
"-tcpDaemon",
|
||||||
"-key", "node", databaseName)
|
"-key", "node", databaseName)
|
||||||
|
// override interface that createTcpServer listens on (which is always 0.0.0.0)
|
||||||
|
System.setProperty("h2.bindAddress", effectiveH2Settings.address.host)
|
||||||
runOnStop += server::stop
|
runOnStop += server::stop
|
||||||
val url = server.start().url
|
val url = server.start().url
|
||||||
printBasicNodeInfo("Database connection url is", "jdbc:h2:$url/node")
|
printBasicNodeInfo("Database connection url is", "jdbc:h2:$url/node")
|
||||||
|
@ -61,7 +61,7 @@ interface NodeConfiguration : NodeSSLConfiguration {
|
|||||||
val extraNetworkMapKeys: List<UUID>
|
val extraNetworkMapKeys: List<UUID>
|
||||||
val tlsCertCrlDistPoint: URL?
|
val tlsCertCrlDistPoint: URL?
|
||||||
val tlsCertCrlIssuer: String?
|
val tlsCertCrlIssuer: String?
|
||||||
|
val effectiveH2Settings: NodeH2Settings?
|
||||||
fun validate(): List<String>
|
fun validate(): List<String>
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -190,12 +190,14 @@ data class NodeConfigurationImpl(
|
|||||||
override val attachmentCacheBound: Long = NodeConfiguration.defaultAttachmentCacheBound,
|
override val attachmentCacheBound: Long = NodeConfiguration.defaultAttachmentCacheBound,
|
||||||
override val extraNetworkMapKeys: List<UUID> = emptyList(),
|
override val extraNetworkMapKeys: List<UUID> = emptyList(),
|
||||||
// do not use or remove (breaks DemoBench together with rejection of unknown configuration keys during parsing)
|
// do not use or remove (breaks DemoBench together with rejection of unknown configuration keys during parsing)
|
||||||
private val h2port: Int = 0,
|
private val h2port: Int? = null,
|
||||||
|
private val h2Settings: NodeH2Settings? = null,
|
||||||
// do not use or remove (used by Capsule)
|
// do not use or remove (used by Capsule)
|
||||||
private val jarDirs: List<String> = emptyList()
|
private val jarDirs: List<String> = emptyList()
|
||||||
) : NodeConfiguration {
|
) : NodeConfiguration {
|
||||||
companion object {
|
companion object {
|
||||||
private val logger = loggerFor<NodeConfigurationImpl>()
|
private val logger = loggerFor<NodeConfigurationImpl>()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val rpcOptions: NodeRpcOptions = initialiseRpcOptions(rpcAddress, rpcSettings, BrokerRpcSslOptions(baseDirectory / "certificates" / "nodekeystore.jks", keyStorePassword))
|
override val rpcOptions: NodeRpcOptions = initialiseRpcOptions(rpcAddress, rpcSettings, BrokerRpcSslOptions(baseDirectory / "certificates" / "nodekeystore.jks", keyStorePassword))
|
||||||
@ -215,6 +217,7 @@ data class NodeConfigurationImpl(
|
|||||||
}.asOptions(fallbackSslOptions)
|
}.asOptions(fallbackSslOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun validateTlsCertCrlConfig(): List<String> {
|
private fun validateTlsCertCrlConfig(): List<String> {
|
||||||
val errors = mutableListOf<String>()
|
val errors = mutableListOf<String>()
|
||||||
if (tlsCertCrlIssuer != null) {
|
if (tlsCertCrlIssuer != null) {
|
||||||
@ -239,6 +242,15 @@ data class NodeConfigurationImpl(
|
|||||||
errors += validateRpcOptions(rpcOptions)
|
errors += validateRpcOptions(rpcOptions)
|
||||||
errors += validateTlsCertCrlConfig()
|
errors += validateTlsCertCrlConfig()
|
||||||
errors += validateNetworkServices()
|
errors += validateNetworkServices()
|
||||||
|
errors += validateH2Settings()
|
||||||
|
return errors
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validateH2Settings(): List<String> {
|
||||||
|
val errors = mutableListOf<String>()
|
||||||
|
if (h2port != null && h2Settings != null) {
|
||||||
|
errors += "Cannot specify both 'h2port' and 'h2Settings' in configuration"
|
||||||
|
}
|
||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,6 +298,11 @@ data class NodeConfigurationImpl(
|
|||||||
override val attachmentContentCacheSizeBytes: Long
|
override val attachmentContentCacheSizeBytes: Long
|
||||||
get() = attachmentContentCacheSizeMegaBytes?.MB ?: super.attachmentContentCacheSizeBytes
|
get() = attachmentContentCacheSizeMegaBytes?.MB ?: super.attachmentContentCacheSizeBytes
|
||||||
|
|
||||||
|
override val effectiveH2Settings: NodeH2Settings?
|
||||||
|
get() = when {
|
||||||
|
h2port != null -> NodeH2Settings(address = NetworkHostAndPort(host="localhost", port=h2port))
|
||||||
|
else -> h2Settings
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// This is a sanity feature do not remove.
|
// This is a sanity feature do not remove.
|
||||||
@ -303,9 +320,12 @@ data class NodeConfigurationImpl(
|
|||||||
if (compatibilityZoneURL != null && networkServices == null) {
|
if (compatibilityZoneURL != null && networkServices == null) {
|
||||||
networkServices = NetworkServicesConfig(compatibilityZoneURL, compatibilityZoneURL, true)
|
networkServices = NetworkServicesConfig(compatibilityZoneURL, compatibilityZoneURL, true)
|
||||||
}
|
}
|
||||||
|
require(h2port == null || h2Settings == null) { "Cannot specify both 'h2port' and 'h2Settings' in configuration" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
data class NodeRpcSettings(
|
data class NodeRpcSettings(
|
||||||
val address: NetworkHostAndPort?,
|
val address: NetworkHostAndPort?,
|
||||||
val adminAddress: NetworkHostAndPort?,
|
val adminAddress: NetworkHostAndPort?,
|
||||||
@ -328,6 +348,10 @@ data class NodeRpcSettings(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class NodeH2Settings(
|
||||||
|
val address: NetworkHostAndPort?
|
||||||
|
)
|
||||||
|
|
||||||
enum class VerifierType {
|
enum class VerifierType {
|
||||||
InMemory,
|
InMemory,
|
||||||
OutOfProcess
|
OutOfProcess
|
||||||
|
@ -5,7 +5,7 @@ crlCheckSoftFail = true
|
|||||||
lazyBridgeStart = true
|
lazyBridgeStart = true
|
||||||
dataSourceProperties = {
|
dataSourceProperties = {
|
||||||
dataSourceClassName = org.h2.jdbcx.JdbcDataSource
|
dataSourceClassName = org.h2.jdbcx.JdbcDataSource
|
||||||
dataSource.url = "jdbc:h2:file:"${baseDirectory}"/persistence;DB_CLOSE_ON_EXIT=FALSE;WRITE_DELAY=0;LOCK_TIMEOUT=10000;AUTO_SERVER_PORT="${h2port}
|
dataSource.url = "jdbc:h2:file:"${baseDirectory}"/persistence;DB_CLOSE_ON_EXIT=FALSE;WRITE_DELAY=0;LOCK_TIMEOUT=10000"
|
||||||
dataSource.user = sa
|
dataSource.user = sa
|
||||||
dataSource.password = ""
|
dataSource.password = ""
|
||||||
}
|
}
|
||||||
@ -13,7 +13,7 @@ database = {
|
|||||||
transactionIsolationLevel = "REPEATABLE_READ"
|
transactionIsolationLevel = "REPEATABLE_READ"
|
||||||
exportHibernateJMXStatistics = "false"
|
exportHibernateJMXStatistics = "false"
|
||||||
}
|
}
|
||||||
h2port = 0
|
|
||||||
useTestClock = false
|
useTestClock = false
|
||||||
verifierType = InMemory
|
verifierType = InMemory
|
||||||
rpcSettings = {
|
rpcSettings = {
|
||||||
|
@ -45,7 +45,6 @@ class NodeConfigTest {
|
|||||||
assertEquals(localPort(40002), fullConfig.rpcOptions.address)
|
assertEquals(localPort(40002), fullConfig.rpcOptions.address)
|
||||||
assertEquals(localPort(10001), fullConfig.p2pAddress)
|
assertEquals(localPort(10001), fullConfig.p2pAddress)
|
||||||
assertEquals(listOf(user("jenny")), fullConfig.rpcUsers)
|
assertEquals(listOf(user("jenny")), fullConfig.rpcUsers)
|
||||||
assertThat(fullConfig.dataSourceProperties["dataSource.url"] as String).contains("AUTO_SERVER_PORT=30001")
|
|
||||||
assertTrue(fullConfig.useTestClock)
|
assertTrue(fullConfig.useTestClock)
|
||||||
assertFalse(fullConfig.detectPublicIp)
|
assertFalse(fullConfig.detectPublicIp)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user