mirror of
https://github.com/corda/corda.git
synced 2024-12-24 07:06:44 +00:00
CORDA-3028: Add Node Diagnostics Info RPC Call (#5271)
* CORDA-3028: Add Node Diagnostics Info RPC Call - Initial commit * CORDA-3028: Add Node Diagnostics Info RPC Call - Changes after code review * CORDA-3028: Add Node Diagnostics Info RPC Call - Additional code review update and documentation * CORDA-3028: Add Node Diagnostics Info RPC Call - Additional changes to documentation * CORDA-3028: Add Node Diagnostics Info RPC Call - Another change to documentation * CORDA-3028: Add Node Diagnostics Info RPC Call - More changes to documentation * CORDA-3028: Add Node Diagnostics Info RPC Call - Comment change
This commit is contained in:
parent
6d3a6a3998
commit
933330bc4c
15
core/src/main/kotlin/net/corda/core/cordapp/CordappInfo.kt
Normal file
15
core/src/main/kotlin/net/corda/core/cordapp/CordappInfo.kt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package net.corda.core.cordapp
|
||||||
|
|
||||||
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
data class CordappInfo(val type: String,
|
||||||
|
val name: String,
|
||||||
|
val shortName: String,
|
||||||
|
val minimumPlatformVersion: Int,
|
||||||
|
val targetPlatformVersion: Int,
|
||||||
|
val version: String,
|
||||||
|
val vendor: String,
|
||||||
|
val licence: String,
|
||||||
|
val jarHash: SecureHash.SHA256)
|
@ -12,6 +12,7 @@ import net.corda.core.identity.AbstractParty
|
|||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.NetworkParameters
|
import net.corda.core.node.NetworkParameters
|
||||||
|
import net.corda.core.node.NodeDiagnosticInfo
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.services.AttachmentId
|
import net.corda.core.node.services.AttachmentId
|
||||||
import net.corda.core.node.services.NetworkMapCache
|
import net.corda.core.node.services.NetworkMapCache
|
||||||
@ -280,6 +281,11 @@ interface CordaRPCOps : RPCOps {
|
|||||||
/** Returns Node's NodeInfo, assuming this will not change while the node is running. */
|
/** Returns Node's NodeInfo, assuming this will not change while the node is running. */
|
||||||
fun nodeInfo(): NodeInfo
|
fun nodeInfo(): NodeInfo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns Node's NodeDiagnosticInfo, including the version details as well as the information about installed CorDapps.
|
||||||
|
*/
|
||||||
|
fun nodeDiagnosticInfo(): NodeDiagnosticInfo
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns network's notary identities, assuming this will not change while the node is running.
|
* Returns network's notary identities, assuming this will not change while the node is running.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.corda.core.node
|
||||||
|
|
||||||
|
import net.corda.core.cordapp.CordappInfo
|
||||||
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
|
||||||
|
@CordaSerializable
|
||||||
|
data class NodeDiagnosticInfo(val version: String,
|
||||||
|
val revision: String,
|
||||||
|
val platformVersion: Int,
|
||||||
|
val vendor: String,
|
||||||
|
val cordapps: List<CordappInfo>)
|
@ -17,8 +17,10 @@ The key RPC operations exposed by the node are:
|
|||||||
* Start one of the node's registered flows
|
* Start one of the node's registered flows
|
||||||
* ``CordaRPCOps.startTrackedFlowDynamic``
|
* ``CordaRPCOps.startTrackedFlowDynamic``
|
||||||
* As above, but also returns a progress handle for the flow
|
* As above, but also returns a progress handle for the flow
|
||||||
|
* ``CordaRPCOps.nodeDiagnosticInfo``
|
||||||
|
* Returns diagnostic information about the node, including the version and CorDapp details
|
||||||
* ``CordaRPCOps.nodeInfo``
|
* ``CordaRPCOps.nodeInfo``
|
||||||
* Returns information about the node
|
* Returns the network map entry of the node, including its address and identity details as well as the platform version information
|
||||||
* ``CordaRPCOps.currentNodeTime``
|
* ``CordaRPCOps.currentNodeTime``
|
||||||
* Returns the current time according to the node's clock
|
* Returns the current time according to the node's clock
|
||||||
* ``CordaRPCOps.partyFromKey/CordaRPCOps.wellKnownPartyFromX500Name``
|
* ``CordaRPCOps.partyFromKey/CordaRPCOps.wellKnownPartyFromX500Name``
|
||||||
|
@ -242,3 +242,40 @@ If the above holds, Corda components will benefit from the following:
|
|||||||
* A timely recovery from deletion or corruption of configuration files (e.g., ``node.conf``, ``node-info`` files, etc.), database drivers, CorDapps binaries and configuration, and certificate directories, provided backups are available to restore from.
|
* A timely recovery from deletion or corruption of configuration files (e.g., ``node.conf``, ``node-info`` files, etc.), database drivers, CorDapps binaries and configuration, and certificate directories, provided backups are available to restore from.
|
||||||
|
|
||||||
.. warning:: Private keys used to sign transactions should be preserved with the utmost care. The recommendation is to keep at least two separate copies on a storage not connected to the Internet.
|
.. warning:: Private keys used to sign transactions should be preserved with the utmost care. The recommendation is to keep at least two separate copies on a storage not connected to the Internet.
|
||||||
|
|
||||||
|
Checking node version and installed CorDapps
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
A ``nodeDiagnosticInfo`` RPC call can be made to obtain version information about the Corda platform running on the node. The returned ``NodeDiagnosticInfo`` object also includes information about the CorDapps installed on the node.
|
||||||
|
The RPC call is also available as the ``run nodeDiagnosticInfo`` command executable from the Corda shell that can be accessed via the local terminal, SSH, or as the standalone shell.
|
||||||
|
|
||||||
|
Example
|
||||||
|
+++++++
|
||||||
|
|
||||||
|
Here is a sample output displayed by the ``run nodeDiagnosticInfo`` command executed from the Corda shell:
|
||||||
|
|
||||||
|
.. code-block:: none
|
||||||
|
|
||||||
|
version: "|corda_version|"
|
||||||
|
revision: "d7e4a0050049be357999f57f69d8bca41a2b8274"
|
||||||
|
platformVersion: 4
|
||||||
|
vendor: "Corda Open Source"
|
||||||
|
cordapps:
|
||||||
|
- type: "Contract CorDapp"
|
||||||
|
name: "corda-finance-contracts-|corda_version|"
|
||||||
|
shortName: "Corda Finance Demo"
|
||||||
|
minimumPlatformVersion: 1
|
||||||
|
targetPlatformVersion: 4
|
||||||
|
version: "1"
|
||||||
|
vendor: "R3"
|
||||||
|
licence: "Open Source (Apache 2)"
|
||||||
|
jarHash: "570EEB9DF4B43680586F3BE663F9C5844518BC2E410EAF9904E8DEE930B7E45C"
|
||||||
|
- type: "Workflow CorDapp"
|
||||||
|
name: "corda-finance-workflows-|corda_version|"
|
||||||
|
shortName: "Corda Finance Demo"
|
||||||
|
minimumPlatformVersion: 1
|
||||||
|
targetPlatformVersion: 4
|
||||||
|
version: "1"
|
||||||
|
vendor: "R3"
|
||||||
|
licence: "Open Source (Apache 2)"
|
||||||
|
jarHash: "6EA4E0B36010F1DD27B5677F3686B4713BA40C316804A4188DCA20F477FDB23F"
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package net.corda.node
|
||||||
|
|
||||||
|
import net.corda.core.internal.PLATFORM_VERSION
|
||||||
|
import net.corda.testing.driver.DriverParameters
|
||||||
|
import net.corda.testing.driver.driver
|
||||||
|
import net.corda.testing.node.internal.FINANCE_CONTRACTS_CORDAPP
|
||||||
|
import net.corda.testing.node.internal.FINANCE_WORKFLOWS_CORDAPP
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class NodeRPCTests {
|
||||||
|
private val CORDA_VERSION_REGEX = "\\d+(\\.\\d+)?(-\\w+)?".toRegex() // e.g. "5.0-SNAPSHOT"
|
||||||
|
private val CORDA_VENDOR = "Corda Open Source"
|
||||||
|
private val CORDAPPS = listOf(FINANCE_CONTRACTS_CORDAPP, FINANCE_WORKFLOWS_CORDAPP)
|
||||||
|
private val CORDAPP_TYPES = setOf("Contract CorDapp", "Workflow CorDapp")
|
||||||
|
private val CORDAPP_CONTRACTS_NAME_REGEX = "corda-finance-contracts-$CORDA_VERSION_REGEX".toRegex()
|
||||||
|
private val CORDAPP_WORKFLOWS_NAME_REGEX = "corda-finance-workflows-$CORDA_VERSION_REGEX".toRegex()
|
||||||
|
private val CORDAPP_SHORT_NAME = "Corda Finance Demo"
|
||||||
|
private val CORDAPP_VENDOR = "R3"
|
||||||
|
private val CORDAPP_LICENCE = "Open Source (Apache 2)"
|
||||||
|
private val HEXADECIMAL_REGEX = "[0-9a-fA-F]+".toRegex()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `run nodeDiagnosticInfo`() {
|
||||||
|
driver(DriverParameters(notarySpecs = emptyList(), cordappsForAllNodes = CORDAPPS)) {
|
||||||
|
val nodeDiagnosticInfo = startNode().get().rpc.nodeDiagnosticInfo()
|
||||||
|
assertTrue(nodeDiagnosticInfo.version.matches(CORDA_VERSION_REGEX))
|
||||||
|
assertTrue(nodeDiagnosticInfo.revision.matches(HEXADECIMAL_REGEX))
|
||||||
|
assertEquals(PLATFORM_VERSION, nodeDiagnosticInfo.platformVersion)
|
||||||
|
assertEquals(CORDA_VENDOR, nodeDiagnosticInfo.vendor)
|
||||||
|
assertEquals(CORDAPPS.size, nodeDiagnosticInfo.cordapps.size)
|
||||||
|
assertEquals(CORDAPP_TYPES, nodeDiagnosticInfo.cordapps.map { it.type }.toSet())
|
||||||
|
assertTrue(nodeDiagnosticInfo.cordapps.any { it.name.matches(CORDAPP_CONTRACTS_NAME_REGEX) })
|
||||||
|
assertTrue(nodeDiagnosticInfo.cordapps.any { it.name.matches(CORDAPP_WORKFLOWS_NAME_REGEX) })
|
||||||
|
val cordappInfo = nodeDiagnosticInfo.cordapps.first()
|
||||||
|
assertEquals(CORDAPP_SHORT_NAME, cordappInfo.shortName)
|
||||||
|
assertTrue(cordappInfo.version.all { it.isDigit() })
|
||||||
|
assertEquals(CORDAPP_VENDOR, cordappInfo.vendor)
|
||||||
|
assertEquals(CORDAPP_LICENCE, cordappInfo.licence)
|
||||||
|
assertTrue(cordappInfo.minimumPlatformVersion <= PLATFORM_VERSION)
|
||||||
|
assertTrue(cordappInfo.targetPlatformVersion <= PLATFORM_VERSION)
|
||||||
|
assertTrue(cordappInfo.jarHash.toString().matches(HEXADECIMAL_REGEX))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,14 @@
|
|||||||
package net.corda.node.internal
|
package net.corda.node.internal
|
||||||
|
|
||||||
import net.corda.client.rpc.notUsed
|
import net.corda.client.rpc.notUsed
|
||||||
|
import net.corda.common.logging.CordaVersion
|
||||||
import net.corda.core.CordaRuntimeException
|
import net.corda.core.CordaRuntimeException
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.context.InvocationContext
|
import net.corda.core.context.InvocationContext
|
||||||
import net.corda.core.context.InvocationOrigin
|
import net.corda.core.context.InvocationOrigin
|
||||||
import net.corda.core.contracts.ContractState
|
import net.corda.core.contracts.ContractState
|
||||||
|
import net.corda.core.cordapp.Cordapp
|
||||||
|
import net.corda.core.cordapp.CordappInfo
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.FlowInitiator
|
import net.corda.core.flows.FlowInitiator
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
@ -21,6 +24,7 @@ import net.corda.core.internal.messaging.InternalCordaRPCOps
|
|||||||
import net.corda.core.internal.sign
|
import net.corda.core.internal.sign
|
||||||
import net.corda.core.messaging.*
|
import net.corda.core.messaging.*
|
||||||
import net.corda.core.node.NetworkParameters
|
import net.corda.core.node.NetworkParameters
|
||||||
|
import net.corda.core.node.NodeDiagnosticInfo
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.services.AttachmentId
|
import net.corda.core.node.services.AttachmentId
|
||||||
import net.corda.core.node.services.NetworkMapCache
|
import net.corda.core.node.services.NetworkMapCache
|
||||||
@ -165,6 +169,32 @@ internal class CordaRPCOpsImpl(
|
|||||||
return services.myInfo
|
return services.myInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun nodeDiagnosticInfo(): NodeDiagnosticInfo {
|
||||||
|
return NodeDiagnosticInfo(
|
||||||
|
version = CordaVersion.releaseVersion,
|
||||||
|
revision = CordaVersion.revision,
|
||||||
|
platformVersion = CordaVersion.platformVersion,
|
||||||
|
vendor = CordaVersion.vendor,
|
||||||
|
cordapps = services.cordappProvider.cordapps
|
||||||
|
.filter { !it.jarPath.toString().endsWith("corda-core-${CordaVersion.releaseVersion}.jar") }
|
||||||
|
.map { CordappInfo(
|
||||||
|
type = when (it.info) {
|
||||||
|
is Cordapp.Info.Contract -> "Contract CorDapp"
|
||||||
|
is Cordapp.Info.Workflow -> "Workflow CorDapp"
|
||||||
|
else -> "CorDapp"
|
||||||
|
},
|
||||||
|
name = it.name,
|
||||||
|
shortName = it.info.shortName,
|
||||||
|
minimumPlatformVersion = it.minimumPlatformVersion,
|
||||||
|
targetPlatformVersion = it.targetPlatformVersion,
|
||||||
|
version = it.info.version,
|
||||||
|
vendor = it.info.vendor,
|
||||||
|
licence = it.info.licence,
|
||||||
|
jarHash = it.jarHash)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun notaryIdentities(): List<Party> {
|
override fun notaryIdentities(): List<Party> {
|
||||||
return services.networkMapCache.notaryIdentities
|
return services.networkMapCache.notaryIdentities
|
||||||
}
|
}
|
||||||
@ -373,4 +403,4 @@ internal class CordaRPCOpsImpl(
|
|||||||
private inline fun <reified TARGET> Class<*>.checkIsA() {
|
private inline fun <reified TARGET> Class<*>.checkIsA() {
|
||||||
require(TARGET::class.java.isAssignableFrom(this)) { "$name is not a ${TARGET::class.java.name}" }
|
require(TARGET::class.java.isAssignableFrom(this)) { "$name is not a ${TARGET::class.java.name}" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user