mirror of
https://github.com/corda/corda.git
synced 2024-12-27 00:21:12 +00:00
Fix ssh for windows (#121)
* Make ssh tunnels work with Pageant on windows and allow specifying explicit ssh remote user * Update comments
This commit is contained in:
parent
f382639ed8
commit
2b217b6eea
@ -7,7 +7,7 @@ the Corda node via RPC.
|
||||
To run up the JMeter UI, using the jmeter.properties in the resources folder,
|
||||
type the following:
|
||||
|
||||
./gradlew tools:jmeter:run
|
||||
`./gradlew tools:jmeter:run`
|
||||
|
||||
You can then open the example script in "Example Flow Properties.jmx" via the File -> Open menu option. You need to
|
||||
configure the host, ports, user name and password in the Java Sampler that correspond to your chosen target Corda node.
|
||||
@ -15,7 +15,7 @@ Simply running from the UI will result in the RPC client running inside the UI J
|
||||
|
||||
If you wish to pass additional arguments to JMeter, you can do this:
|
||||
|
||||
./gradlew tools:jmeter:run -PjmeterArgs="['-n', '-Ljmeter.engine=DEBUG']"
|
||||
`./gradlew tools:jmeter:run -PjmeterArgs="['-n', '-Ljmeter.engine=DEBUG']"`
|
||||
|
||||
The intention is to run against a remote Corda node or nodes, hosted on servers rather than desktops. To
|
||||
this end, we leverage the JMeter ability to run remote agents that actually execute the tests, with these
|
||||
@ -26,7 +26,7 @@ The remote agents then run close to the nodes, so the latency of RPC calls is mi
|
||||
|
||||
A Capsule (http://www.capsule.io) based launchable JAR is created that can be run with the simple command line
|
||||
|
||||
java -jar jmeter-corda-<version>.jar
|
||||
`java -jar jmeter-corda-<version>.jar`
|
||||
|
||||
Embedded in the JAR is all of the corda code for flows and RPC, as well as the jmeter.propeties. This
|
||||
JAR will also include a properties file based on the hostname in the JMeter configuration,
|
||||
@ -34,7 +34,7 @@ so we allocate different SSH tunneled port numbers this way.
|
||||
|
||||
To launch JMeter with the tunnels automatically created:
|
||||
|
||||
./gradlew tools:jmeter:run -PjmeterHosts="['hostname1', 'hostname2']"
|
||||
`./gradlew tools:jmeter:run -PjmeterHosts="['hostname1', 'hostname2']"`
|
||||
|
||||
The list of hostnames should be of at least length one, with a maximum equal to the length of the remote_hosts
|
||||
option in jmeter.properties. We effectively "zip" together the hostnames and that list to build the SSH tunnels.
|
||||
@ -45,4 +45,13 @@ from remote agents.
|
||||
|
||||
The SSH tunnels can be started independently with:
|
||||
|
||||
./gradlew tools:jmeter:runSsh -PjmeterHosts="['hostname1', 'hostname2']"
|
||||
`./gradlew tools:jmeter:runSsh -PjmeterHosts="['hostname1', 'hostname2']"`
|
||||
|
||||
For the ssh tunneling to work, an ssh agent must be running on your local machine with the
|
||||
appropriate private key loaded. If the environment variable `SSH_AUTH_SOCK` is set, the code
|
||||
assumes that a posix sshagent process is being used, if it is not set, it assumes that
|
||||
[Pageant](https://www.ssh.com/ssh/putty/putty-manuals/0.68/Chapter9.html) is in use. If the
|
||||
remote user name is different from the current user name, `-XsshUser <remote user name>`
|
||||
can be used to set this, or in the gradle call:
|
||||
|
||||
`./gradlew tools:jmeter:runSsh -PjmeterHosts="['hostname1', 'hostname2']" -PsshUser="'username'"`
|
||||
|
@ -13,6 +13,7 @@ dependencies {
|
||||
compile group: 'com.jcraft', name: 'jsch.agentproxy.core', version: '0.0.9'
|
||||
compile group: 'com.jcraft', name: 'jsch.agentproxy.sshagent', version: '0.0.9'
|
||||
compile group: 'com.jcraft', name: 'jsch.agentproxy.usocket-jna', version: '0.0.9'
|
||||
compile group: 'com.jcraft', name: 'jsch.agentproxy.pageant', version: '0.0.9'
|
||||
|
||||
// Log4J: logging framework (with SLF4J bindings)
|
||||
compile "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
|
||||
@ -60,8 +61,13 @@ task(runServer, dependsOn: 'classes', type: JavaExec) {
|
||||
task(runSsh, dependsOn: 'classes', type: JavaExec) {
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
main = 'com.r3.corda.jmeter.Ssh'
|
||||
if ( project.hasProperty("sshUser") ){
|
||||
args+= "-XsshUser"
|
||||
args+= Eval.me(sshUser)
|
||||
}
|
||||
if ( project.hasProperty("jmeterHosts") ) {
|
||||
args Eval.me(jmeterHosts)
|
||||
args+= "-Xssh"
|
||||
args+= Eval.me(jmeterHosts)
|
||||
}
|
||||
standardInput = System.in
|
||||
}
|
||||
@ -85,6 +91,10 @@ run {
|
||||
if ( project.hasProperty("jmeterArgs") ) {
|
||||
args+= Eval.me(jmeterHosts)
|
||||
}
|
||||
if ( project.hasProperty("sshUser") ){
|
||||
args+= "-XsshUser"
|
||||
args+= Eval.me(sshUser)
|
||||
}
|
||||
if ( project.hasProperty("jmeterHosts") ) {
|
||||
args+= "-Xssh"
|
||||
args+= Eval.me(jmeterHosts)
|
||||
|
@ -5,6 +5,7 @@ import com.jcraft.jsch.Identity
|
||||
import com.jcraft.jsch.IdentityRepository
|
||||
import com.jcraft.jsch.JSch
|
||||
import com.jcraft.jsch.agentproxy.AgentProxy
|
||||
import com.jcraft.jsch.agentproxy.connector.PageantConnector
|
||||
import com.jcraft.jsch.agentproxy.connector.SSHAgentConnector
|
||||
import com.jcraft.jsch.agentproxy.usocket.JNAUSocketFactory
|
||||
import org.slf4j.LoggerFactory
|
||||
@ -16,7 +17,11 @@ private val log = LoggerFactory.getLogger(Ssh::class.java)
|
||||
* Creates a new [JSch] instance with identities loaded from the running SSH agent.
|
||||
*/
|
||||
fun setupJSchWithSshAgent(): JSch {
|
||||
val connector = SSHAgentConnector(JNAUSocketFactory())
|
||||
val connector =
|
||||
if (System.getenv("SSH_AUTH_SOCK") == null)
|
||||
PageantConnector()
|
||||
else
|
||||
SSHAgentConnector(JNAUSocketFactory())
|
||||
val agentProxy = AgentProxy(connector)
|
||||
val identities = agentProxy.identities
|
||||
require(identities.isNotEmpty()) { "No SSH identities found, please add one to the agent" }
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.r3.corda.jmeter
|
||||
|
||||
import com.sun.javaws.exceptions.InvalidArgumentException
|
||||
import net.corda.core.internal.div
|
||||
import org.apache.jmeter.JMeter
|
||||
import org.slf4j.LoggerFactory
|
||||
@ -54,19 +55,29 @@ class Launcher {
|
||||
}
|
||||
}
|
||||
|
||||
private fun maybeOpenSshTunnels(args: Array<String>): Array<String> {
|
||||
fun maybeOpenSshTunnels(args: Array<String>): Array<String> {
|
||||
// We trim the args at the point "-Xssh" appears in the array of args. Anything after that is a host to
|
||||
// SSH tunnel to.
|
||||
// SSH tunnel to. Also get and remove the "-XsshUser" argument if it appears.
|
||||
var index = 0
|
||||
for (arg in args) {
|
||||
if (arg == "-Xssh") {
|
||||
var userName = System.getProperty("user.name")
|
||||
val returnArgs = mutableListOf<String>()
|
||||
while (index < args.size) {
|
||||
if (args[index] == "-XsshUser") {
|
||||
++index
|
||||
if (index == args.size || args[index].startsWith("-")) {
|
||||
throw InvalidArgumentException(args)
|
||||
}
|
||||
userName = args[index]
|
||||
} else if (args[index] == "-Xssh") {
|
||||
// start ssh
|
||||
Ssh.main(args.copyOfRange(index + 1, args.size), false)
|
||||
return if (index == 0) emptyArray() else args.copyOfRange(0, index)
|
||||
Ssh.createSshTunnels(args.copyOfRange(index + 1, args.size), userName, false)
|
||||
return returnArgs.toTypedArray()
|
||||
} else {
|
||||
returnArgs.add(args[index])
|
||||
}
|
||||
index++
|
||||
}
|
||||
return args
|
||||
return returnArgs.toTypedArray()
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package com.r3.corda.jmeter
|
||||
|
||||
import com.jcraft.jsch.JSch
|
||||
import com.jcraft.jsch.Session
|
||||
import com.sun.javaws.exceptions.InvalidArgumentException
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.nodeapi.internal.addShutdownHook
|
||||
import org.slf4j.LoggerFactory
|
||||
@ -17,9 +18,30 @@ class Ssh {
|
||||
val log = LoggerFactory.getLogger(this::class.java)
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun main(args: Array<String>, wait: Boolean = true) {
|
||||
val userName = System.getProperty("user.name")
|
||||
fun main(args: Array<String>) {
|
||||
// parse the args and call createSshTunnels
|
||||
// the only arguments recognised are "-XsshUser" for the remote user name
|
||||
// and "-Xssh" - everything after this will be treated as a remote host name
|
||||
var userName = System.getProperty("user.name")
|
||||
var index = 0
|
||||
while (index < args.size) {
|
||||
if (args[index] == "-XsshUser") {
|
||||
++index
|
||||
if (index == args.size || args[index].startsWith("-")) {
|
||||
throw InvalidArgumentException(args)
|
||||
}
|
||||
userName = args[index]
|
||||
} else if (args[index] == "-Xssh") {
|
||||
createSshTunnels(args.copyOfRange(index + 1, args.size), userName, true)
|
||||
return
|
||||
}
|
||||
}
|
||||
log.info("Nothing to be done - did you specify hosts to tunnel to with -Xssh?")
|
||||
}
|
||||
|
||||
|
||||
fun createSshTunnels(hosts: Array<String>, userName: String, wait: Boolean) {
|
||||
log.info("User name for ssh: ${userName}")
|
||||
val jsch = setupJSchWithSshAgent()
|
||||
val sessions = mutableListOf<Session>()
|
||||
|
||||
@ -34,7 +56,7 @@ class Ssh {
|
||||
|
||||
// Where JMeter driver will try to connect for remote agents (should all be localhost so can ssh tunnel).
|
||||
val localHostsAndPorts = jmeterProps.getProperty("remote_hosts", "").split(',').map { it.trim() }
|
||||
args.zip(localHostsAndPorts) { remoteHost, localHostAndPortString ->
|
||||
hosts.zip(localHostsAndPorts) { remoteHost, localHostAndPortString ->
|
||||
// Actual remote host and port we will tunnel to.
|
||||
log.info("Creating tunnels for $remoteHost")
|
||||
val localHostAndPort = NetworkHostAndPort.parse(localHostAndPortString)
|
||||
|
Loading…
Reference in New Issue
Block a user