diff --git a/node/src/main/kotlin/net/corda/node/ArgsParser.kt b/node/src/main/kotlin/net/corda/node/ArgsParser.kt index 8353dd7f1a..f42a922564 100644 --- a/node/src/main/kotlin/net/corda/node/ArgsParser.kt +++ b/node/src/main/kotlin/net/corda/node/ArgsParser.kt @@ -1,5 +1,6 @@ package net.corda.node +import com.typesafe.config.ConfigFactory import joptsimple.OptionParser import joptsimple.util.EnumConverter import net.corda.core.internal.div @@ -93,7 +94,9 @@ data class CmdLineOptions(val baseDirectory: Path, val justGenerateNodeInfo: Boolean, val bootstrapRaftCluster: Boolean) { fun loadConfig(): NodeConfiguration { - val config = ConfigHelper.loadConfig(baseDirectory, configFile).parseAsNodeConfiguration() + val config = ConfigHelper.loadConfig(baseDirectory, configFile, configOverrides = ConfigFactory.parseMap( + mapOf("noLocalShell" to this.noLocalShell) + )).parseAsNodeConfiguration() if (isRegistration) { requireNotNull(config.compatibilityZoneURL) { "Compatibility Zone Url must be provided in registration mode." } requireNotNull(networkRootTruststorePath) { "Network root trust store path must be provided in registration mode." } diff --git a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt index 42355c78f4..30e484471f 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -36,10 +36,7 @@ import net.corda.node.services.ContractUpgradeHandler import net.corda.node.services.FinalityHandler import net.corda.node.services.NotaryChangeHandler import net.corda.node.services.api.* -import net.corda.node.services.config.BFTSMaRtConfiguration -import net.corda.node.services.config.NodeConfiguration -import net.corda.node.services.config.NotaryConfig -import net.corda.node.services.config.configureWithDevSSLCertificate +import net.corda.node.services.config.* import net.corda.node.services.events.NodeSchedulerService import net.corda.node.services.events.ScheduledActivityObserver import net.corda.node.services.identity.PersistentIdentityService @@ -278,7 +275,9 @@ abstract class AbstractNode(val configuration: NodeConfiguration, protected abstract fun getRxIoScheduler(): Scheduler open fun startShell(rpcOps: CordaRPCOps) { - InteractiveShell.startShell(configuration, rpcOps, securityManager, _services.identityService, _services.database) + if (configuration.shouldInitCrashShell()) { + InteractiveShell.startShell(configuration, rpcOps, securityManager, _services.identityService, _services.database) + } } private fun initNodeInfo(networkMapCache: NetworkMapCacheBaseInternal, diff --git a/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt b/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt index fa3ea52d3a..c19516aafb 100644 --- a/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt +++ b/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt @@ -11,6 +11,7 @@ import net.corda.core.utilities.loggerFor import net.corda.node.* import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.NodeConfigurationImpl +import net.corda.node.services.config.shouldStartLocalShell import net.corda.node.services.transactions.bftSMaRtSerialFilter import net.corda.node.shell.InteractiveShell import net.corda.node.utilities.registration.HTTPNetworkRegistrationService @@ -140,7 +141,7 @@ open class NodeStartup(val args: Array) { Node.printBasicNodeInfo("Node for \"$name\" started up and registered in $elapsed sec") // Don't start the shell if there's no console attached. - if (!cmdlineOptions.noLocalShell && System.console() != null && conf.devMode) { + if (conf.shouldStartLocalShell()) { startedNode.internals.startupComplete.then { try { InteractiveShell.runLocalShell(startedNode) diff --git a/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt b/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt index 4af6cb07e4..b26e18cffb 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt @@ -45,6 +45,7 @@ interface NodeConfiguration : NodeSSLConfiguration { val detectPublicIp: Boolean get() = true val sshd: SSHDConfiguration? val database: DatabaseConfig + val noLocalShell: Boolean get() = false val transactionCacheSizeBytes: Long get() = defaultTransactionCacheSize val attachmentContentCacheSizeBytes: Long get() = defaultAttachmentContentCacheSize val attachmentCacheBound: Long get() = defaultAttachmentCacheBound @@ -69,6 +70,10 @@ fun NodeConfiguration.shouldCheckCheckpoints(): Boolean { return this.devMode && this.devModeOptions?.disableCheckpointChecker != true } +fun NodeConfiguration.shouldStartSSHDaemon() = this.sshd != null +fun NodeConfiguration.shouldStartLocalShell() = !this.noLocalShell && System.console() != null && this.devMode +fun NodeConfiguration.shouldInitCrashShell() = shouldStartLocalShell() || shouldStartSSHDaemon() + data class NotaryConfig(val validating: Boolean, val raft: RaftConfig? = null, val bftSMaRt: BFTSMaRtConfiguration? = null, @@ -128,6 +133,7 @@ data class NodeConfigurationImpl( override val notary: NotaryConfig?, override val certificateChainCheckPolicies: List, override val devMode: Boolean = false, + override val noLocalShell: Boolean = false, override val devModeOptions: DevModeOptions? = null, override val useTestClock: Boolean = false, override val detectPublicIp: Boolean = true, diff --git a/node/src/test/kotlin/net/corda/node/services/config/NodeConfigurationImplTest.kt b/node/src/test/kotlin/net/corda/node/services/config/NodeConfigurationImplTest.kt index ab9958f73c..21899cce86 100644 --- a/node/src/test/kotlin/net/corda/node/services/config/NodeConfigurationImplTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/config/NodeConfigurationImplTest.kt @@ -29,6 +29,18 @@ class NodeConfigurationImplTest { assertFalse { configDebugOptions(true, DevModeOptions(true)).shouldCheckCheckpoints() } } + @Test + fun `check crashShell flags helper`() { + assertFalse { testConfiguration.copy(sshd = null).shouldStartSSHDaemon() } + assertTrue { testConfiguration.copy(sshd = SSHDConfiguration(1234)).shouldStartSSHDaemon() } + assertFalse { testConfiguration.copy(noLocalShell = true).shouldStartLocalShell() } + assertFalse { testConfiguration.copy(noLocalShell = false, devMode = false).shouldStartLocalShell() } + assertFalse { testConfiguration.copy(noLocalShell = false, devMode = true).shouldStartLocalShell() } + assertFalse { testConfiguration.copy(noLocalShell = true).shouldInitCrashShell() } + assertFalse { testConfiguration.copy(sshd = null).shouldInitCrashShell() } + assertFalse { testConfiguration.copy(noLocalShell = true, sshd = null).shouldInitCrashShell() } + } + private fun configDebugOptions(devMode: Boolean, devModeOptions: DevModeOptions?): NodeConfiguration { return testConfiguration.copy(devMode = devMode, devModeOptions = devModeOptions) } @@ -63,6 +75,7 @@ class NodeConfigurationImplTest { notary = null, certificateChainCheckPolicies = emptyList(), devMode = true, + noLocalShell = false, activeMQServer = ActiveMqServerConfiguration(BridgeConfiguration(0, 0, 0.0)), rpcSettings = rpcSettings )