|  | package com.mirantis.mk | 
|  |  | 
|  | /** | 
|  | * | 
|  | * SSH functions | 
|  | * | 
|  | */ | 
|  |  | 
|  | /** | 
|  | * Ensure entry in SSH known hosts | 
|  | * | 
|  | * @param url   url of remote host | 
|  | */ | 
|  | def ensureKnownHosts(url) { | 
|  | def hostArray = getKnownHost(url) | 
|  | sh "test -f ~/.ssh/known_hosts && grep ${hostArray[0]} ~/.ssh/known_hosts || ssh-keyscan -H -p ${hostArray[1]} ${hostArray[0]} >> ~/.ssh/known_hosts" | 
|  | } | 
|  |  | 
|  | @NonCPS | 
|  | def getKnownHost(url){ | 
|  | // test for git@github.com:organization/repository like URLs | 
|  | def p = ~/[a-z0-9\._\-]+@(.+\..+)\:{1}.*/ | 
|  | def result = p.matcher(url) | 
|  | def host = "" | 
|  | if (result.matches()) { | 
|  | host = result.group(1) | 
|  | port = 22 | 
|  | } else { | 
|  | // test for protocol | 
|  | if(url.indexOf("://") == -1){ | 
|  | url="ssh://" + url | 
|  | } | 
|  | parsed = new URI(url) | 
|  | host = parsed.host | 
|  | port = parsed.port && parsed.port > 0 ? parsed.port: 22 | 
|  | } | 
|  | return [host,port] | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Execute command with ssh-agent | 
|  | * | 
|  | * @param cmd   Command to execute | 
|  | * @return STDOUT output | 
|  | */ | 
|  | def runSshAgentCommand(cmd) { | 
|  | // if file exists, then we started ssh-agent | 
|  | if (fileExists("$HOME/.ssh/ssh-agent.sh")) { | 
|  | return sh(script:". ~/.ssh/ssh-agent.sh && ${cmd}", returnStdout:true) | 
|  | } else { | 
|  | // we didn't start ssh-agent in prepareSshAgentKey() because some ssh-agent | 
|  | // is running. Let's re-use already running agent and re-construct | 
|  | //   * SSH_AUTH_SOCK | 
|  | //   * SSH_AGENT_PID | 
|  | return sh(script:""" | 
|  | export SSH_AUTH_SOCK=`find /tmp/ -type s -name agent.\\* 2> /dev/null |  grep '/tmp/ssh-.*/agent.*' | head -n 1` | 
|  | export SSH_AGENT_PID=`echo \${SSH_AUTH_SOCK} | cut -d. -f2` | 
|  | ${cmd} | 
|  | """, returnStdout: true) | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Execute command with ssh-agent (shortcut for runSshAgentCommand) | 
|  | * | 
|  | * @param cmd   Command to execute | 
|  | * @return STDOUT output | 
|  | */ | 
|  | def agentSh(cmd) { | 
|  | return runSshAgentCommand(cmd) | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Execute command with ssh-agent with retries and additional options | 
|  | * | 
|  | * @param address address of remote server | 
|  | * @param cmd command to execute | 
|  | * @param user the name of user to execute ssh command with | 
|  | * @param retries number of command retries in case of failure | 
|  | * @param wait delay between retries | 
|  | * @param options additional ssh options | 
|  |  | 
|  | */ | 
|  | def executeMachineSshCommand(address, cmd, user = 'ubuntu', retries=5, wait=10, options=null){ | 
|  | def common = new com.mirantis.mk.Common() | 
|  | if (!options){ | 
|  | options = ['StrictHostKeyChecking': 'no', 'UserKnownHostsFile': '/dev/null'] | 
|  | } | 
|  | String optionsString = '' | 
|  | options.each { k,v -> | 
|  | optionsString += "-o ${k}=${v} " | 
|  | } | 
|  |  | 
|  | common.retry(retries, wait) { | 
|  | return agentSh("ssh ${optionsString} ${user}@${address} '${cmd}'") | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Setup ssh agent and add private key | 
|  | * | 
|  | * @param credentialsId Jenkins credentials name to lookup private key | 
|  | */ | 
|  | def prepareSshAgentKey(credentialsId) { | 
|  | def common = new com.mirantis.mk.Common() | 
|  | c = common.getSshCredentials(credentialsId) | 
|  | // create ~/.ssh and delete file ssh-agent.sh which can be stale | 
|  | sh('mkdir -p -m 700 ~/.ssh && rm -f ~/.ssh/ssh-agent.sh') | 
|  | sh('pgrep -l -u `id -u` -f ssh-agent\$ >/dev/null || ssh-agent|grep -v "Agent pid" > ~/.ssh/ssh-agent.sh') | 
|  | sh("set +x; echo '${c.getPrivateKey()}' > ~/.ssh/id_rsa_${credentialsId} && chmod 600 ~/.ssh/id_rsa_${credentialsId}; set -x") | 
|  | runSshAgentCommand("ssh-add ~/.ssh/id_rsa_${credentialsId}") | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Copy files via SCP | 
|  | * | 
|  | * @param source source file | 
|  | * @param destination desination file | 
|  | * @param options additional scp options | 
|  |  | 
|  | */ | 
|  | def executeMachineScpCommand(source, destination, options=null){ | 
|  | if (!options){ | 
|  | options = ['StrictHostKeyChecking': 'no', 'UserKnownHostsFile': '/dev/null'] | 
|  | } | 
|  | String optionsString = '' | 
|  | options.each { k,v -> | 
|  | optionsString += "-o ${k}=${v} " | 
|  | } | 
|  |  | 
|  | agentSh("scp ${optionsString} ${source} ${destination}") | 
|  | } | 
|  |  | 
|  |  | 
|  | return this; |