mirror of
https://github.com/corda/corda.git
synced 2025-01-18 02:39:51 +00:00
CORDA-2506: Better handling of invalid log path (#4895)
Test if we have access to the logging path (baseDirectory/logs) before attempting to write to them. This allows us to shut down gracefully with an easily understandable error message. Without doing this, the log4j2 will attempt to access the logPath when it first uses the logger in the call() function.
This commit is contained in:
parent
03967742e4
commit
82c45c6f83
@ -1,10 +1,12 @@
|
|||||||
package net.corda.node.internal
|
package net.corda.node.internal
|
||||||
|
|
||||||
import io.netty.channel.unix.Errors
|
import io.netty.channel.unix.Errors
|
||||||
|
import net.corda.cliutils.printError
|
||||||
import net.corda.cliutils.CliWrapperBase
|
import net.corda.cliutils.CliWrapperBase
|
||||||
import net.corda.cliutils.CordaCliWrapper
|
import net.corda.cliutils.CordaCliWrapper
|
||||||
import net.corda.cliutils.CordaVersionProvider
|
import net.corda.cliutils.CordaVersionProvider
|
||||||
import net.corda.cliutils.ExitCodes
|
import net.corda.cliutils.ExitCodes
|
||||||
|
import net.corda.cliutils.ShellConstants
|
||||||
import net.corda.core.contracts.HashAttachmentConstraint
|
import net.corda.core.contracts.HashAttachmentConstraint
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
@ -53,7 +55,7 @@ abstract class NodeCliCommand(alias: String, description: String, val startup: N
|
|||||||
const val LOGS_DIRECTORY_NAME = "logs"
|
const val LOGS_DIRECTORY_NAME = "logs"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initLogging() = this.initLogging(cmdLineOptions.baseDirectory)
|
override fun initLogging(): Boolean = this.initLogging(cmdLineOptions.baseDirectory)
|
||||||
|
|
||||||
@Mixin
|
@Mixin
|
||||||
val cmdLineOptions = SharedNodeCmdLineOptions()
|
val cmdLineOptions = SharedNodeCmdLineOptions()
|
||||||
@ -71,7 +73,7 @@ open class NodeStartupCli : CordaCliWrapper("corda", "Runs a Corda Node") {
|
|||||||
private val initialRegistrationCli by lazy { InitialRegistrationCli(startup) }
|
private val initialRegistrationCli by lazy { InitialRegistrationCli(startup) }
|
||||||
private val validateConfigurationCli by lazy { ValidateConfigurationCli() }
|
private val validateConfigurationCli by lazy { ValidateConfigurationCli() }
|
||||||
|
|
||||||
override fun initLogging() = this.initLogging(cmdLineOptions.baseDirectory)
|
override fun initLogging(): Boolean = this.initLogging(cmdLineOptions.baseDirectory)
|
||||||
|
|
||||||
override fun additionalSubCommands() = setOf(networkCacheCli, justGenerateNodeInfoCli, justGenerateRpcSslCertsCli, initialRegistrationCli, validateConfigurationCli)
|
override fun additionalSubCommands() = setOf(networkCacheCli, justGenerateNodeInfoCli, justGenerateRpcSslCertsCli, initialRegistrationCli, validateConfigurationCli)
|
||||||
|
|
||||||
@ -437,14 +439,32 @@ interface NodeStartupLogging {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CliWrapperBase.initLogging(baseDirectory: Path) {
|
fun CliWrapperBase.initLogging(baseDirectory: Path): Boolean {
|
||||||
System.setProperty("defaultLogLevel", specifiedLogLevel) // These properties are referenced from the XML config file.
|
System.setProperty("defaultLogLevel", specifiedLogLevel) // These properties are referenced from the XML config file.
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
System.setProperty("consoleLoggingEnabled", "true")
|
System.setProperty("consoleLoggingEnabled", "true")
|
||||||
System.setProperty("consoleLogLevel", specifiedLogLevel)
|
System.setProperty("consoleLogLevel", specifiedLogLevel)
|
||||||
Node.renderBasicInfoToConsole = false
|
Node.renderBasicInfoToConsole = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Test for access to the logging path and shutdown if we are unable to reach it.
|
||||||
|
val logPath = baseDirectory / NodeCliCommand.LOGS_DIRECTORY_NAME
|
||||||
|
try {
|
||||||
|
logPath.createDirectories()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
printError("Unable to create logging directory ${logPath.toString()}. Node will now shutdown.")
|
||||||
|
return false
|
||||||
|
} catch (e: SecurityException) {
|
||||||
|
printError("Current user is unable to access logging directory ${logPath.toString()}. Node will now shutdown.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!logPath.isDirectory()) {
|
||||||
|
printError("Unable to access logging directory ${logPath.toString()}. Node will now shutdown.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
System.setProperty("log-path", (baseDirectory / NodeCliCommand.LOGS_DIRECTORY_NAME).toString())
|
System.setProperty("log-path", (baseDirectory / NodeCliCommand.LOGS_DIRECTORY_NAME).toString())
|
||||||
SLF4JBridgeHandler.removeHandlersForRootLogger() // The default j.u.l config adds a ConsoleHandler.
|
SLF4JBridgeHandler.removeHandlersForRootLogger() // The default j.u.l config adds a ConsoleHandler.
|
||||||
SLF4JBridgeHandler.install()
|
SLF4JBridgeHandler.install()
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ class InitialRegistrationCli(val startup: NodeStartup): CliWrapperBase("initial-
|
|||||||
return startup.initialiseAndRun(cmdLineOptions, InitialRegistration(cmdLineOptions.baseDirectory, networkRootTrustStorePath, networkRootTrustStorePassword, startup))
|
return startup.initialiseAndRun(cmdLineOptions, InitialRegistration(cmdLineOptions.baseDirectory, networkRootTrustStorePath, networkRootTrustStorePassword, startup))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initLogging() = this.initLogging(cmdLineOptions.baseDirectory)
|
override fun initLogging(): Boolean = this.initLogging(cmdLineOptions.baseDirectory)
|
||||||
|
|
||||||
@Mixin
|
@Mixin
|
||||||
val cmdLineOptions = InitialRegistrationCmdLineOptions()
|
val cmdLineOptions = InitialRegistrationCmdLineOptions()
|
||||||
|
@ -32,7 +32,7 @@ internal class ValidateConfigurationCli : CliWrapperBase("validate-configuration
|
|||||||
@Mixin
|
@Mixin
|
||||||
private val cmdLineOptions = SharedNodeCmdLineOptions()
|
private val cmdLineOptions = SharedNodeCmdLineOptions()
|
||||||
|
|
||||||
override fun initLogging() = initLogging(cmdLineOptions.baseDirectory)
|
override fun initLogging(): Boolean = initLogging(cmdLineOptions.baseDirectory)
|
||||||
|
|
||||||
override fun runProgram(): Int {
|
override fun runProgram(): Int {
|
||||||
val rawConfig = cmdLineOptions.rawConfiguration().doOnErrors(cmdLineOptions::logRawConfigurationErrors).optional ?: return ExitCodes.FAILURE
|
val rawConfig = cmdLineOptions.rawConfiguration().doOnErrors(cmdLineOptions::logRawConfigurationErrors).optional ?: return ExitCodes.FAILURE
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.cliutils
|
package net.corda.cliutils
|
||||||
|
|
||||||
|
import net.corda.cliutils.ExitCodes
|
||||||
import net.corda.core.internal.rootMessage
|
import net.corda.core.internal.rootMessage
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import org.fusesource.jansi.AnsiConsole
|
import org.fusesource.jansi.AnsiConsole
|
||||||
@ -123,12 +124,13 @@ abstract class CliWrapperBase(val alias: String, val description: String) : Call
|
|||||||
|
|
||||||
// This needs to be called before loggers (See: NodeStartup.kt:51 logger called by lazy, initLogging happens before).
|
// This needs to be called before loggers (See: NodeStartup.kt:51 logger called by lazy, initLogging happens before).
|
||||||
// Node's logging is more rich. In corda configurations two properties, defaultLoggingLevel and consoleLogLevel, are usually used.
|
// Node's logging is more rich. In corda configurations two properties, defaultLoggingLevel and consoleLogLevel, are usually used.
|
||||||
open fun initLogging() {
|
open fun initLogging(): Boolean {
|
||||||
System.setProperty("defaultLogLevel", specifiedLogLevel) // These properties are referenced from the XML config file.
|
System.setProperty("defaultLogLevel", specifiedLogLevel) // These properties are referenced from the XML config file.
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
System.setProperty("consoleLogLevel", specifiedLogLevel)
|
System.setProperty("consoleLogLevel", specifiedLogLevel)
|
||||||
}
|
}
|
||||||
System.setProperty("log-path", Paths.get(".").toString())
|
System.setProperty("log-path", Paths.get(".").toString())
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override this function with the actual method to be run once all the arguments have been parsed. The return number
|
// Override this function with the actual method to be run once all the arguments have been parsed. The return number
|
||||||
@ -141,7 +143,9 @@ abstract class CliWrapperBase(val alias: String, val description: String) : Call
|
|||||||
return runProgram()
|
return runProgram()
|
||||||
}
|
}
|
||||||
|
|
||||||
val specifiedLogLevel: String by lazy { System.getProperty("log4j2.level")?.toLowerCase(Locale.ENGLISH) ?: loggingLevel.name.toLowerCase(Locale.ENGLISH) }
|
val specifiedLogLevel: String by lazy {
|
||||||
|
System.getProperty("log4j2.level")?.toLowerCase(Locale.ENGLISH) ?: loggingLevel.name.toLowerCase(Locale.ENGLISH)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -178,20 +182,20 @@ abstract class CordaCliWrapper(alias: String, description: String) : CliWrapperB
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun call(): Int {
|
override fun call(): Int {
|
||||||
initLogging()
|
if (!initLogging()) {
|
||||||
|
return ExitCodes.FAILURE
|
||||||
|
}
|
||||||
logger.info("Application Args: ${args.joinToString(" ")}")
|
logger.info("Application Args: ${args.joinToString(" ")}")
|
||||||
installShellExtensionsParser.updateShellExtensions()
|
installShellExtensionsParser.updateShellExtensions()
|
||||||
return runProgram()
|
return runProgram()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun printHelp() = cmd.usage(System.out)
|
fun printHelp() = cmd.usage(System.out)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun printWarning(message: String) = System.err.println("${ShellConstants.YELLOW}$message${ShellConstants.RESET}")
|
fun printWarning(message: String) = System.err.println("${ShellConstants.YELLOW}$message${ShellConstants.RESET}")
|
||||||
fun printError(message: String) = System.err.println("${ShellConstants.RED}$message${ShellConstants.RESET}")
|
fun printError(message: String) = System.err.println("${ShellConstants.RED}$message${ShellConstants.RESET}")
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Useful commonly used constants applicable to many CLI tools
|
* Useful commonly used constants applicable to many CLI tools
|
||||||
*/
|
*/
|
||||||
|
@ -56,10 +56,11 @@ class StandaloneShell : CordaCliWrapper("corda-shell", "The Corda standalone she
|
|||||||
|
|
||||||
private fun getManifestEntry(key: String) = if (Manifests.exists(key)) Manifests.read(key) else "Unknown"
|
private fun getManifestEntry(key: String) = if (Manifests.exists(key)) Manifests.read(key) else "Unknown"
|
||||||
|
|
||||||
override fun initLogging() {
|
override fun initLogging() : Boolean {
|
||||||
super.initLogging()
|
super.initLogging()
|
||||||
SLF4JBridgeHandler.removeHandlersForRootLogger() // The default j.u.l config adds a ConsoleHandler.
|
SLF4JBridgeHandler.removeHandlersForRootLogger() // The default j.u.l config adds a ConsoleHandler.
|
||||||
SLF4JBridgeHandler.install()
|
SLF4JBridgeHandler.install()
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun runProgram(): Int {
|
override fun runProgram(): Int {
|
||||||
|
Loading…
Reference in New Issue
Block a user