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:
James Brown 2018-06-13 16:23:39 +01:00 committed by GitHub
parent 636f0d8c92
commit 026a4864b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 11 deletions

View File

@ -7,6 +7,11 @@ release, see :doc:`upgrade-notes`.
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.
* 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
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 "{}".
* ``WireTransaction.Companion.createComponentGroups`` has been marked as ``@CordaInternal``. It was never intended to be

View File

@ -59,11 +59,10 @@ Node can be configured to run SSH server. See :doc:`shell` for details.
Database access
---------------
The node exposes its internal database over a socket which can be browsed using any tool that can use JDBC drivers.
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 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
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.
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
--------------------

View File

@ -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
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
navigate in a terminal window to the unzipped folder
* 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
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
----------
Nodes also have untested support for PostgreSQL 9.6, using PostgreSQL JDBC Driver 42.1.4.

View File

@ -336,15 +336,19 @@ open class Node(configuration: NodeConfiguration,
wellKnownPartyFromAnonymous: (AbstractParty) -> Party?): CordaPersistence {
val databaseUrl = configuration.dataSourceProperties.getProperty("dataSource.url")
val h2Prefix = "jdbc:h2:file:"
if (databaseUrl != null && databaseUrl.startsWith(h2Prefix)) {
val h2Port = databaseUrl.substringAfter(";AUTO_SERVER_PORT=", "").substringBefore(';')
if (h2Port.isNotBlank()) {
val effectiveH2Settings = configuration.effectiveH2Settings
if(effectiveH2Settings != null && effectiveH2Settings.address != null) {
val databaseName = databaseUrl.removePrefix(h2Prefix).substringBefore(';')
val server = org.h2.tools.Server.createTcpServer(
"-tcpPort", h2Port,
"-tcpPort", effectiveH2Settings.address.port.toString(),
"-tcpAllowOthers",
"-tcpDaemon",
"-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
val url = server.start().url
printBasicNodeInfo("Database connection url is", "jdbc:h2:$url/node")

View File

@ -61,7 +61,7 @@ interface NodeConfiguration : NodeSSLConfiguration {
val extraNetworkMapKeys: List<UUID>
val tlsCertCrlDistPoint: URL?
val tlsCertCrlIssuer: String?
val effectiveH2Settings: NodeH2Settings?
fun validate(): List<String>
companion object {
@ -190,12 +190,14 @@ data class NodeConfigurationImpl(
override val attachmentCacheBound: Long = NodeConfiguration.defaultAttachmentCacheBound,
override val extraNetworkMapKeys: List<UUID> = emptyList(),
// 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)
private val jarDirs: List<String> = emptyList()
) : NodeConfiguration {
companion object {
private val logger = loggerFor<NodeConfigurationImpl>()
}
override val rpcOptions: NodeRpcOptions = initialiseRpcOptions(rpcAddress, rpcSettings, BrokerRpcSslOptions(baseDirectory / "certificates" / "nodekeystore.jks", keyStorePassword))
@ -215,6 +217,7 @@ data class NodeConfigurationImpl(
}.asOptions(fallbackSslOptions)
}
private fun validateTlsCertCrlConfig(): List<String> {
val errors = mutableListOf<String>()
if (tlsCertCrlIssuer != null) {
@ -239,6 +242,15 @@ data class NodeConfigurationImpl(
errors += validateRpcOptions(rpcOptions)
errors += validateTlsCertCrlConfig()
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
}
@ -286,6 +298,11 @@ data class NodeConfigurationImpl(
override val attachmentContentCacheSizeBytes: Long
get() = attachmentContentCacheSizeMegaBytes?.MB ?: super.attachmentContentCacheSizeBytes
override val effectiveH2Settings: NodeH2Settings?
get() = when {
h2port != null -> NodeH2Settings(address = NetworkHostAndPort(host="localhost", port=h2port))
else -> h2Settings
}
init {
// This is a sanity feature do not remove.
@ -303,9 +320,12 @@ data class NodeConfigurationImpl(
if (compatibilityZoneURL != null && networkServices == null) {
networkServices = NetworkServicesConfig(compatibilityZoneURL, compatibilityZoneURL, true)
}
require(h2port == null || h2Settings == null) { "Cannot specify both 'h2port' and 'h2Settings' in configuration" }
}
}
data class NodeRpcSettings(
val address: NetworkHostAndPort?,
val adminAddress: NetworkHostAndPort?,
@ -328,6 +348,10 @@ data class NodeRpcSettings(
}
}
data class NodeH2Settings(
val address: NetworkHostAndPort?
)
enum class VerifierType {
InMemory,
OutOfProcess

View File

@ -5,7 +5,7 @@ crlCheckSoftFail = true
lazyBridgeStart = true
dataSourceProperties = {
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.password = ""
}
@ -13,7 +13,7 @@ database = {
transactionIsolationLevel = "REPEATABLE_READ"
exportHibernateJMXStatistics = "false"
}
h2port = 0
useTestClock = false
verifierType = InMemory
rpcSettings = {

View File

@ -45,7 +45,6 @@ class NodeConfigTest {
assertEquals(localPort(40002), fullConfig.rpcOptions.address)
assertEquals(localPort(10001), fullConfig.p2pAddress)
assertEquals(listOf(user("jenny")), fullConfig.rpcUsers)
assertThat(fullConfig.dataSourceProperties["dataSource.url"] as String).contains("AUTO_SERVER_PORT=30001")
assertTrue(fullConfig.useTestClock)
assertFalse(fullConfig.detectPublicIp)
}